From 416d208cc393d09ec3adaad1c5ec37d6c4d322c2 Mon Sep 17 00:00:00 2001 From: Javier Serrano Polo Date: Tue, 24 Apr 2007 05:36:58 +0000 Subject: [PATCH] removed buffer allocator, automatable object dependencies, deadlocks git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@477 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 117 ++++ Makefile.am | 3 +- configure.in | 4 +- include/audio_device.h | 4 +- include/audio_dummy.h | 6 +- include/automatable_object.h | 413 +------------- include/automatable_object_templates.h | 533 ++++++++++++++++++ include/basic_filters.h | 180 +++--- include/buffer_allocator.h | 84 --- include/envelope_and_lfo_widget.h | 4 +- include/tempo_sync_knob.h | 3 +- .../audio_file_processor.cpp | 5 +- plugins/bit_invader/bit_invader.cpp | 5 +- plugins/kicker/kicker.cpp | 5 +- plugins/ladspa_base/ladspa_control.cpp | 1 + plugins/ladspa_effect/caps/Makefile.am | 2 +- plugins/ladspa_effect/ladspa_effect.cpp | 1 - plugins/ladspa_effect/ladspa_effect.h | 1 + .../ladspa_subplugin_features.cpp | 17 +- plugins/lb302/lb302.cpp | 7 +- plugins/organic/organic.cpp | 5 +- plugins/patman/patman.cpp | 7 +- .../plucked_string_synth.cpp | 5 +- plugins/polyb302/polyb302.cpp | 12 +- plugins/singerbot/singerbot.cpp | 7 +- plugins/stk/mallets/mallets.cpp | 11 +- plugins/stk/mallets/mallets.h | 5 +- plugins/triple_oscillator/artwork.png | Bin 24227 -> 23652 bytes .../triple_oscillator/triple_oscillator.cpp | 25 +- plugins/vestige/vestige.cpp | 5 +- plugins/vibed/vibed.cpp | 5 +- plugins/vibed/vibed.h | 3 +- plugins/vibed/vibrating_string.cpp | 8 +- plugins/vibed/vibrating_string.h | 7 +- plugins/vst_effect/vst_effect.cpp | 6 +- src/audio/audio_alsa.cpp | 19 +- src/audio/audio_device.cpp | 23 +- src/audio/audio_file_device.cpp | 1 - src/audio/audio_file_wave.cpp | 6 +- src/audio/audio_jack.cpp | 6 +- src/audio/audio_oss.cpp | 14 +- src/audio/audio_port.cpp | 13 +- src/audio/audio_sample_recorder.cpp | 17 +- src/audio/audio_sdl.cpp | 11 +- src/core/automation_editor.cpp | 1 + src/core/bb_editor.cpp | 1 + src/core/envelope_and_lfo_widget.cpp | 1 + src/core/envelope_tab_widget.cpp | 193 ++----- src/core/export_project_dialog.cpp | 14 +- src/core/main_window.cpp | 1 - src/core/mixer.cpp | 11 +- src/core/note.cpp | 2 +- src/core/note_play_handle.cpp | 1 + src/core/piano_roll.cpp | 1 + src/core/piano_widget.cpp | 1 + src/core/sample_play_handle.cpp | 6 +- src/core/setup_dialog.cpp | 1 + src/core/song_editor.cpp | 1 + src/core/surround_area.cpp | 1 + src/core/track.cpp | 1 + src/lib/buffer_allocator.cpp | 230 -------- src/lmms_single_source.cpp | 1 - src/tracks/instrument_track.cpp | 1 + src/tracks/pattern.cpp | 5 - src/tracks/sample_track.cpp | 2 + src/widgets/automatable_button.cpp | 3 +- src/widgets/automatable_slider.cpp | 1 + src/widgets/combobox.cpp | 1 + src/widgets/effect_label.cpp | 1 + src/widgets/knob.cpp | 1 + src/widgets/lcd_spinbox.cpp | 1 + src/widgets/led_checkbox.cpp | 1 + src/widgets/pixmap_button.cpp | 1 + src/widgets/rack_plugin.cpp | 1 + src/widgets/tempo_sync_knob.cpp | 6 +- src/widgets/visualization_widget.cpp | 4 +- src/widgets/volume_knob.cpp | 2 + 77 files changed, 1010 insertions(+), 1105 deletions(-) create mode 100644 include/automatable_object_templates.h delete mode 100644 include/buffer_allocator.h delete mode 100644 src/lib/buffer_allocator.cpp diff --git a/ChangeLog b/ChangeLog index 7c011f3dc..bb19360fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,120 @@ +2007-04-24 Javier Serrano Polo + + * include/buffer_allocator.h: + * src/lib/buffer_allocator.cpp: + removed, obsoleted by small audio buffers + + * Makefile.am: + * include/audio_device.h: + * plugins/audio_file_processor/audio_file_processor.cpp: + * plugins/bit_invader/bit_invader.cpp: + * plugins/kicker/kicker.cpp: + * plugins/ladspa_effect/ladspa_effect.cpp: + * plugins/lb302/lb302.cpp: + * plugins/organic/organic.cpp: + * plugins/patman/patman.cpp: + * plugins/plucked_string_synth/plucked_string_synth.cpp: + * plugins/polyb302/polyb302.cpp: + * plugins/singerbot/singerbot.cpp: + * plugins/stk/mallets/mallets.cpp: + * plugins/stk/mallets/mallets.h: + * plugins/triple_oscillator/triple_oscillator.cpp: + * plugins/vestige/vestige.cpp: + * plugins/vibed/vibed.cpp: + * plugins/vibed/vibed.h: + * plugins/vibed/vibrating_string.cpp: + * plugins/vibed/vibrating_string.h: + * plugins/vst_effect/vst_effect.cpp: + * src/lmms_single_source.cpp: + * src/audio/audio_alsa.cpp: + * src/audio/audio_device.cpp: + * src/audio/audio_file_device.cpp: + * src/audio/audio_file_wave.cpp: + * src/audio/audio_jack.cpp: + * src/audio/audio_oss.cpp: + * src/audio/audio_port.cpp: + * src/audio/audio_sample_recorder.cpp: + * src/audio/audio_sdl.cpp: + * src/core/main_window.cpp: + * src/core/mixer.cpp: + * src/core/sample_play_handle.cpp: + * src/tracks/pattern.cpp: + * src/widgets/visualization_widget.cpp: + removed buffer allocator + + * include/automatable_object_templates.h: + initial release, templates extracted from automatable_object.h + + * Makefile.am: + * include/automatable_object.h: + * plugins/ladspa_base/ladspa_control.cpp: + * plugins/ladspa_effect/ladspa_effect.h: + * plugins/patman/patman.cpp: + * plugins/singerbot/singerbot.cpp: + * src/core/automation_editor.cpp: + * src/core/bb_editor.cpp: + * src/core/envelope_and_lfo_widget.cpp: + * src/core/export_project_dialog.cpp: + * src/core/note.cpp: + * src/core/note_play_handle.cpp: + * src/core/piano_roll.cpp: + * src/core/piano_widget.cpp: + * src/core/setup_dialog.cpp: + * src/core/song_editor.cpp: + * src/core/surround_area.cpp: + * src/core/track.cpp: + * src/tracks/instrument_track.cpp: + * src/tracks/sample_track.cpp: + * src/widgets/automatable_button.cpp: + * src/widgets/automatable_slider.cpp: + * src/widgets/combobox.cpp: + * src/widgets/effect_label.cpp: + * src/widgets/knob.cpp: + * src/widgets/lcd_spinbox.cpp: + * src/widgets/led_checkbox.cpp: + * src/widgets/pixmap_button.cpp: + * src/widgets/rack_plugin.cpp: + * src/widgets/tempo_sync_knob.cpp: + * src/widgets/volume_knob.cpp: + reduced dependencies on automatable object + + * src/audio/audio_device.cpp: + * src/core/export_project_dialog.cpp: + * src/core/mixer.cpp: + fixed deadlocks + + * include/audio_dummy.h: + don't process buffers + + * src/audio/audio_sample_recorder.cpp: + fixed high quality + + * include/basic_filters.h: + * include/envelope_and_lfo_widget.h: + * src/core/envelope_tab_widget.cpp: + simplified envelope processing + + * include/basic_filters.h: + - use samplerate member as sample rate + - reformatted + + * plugins/ladspa_effect/ladspa_subplugin_features.cpp: + reverted layout changes in QT3, fixes descriptions + + * plugins/triple_oscillator/artwork.png: + * plugins/triple_oscillator/triple_oscillator.cpp: + updated GUI + + * include/tempo_sync_knob.h: + * src/widgets/tempo_sync_knob.cpp: + graceful shutdown + + * src/widgets/automatable_button.cpp: + fixed undef + + * plugins/ladspa_effect/caps/Makefile.am: + use DESTDIR + 2007-04-21 Javier Serrano Polo * plugins/singerbot/singerbot.cpp: diff --git a/Makefile.am b/Makefile.am index a1972e31a..80244b5ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -172,7 +172,6 @@ lmms_SOURCES = \ $(srcdir)/src/core/surround_area.cpp \ $(srcdir)/src/core/timeline.cpp \ $(srcdir)/src/lib/base64.cpp \ - $(srcdir)/src/lib/buffer_allocator.cpp \ $(srcdir)/src/lib/clipboard.cpp \ $(srcdir)/src/lib/journalling_object.cpp \ $(srcdir)/src/lib/project_journal.cpp \ @@ -309,7 +308,6 @@ lmms_SOURCES = \ $(srcdir)/include/nstate_button.h \ $(srcdir)/include/midi_dummy.h \ $(srcdir)/include/midi_mapper.h \ - $(srcdir)/include/buffer_allocator.h \ $(srcdir)/include/lcd_spinbox.h \ $(srcdir)/include/tooltip.h \ $(srcdir)/include/automatable_button.h \ @@ -336,6 +334,7 @@ lmms_SOURCES = \ $(srcdir)/include/rubberband.h \ $(srcdir)/include/base64.h \ $(srcdir)/include/automatable_object.h \ + $(srcdir)/include/automatable_object_templates.h \ $(srcdir)/include/journalling_object.h \ $(srcdir)/include/level_object.h \ $(srcdir)/include/project_journal.h \ diff --git a/configure.in b/configure.in index 24eec65fd..967515220 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT(lmms, 0.2.1-svn20070421, lmms-devel/at/lists/dot/sf/dot/net) -AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20070421) +AC_INIT(lmms, 0.2.1-svn20070424, lmms-devel/at/lists/dot/sf/dot/net) +AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20070424) AM_CONFIG_HEADER(config.h) diff --git a/include/audio_device.h b/include/audio_device.h index c5e5f9187..1977c754e 100644 --- a/include/audio_device.h +++ b/include/audio_device.h @@ -97,10 +97,11 @@ public: return( m_channels ); } - bool processNextBuffer( void ); + void processNextBuffer( void ); virtual void startProcessing( void ) { + m_in_process = TRUE; } virtual void stopProcessing( void ); @@ -175,6 +176,7 @@ private: sample_rate_t m_sampleRate; ch_cnt_t m_channels; mixer * m_mixer; + bool m_in_process; QMutex m_devMutex; diff --git a/include/audio_dummy.h b/include/audio_dummy.h index d909ef5f0..9e1ca5edc 100644 --- a/include/audio_dummy.h +++ b/include/audio_dummy.h @@ -92,10 +92,14 @@ private: while( TRUE ) { timer.reset(); - if ( !processNextBuffer() ) + const surroundSampleFrame * b = + getMixer()->nextBuffer(); + if( !b ) { break; } + delete[] b; + const Sint32 microseconds = static_cast( getMixer()->framesPerAudioBuffer() * 1000000.0f / getMixer()->sampleRate() - diff --git a/include/automatable_object.h b/include/automatable_object.h index 88e5f809d..c69d126ae 100644 --- a/include/automatable_object.h +++ b/include/automatable_object.h @@ -29,29 +29,24 @@ #include #include "qt3support.h" -#include "automation_editor.h" -#include "automation_pattern.h" -#include "engine.h" #include "journalling_object.h" -#include "templates.h" -#include "midi_time.h" #include "level_object.h" #ifndef QT3 -#include -#include #include #else -#include -#include #include #endif +class automationPattern; +class track; + + template class automatableObject : public journallingObject, public levelObject { @@ -60,32 +55,9 @@ public: automatableObject( track * _track = NULL, const T _val = 0, const T _min = 0, const T _max = 0, - const T _step = defaultRelStep() ) : - m_value( _val ), - m_minValue( _min ), - m_maxValue( _max ), - m_step( _step ), - m_automation_pattern( NULL ), - m_track( _track ), - m_journalEntryReady( FALSE ) - { - m_curLevel = level( _val ); - m_minLevel = level( _min ); - m_maxLevel = level( _max ); - } + const T _step = defaultRelStep() ); - virtual ~automatableObject() - { - if( m_automation_pattern ) - { - delete m_automation_pattern; - } - while( m_linkedObjects.empty() == FALSE ) - { - m_linkedObjects.last()->unlinkObject( this ); - m_linkedObjects.erase( m_linkedObjects.end() - 1 ); - } - } + virtual ~automatableObject(); static inline T minRelStep( void ) { @@ -128,217 +100,32 @@ public: return( m_curLevel ); } - inline T fittedValue( T _value ) - { - _value = tLimit( _value, minValue(), maxValue() ); + inline T fittedValue( T _value ); - if( m_step != 0 ) - { - _value = static_cast( roundf( _value - / (float)step() ) * step() ); - } - else - { - _value = minValue(); - } + virtual void setInitValue( const T _value ); - // correct rounding error at the border - if( tAbs( _value - maxValue() ) < minEps() * - tAbs( step() ) ) - { - _value = maxValue(); - } - - // correct rounding error if value = 0 - if( tAbs( _value ) < minEps() * tAbs( step() ) ) - { - _value = 0; - } - - return( _value ); - } - - inline virtual void setInitValue( const T _value ) - { - bool journalling = testAndSetJournalling( FALSE ); - setValue( _value ); - if( m_automation_pattern ) - { - setFirstValue(); - } - setJournalling( journalling ); - } - - inline virtual void setValue( const T _value ) - { - const T old_val = m_value; - - m_value = fittedValue( _value ); - if( old_val != m_value ) - { - m_curLevel = level( m_value ); - - // add changes to history so user can undo it - addJournalEntry( journalEntry( 0, - static_cast( m_value ) - - static_cast( old_val ) ) ); - - // notify linked objects - - // doesn't work because of implicit typename T - // for( autoObjVector::iterator it = - // m_linkedObjects.begin(); - // it != m_linkedObjects.end(); ++it ) - for( csize i = 0; i < m_linkedObjects.size(); ++i ) - { - autoObj * it = m_linkedObjects[i]; - if( value() != it->value() && - it->fittedValue( value() ) != - it->value() ) - { - bool journalling = - it->testAndSetJournalling( - isJournalling() ); - it->setValue( value() ); - it->setJournalling( journalling ); - } - } - } - } + inline virtual void setValue( const T _value ); inline virtual void incValue( int _steps ) { setValue( m_value + _steps * m_step ); } - inline virtual void setRange( const T _min, const T _max, - const T _step = defaultRelStep() ) - { - m_minValue = _min; - m_maxValue = _max; - if( m_minValue > m_maxValue ) - { - qSwap( m_minValue, m_maxValue ); - } - setStep( _step ); - // re-adjust value - autoObj::setInitValue( value() ); - } + virtual void setRange( const T _min, const T _max, + const T _step = defaultRelStep() ); - inline virtual void setStep( const T _step ) - { - /* - const T intv = maxValue() - minValue(); + inline virtual void setStep( const T _step ); - if( _step == 0 ) - { - m_step = intv * defaultRelStep(); - } - else - { - if( ( intv > 0 ) && ( _step < 0 ) || ( intv < 0 ) && - ( _step > 0 ) ) - { - m_step = -_step; - } - else - { - m_step = _step; - } - if( tAbs( m_step ) < - tAbs( minRelStep() * intv ) ) - { - m_step = minRelStep() * intv; - } - }*/ - m_step = _step; - m_curLevel = level( m_value ); - m_minLevel = level( m_minValue ); - m_maxLevel = level( m_maxValue ); - } + static void linkObjects( autoObj * _object1, autoObj * _object2 ); - static inline void linkObjects( autoObj * _object1, - autoObj * _object2 ) - { - _object1->linkObject( _object2 ); - _object2->linkObject( _object1 ); - - if( _object1->m_automation_pattern - != _object2->m_automation_pattern ) - { - if( _object2->m_automation_pattern ) - { - delete _object2->m_automation_pattern; - } - _object2->m_automation_pattern - = _object1->m_automation_pattern; - } - } - - static void unlinkObjects( autoObj * _object1, - autoObj * _object2 ) - { - _object1->unlinkObject( _object2 ); - _object2->unlinkObject( _object1 ); - - if( _object1->m_automation_pattern - && _object1->m_automation_pattern - == _object2->m_automation_pattern ) - { - _object2->m_automation_pattern = new automationPattern( - *_object1->m_automation_pattern, _object2 ); - } - } + static void unlinkObjects( autoObj * _object1, autoObj * _object2 ); virtual void FASTCALL saveSettings( QDomDocument & _doc, QDomElement & _this, - const QString & _name = "value" ) - { - if( m_automation_pattern ) - { - QDomElement pattern_element; - QDomNode node = _this.namedItem( - automationPattern::classNodeName() ); - if( node.isElement() ) - { - pattern_element = node.toElement(); - } - else - { - pattern_element = _doc.createElement( - automationPattern::classNodeName() ); - _this.appendChild( pattern_element ); - } - QDomElement element = _doc.createElement( _name ); - m_automation_pattern->saveSettings( _doc, element ); - pattern_element.appendChild( element ); - } - else - { - _this.setAttribute( _name, value() ); - } - } + const QString & _name = "value" ); virtual void FASTCALL loadSettings( const QDomElement & _this, - const QString & _name = "value" ) - { - QDomNode node = _this.namedItem( - automationPattern::classNodeName() ); - if( node.isElement() ) - { - node = node.namedItem( _name ); - if( node.isElement() ) - { - m_automation_pattern->loadSettings( - node.toElement() ); - setLevel( m_automation_pattern->valueAt( - midiTime( 0 ) ) ); - return; - } - } - - setInitValue( attributeValue( _this.attribute( _name ) ) ); - } + const QString & _name = "value" ); virtual QString nodeName( void ) const { @@ -355,16 +142,7 @@ public: m_data = _data; } - inline automationPattern * getAutomationPattern( void ) - { - if( !m_automation_pattern ) - { - m_automation_pattern = new automationPattern( m_track, - this ); - syncAutomationPattern(); - } - return( m_automation_pattern ); - } + inline automationPattern * getAutomationPattern( void ); inline bool nullTrack( void ) { @@ -378,67 +156,15 @@ public: protected: - virtual void redoStep( journalEntry & _je ) - { - bool journalling = testAndSetJournalling( FALSE ); -/*#ifndef QT3 - setValue( static_cast( value() + - _je.data().value() ) ); -#else*/ - setValue( static_cast( value() + static_cast( - _je.data().toDouble() ) ) ); -//#endif - setJournalling( journalling ); - } + virtual void redoStep( journalEntry & _je ); - virtual void undoStep( journalEntry & _je ) - { - journalEntry je( _je.actionID(), -/*#ifndef QT3 - -_je.data().value() -#else*/ - static_cast( -_je.data().toDouble() ) -//#endif - ); - redoStep( je ); - } + virtual void undoStep( journalEntry & _je ); - inline void prepareJournalEntryFromOldVal( void ) - { - m_oldValue = value(); - saveJournallingState( FALSE ); - m_journalEntryReady = TRUE; - } + void prepareJournalEntryFromOldVal( void ); - inline void addJournalEntryFromOldToCurVal( void ) - { - if( m_journalEntryReady ) - { - restoreJournallingState(); - if( value() != m_oldValue ) - { - addJournalEntry( journalEntry( 0, value() - - m_oldValue ) ); - } - m_journalEntryReady = FALSE; - } - } + void addJournalEntryFromOldToCurVal( void ); - inline void setFirstValue( void ) - { - if( m_automation_pattern - && m_automation_pattern->updateFirst() ) - { - m_automation_pattern->putValue( midiTime( 0 ), - m_curLevel, FALSE ); - if( engine::getAutomationEditor() && - engine::getAutomationEditor()->currentPattern() - == m_automation_pattern ) - { - engine::getAutomationEditor()->update(); - } - } - } + inline void setFirstValue( void ); private: @@ -459,52 +185,15 @@ private: typedef vvector autoObjVector; autoObjVector m_linkedObjects; - inline void linkObject( autoObj * _object ) - { - if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(), - _object ) == m_linkedObjects.end() ) - { - m_linkedObjects.push_back( _object ); - } - } + inline void linkObject( autoObj * _object ); - inline void unlinkObject( autoObj * _object ) - { - if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(), - _object ) != m_linkedObjects.end() ) - { - m_linkedObjects.erase( qFind( m_linkedObjects.begin(), - m_linkedObjects.end(), - _object ) ); - } - } + inline void unlinkObject( autoObj * _object ); - static T attributeValue( QString _value ); + static inline T attributeValue( QString _value ); - inline void syncAutomationPattern( void ) - { - for( csize i = 0; i < m_linkedObjects.size(); ++i ) - { - autoObj * it = m_linkedObjects[i]; - if( m_automation_pattern != it->m_automation_pattern ) - { - it->m_automation_pattern = m_automation_pattern; - } - } - } + inline void syncAutomationPattern( void ); - void setLevel( int _level ) - { - if( m_curLevel == _level ) - { - return; - } - bool journalling = testAndSetJournalling( FALSE ); - m_automation_pattern->setUpdateFirst( FALSE ); - setValue( _level * m_step ); - m_automation_pattern->setUpdateFirst( TRUE ); - setJournalling( journalling ); - } + inline void setLevel( int _level ); inline int level( T _value ) const { @@ -525,54 +214,6 @@ private: -template<> -inline float automatableObject::minRelStep( void ) -{ - return( 1.0e-10 ); -} - - - -template<> -inline float automatableObject::defaultRelStep( void ) -{ - return( 1.0e-2 ); -} - - -template<> -inline float automatableObject::minEps( void ) -{ - return( 1.0e-10 ); -} - - - -template<> -inline float automatableObject::attributeValue( QString _value ) -{ - return( _value.toFloat() ); -} - - - -template<> -inline int automatableObject::attributeValue( QString _value ) -{ - return( _value.toInt() ); -} - - - -template<> -inline bool automatableObject::attributeValue( - QString _value ) -{ - return( static_cast( _value.toInt() ) ); -} - - - #endif diff --git a/include/automatable_object_templates.h b/include/automatable_object_templates.h new file mode 100644 index 000000000..7853ac26e --- /dev/null +++ b/include/automatable_object_templates.h @@ -0,0 +1,533 @@ +/* + * automatable_object_templates.h - definition of automatableObject templates + * + * Copyright (c) 2006-2007 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef _AUTOMATABLE_OBJECT_TEMPLATES_H +#define _AUTOMATABLE_OBJECT_TEMPLATES_H + + +#include "automatable_object.h" +#include "automation_editor.h" +#include "automation_pattern.h" +#include "engine.h" +#include "templates.h" + +#ifndef QT3 + +#include + +#else + +#include + +#endif + + +template +automatableObject::automatableObject( track * _track, + const T _val, const T _min, + const T _max, const T _step ) : + m_value( _val ), + m_minValue( _min ), + m_maxValue( _max ), + m_step( _step ), + m_automation_pattern( NULL ), + m_track( _track ), + m_journalEntryReady( FALSE ) +{ + m_curLevel = level( _val ); + m_minLevel = level( _min ); + m_maxLevel = level( _max ); +} + + + + +template +automatableObject::~automatableObject() +{ + if( m_automation_pattern ) + { + delete m_automation_pattern; + } + while( m_linkedObjects.empty() == FALSE ) + { + m_linkedObjects.last()->unlinkObject( this ); + m_linkedObjects.erase( m_linkedObjects.end() - 1 ); + } +} + + + + +template +T automatableObject::fittedValue( T _value ) +{ + _value = tLimit( _value, minValue(), maxValue() ); + + if( m_step != 0 ) + { + _value = static_cast( roundf( _value / (float)step() ) + * step() ); + } + else + { + _value = minValue(); + } + + // correct rounding error at the border + if( tAbs( _value - maxValue() ) < minEps() * tAbs( step() ) ) + { + _value = maxValue(); + } + + // correct rounding error if value = 0 + if( tAbs( _value ) < minEps() * tAbs( step() ) ) + { + _value = 0; + } + + return( _value ); +} + + + + +template +void automatableObject::setInitValue( const T _value ) +{ + bool journalling = testAndSetJournalling( FALSE ); + setValue( _value ); + if( m_automation_pattern ) + { + setFirstValue(); + } + setJournalling( journalling ); +} + + + + +template +void automatableObject::setValue( const T _value ) +{ + const T old_val = m_value; + + m_value = fittedValue( _value ); + if( old_val != m_value ) + { + m_curLevel = level( m_value ); + + // add changes to history so user can undo it + addJournalEntry( journalEntry( 0, + static_cast( m_value ) - + static_cast( old_val ) ) ); + + // notify linked objects + + // doesn't work because of implicit typename T + // for( autoObjVector::iterator it = + // m_linkedObjects.begin(); + // it != m_linkedObjects.end(); ++it ) + for( csize i = 0; i < m_linkedObjects.size(); ++i ) + { + autoObj * it = m_linkedObjects[i]; + if( value() != it->value() && it->fittedValue( value() ) + != it->value() ) + { + bool journalling = it->testAndSetJournalling( + isJournalling() ); + it->setValue( value() ); + it->setJournalling( journalling ); + } + } + } +} + + + + +template +void automatableObject::setRange( const T _min, const T _max, + const T _step ) +{ + m_minValue = _min; + m_maxValue = _max; + if( m_minValue > m_maxValue ) + { + qSwap( m_minValue, m_maxValue ); + } + setStep( _step ); + // re-adjust value + autoObj::setInitValue( value() ); +} + + + + +template +void automatableObject::setStep( const T _step ) +{ + /* + const T intv = maxValue() - minValue(); + + if( _step == 0 ) + { + m_step = intv * defaultRelStep(); + } + else + { + if( ( intv > 0 ) && ( _step < 0 ) || ( intv < 0 ) && + ( _step > 0 ) ) + { + m_step = -_step; + } + else + { + m_step = _step; + } + if( tAbs( m_step ) < tAbs( minRelStep() * intv ) ) + { + m_step = minRelStep() * intv; + } + }*/ + m_step = _step; + m_curLevel = level( m_value ); + m_minLevel = level( m_minValue ); + m_maxLevel = level( m_maxValue ); +} + + + + +template +void automatableObject::linkObjects( autoObj * _object1, + autoObj * _object2 ) +{ + _object1->linkObject( _object2 ); + _object2->linkObject( _object1 ); + + if( _object1->m_automation_pattern != _object2->m_automation_pattern ) + { + if( _object2->m_automation_pattern ) + { + delete _object2->m_automation_pattern; + } + _object2->m_automation_pattern = _object1->m_automation_pattern; + } +} + + + + +template +void automatableObject::unlinkObjects( autoObj * _object1, + autoObj * _object2 ) +{ + _object1->unlinkObject( _object2 ); + _object2->unlinkObject( _object1 ); + + if( _object1->m_automation_pattern && _object1->m_automation_pattern + == _object2->m_automation_pattern ) + { + _object2->m_automation_pattern = new automationPattern( + *_object1->m_automation_pattern, _object2 ); + } +} + + + + +template +void automatableObject::saveSettings( QDomDocument & _doc, + QDomElement & _this, + const QString & _name ) +{ + if( m_automation_pattern ) + { + QDomElement pattern_element; + QDomNode node = _this.namedItem( + automationPattern::classNodeName() ); + if( node.isElement() ) + { + pattern_element = node.toElement(); + } + else + { + pattern_element = _doc.createElement( + automationPattern::classNodeName() ); + _this.appendChild( pattern_element ); + } + QDomElement element = _doc.createElement( _name ); + m_automation_pattern->saveSettings( _doc, element ); + pattern_element.appendChild( element ); + } + else + { + _this.setAttribute( _name, value() ); + } +} + + + + +template +void automatableObject::loadSettings( + const QDomElement & _this, + const QString & _name ) +{ + QDomNode node = _this.namedItem( automationPattern::classNodeName() ); + if( node.isElement() ) + { + node = node.namedItem( _name ); + if( node.isElement() ) + { + m_automation_pattern->loadSettings( node.toElement() ); + setLevel( m_automation_pattern->valueAt( + midiTime( 0 ) ) ); + return; + } + } + + setInitValue( attributeValue( _this.attribute( _name ) ) ); +} + + + + +template +automationPattern * automatableObject::getAutomationPattern( + void ) +{ + if( !m_automation_pattern ) + { + m_automation_pattern = new automationPattern( m_track, this ); + syncAutomationPattern(); + } + return( m_automation_pattern ); +} + + + + +template +void automatableObject::redoStep( journalEntry & _je ) +{ + bool journalling = testAndSetJournalling( FALSE ); +/*#ifndef QT3 + setValue( static_cast( value() + + _je.data().value() ) ); +#else*/ + setValue( static_cast( value() + static_cast( + _je.data().toDouble() ) ) ); +//#endif + setJournalling( journalling ); +} + + + + +template +void automatableObject::undoStep( journalEntry & _je ) +{ + journalEntry je( _je.actionID(), +/*#ifndef QT3 + -_je.data().value() +#else*/ + static_cast( -_je.data().toDouble() ) +//#endif + ); + redoStep( je ); +} + + + + +template +void automatableObject::prepareJournalEntryFromOldVal( void ) +{ + m_oldValue = value(); + saveJournallingState( FALSE ); + m_journalEntryReady = TRUE; +} + + + + +template +void automatableObject::addJournalEntryFromOldToCurVal( + void ) +{ + if( m_journalEntryReady ) + { + restoreJournallingState(); + if( value() != m_oldValue ) + { + addJournalEntry( journalEntry( 0, value() - + m_oldValue ) ); + } + m_journalEntryReady = FALSE; + } +} + + + + +template +void automatableObject::setFirstValue( void ) +{ + if( m_automation_pattern && m_automation_pattern->updateFirst() ) + { + m_automation_pattern->putValue( midiTime( 0 ), m_curLevel, + FALSE ); + if( engine::getAutomationEditor() && + engine::getAutomationEditor()->currentPattern() + == m_automation_pattern ) + { + engine::getAutomationEditor()->update(); + } + } +} + + + + +template +void automatableObject::linkObject( autoObj * _object ) +{ + if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(), _object ) + == m_linkedObjects.end() ) + { + m_linkedObjects.push_back( _object ); + } +} + + + + +template +void automatableObject::unlinkObject( autoObj * _object ) +{ + if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(), _object ) + != m_linkedObjects.end() ) + { + m_linkedObjects.erase( qFind( m_linkedObjects.begin(), + m_linkedObjects.end(), + _object ) ); + } +} + + + + +template +void automatableObject::syncAutomationPattern( void ) +{ + for( csize i = 0; i < m_linkedObjects.size(); ++i ) + { + autoObj * it = m_linkedObjects[i]; + if( m_automation_pattern != it->m_automation_pattern ) + { + it->m_automation_pattern = m_automation_pattern; + } + } +} + + + + +template +void automatableObject::setLevel( int _level ) +{ + if( m_curLevel == _level ) + { + return; + } + bool journalling = testAndSetJournalling( FALSE ); + m_automation_pattern->setUpdateFirst( FALSE ); + setValue( _level * m_step ); + m_automation_pattern->setUpdateFirst( TRUE ); + setJournalling( journalling ); +} + + + + +template<> +inline float automatableObject::minRelStep( void ) +{ + return( 1.0e-10 ); +} + + + + +template<> +inline float automatableObject::defaultRelStep( void ) +{ + return( 1.0e-2 ); +} + + + + +template<> +inline float automatableObject::minEps( void ) +{ + return( 1.0e-10 ); +} + + + + +template<> +inline float automatableObject::attributeValue( QString _value ) +{ + return( _value.toFloat() ); +} + + + + +template<> +inline int automatableObject::attributeValue( QString _value ) +{ + return( _value.toInt() ); +} + + + + +template<> +inline bool automatableObject::attributeValue( + QString _value ) +{ + return( static_cast( _value.toInt() ) ); +} + + + + +#endif + diff --git a/include/basic_filters.h b/include/basic_filters.h index a581a70ab..53bca10b9 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -82,7 +82,7 @@ public: m_b2a0( 0.0f ), m_a1a0( 0.0f ), m_a2a0( 0.0f ), - m_sampleRate( 1.0f / _sample_rate ), + m_sampleRate( _sample_rate ), m_subFilter( NULL ) { // reset in/out history @@ -231,13 +231,17 @@ public: return( out ); } - - inline void calcFilterCoeffs( const filterTypes _type, float _freq, - float _q + + void setType( const filterTypes _type ) + { + m_type = _type; + } + + + inline void calcFilterCoeffs( float _freq, float _q /*, const bool _q_is_bandwidth = FALSE*/ ) { // temp coef vars - m_type = _type; _freq = tMax( _freq, 0.01f );// limit freq and q for not getting // bad noise out of the filter... _q = tMax( _q, minQ() ); @@ -250,21 +254,21 @@ public: { m_subFilter = new basicFilters( - static_cast( 1.0f / m_sampleRate ) ); + static_cast( m_sampleRate ) ); + m_subFilter->setType( MOOG ); } - m_subFilter->calcFilterCoeffs( MOOG, _freq, - _q ); + m_subFilter->calcFilterCoeffs( _freq, _q ); } case MOOG: { // [ 0 - 1 ] - const float f = 2 * _freq * m_sampleRate; + const float f = 2 * _freq / m_sampleRate; // (Empirical tunning) - m_k = 3.6f*f - 1.6f*f*f - 1; - m_p = (m_k+1)*0.5f; - m_r = _q*powf( M_E, ( ( 1-m_p ) * 1.386249f ) ); - break; + m_k = 3.6f * f - 1.6f * f * f - 1; + m_p = ( m_k + 1 ) * 0.5f; + m_r = _q * powf( M_E, ( 1 - m_p ) * 1.386249f ); + return; } /* case DOUBLE_MOOG2: @@ -273,7 +277,7 @@ public: { m_subFilter = new basicFilters( - 1.0f / m_sampleRate ); + m_sampleRate ); } m_subFilter->calcFilterCoeffs( MOOG2, _freq, _q ); @@ -281,8 +285,8 @@ public: case MOOG2: { - const float kfc = 2 * _freq * m_sampleRate; - const float kf = _freq * m_sampleRate; + const float kfc = 2 * _freq / m_sampleRate; + const float kf = _freq / m_sampleRate; const float kfcr = 1.8730 * ( kfc*kfc*kfc ) + 0.4955 * ( kfc*kfc ) + 0.6490 * kfc + 0.9988; @@ -295,81 +299,79 @@ public: }*/ default: - { - // other filters - const float omega = F_2PI * _freq * - m_sampleRate; - const float tsin = sinf( omega ); - const float tcos = cosf( omega ); - //float alpha; - - //if (q_is_bandwidth) - //alpha = tsin*sinhf(logf(2.0f)/2.0f*q*omega/ - // tsin); - //else - const float alpha = 0.5f * tsin / _q; - - const float a0 = 1.0f / ( 1.0f + alpha ); - - if( m_type == LOWPASS || - m_type == DOUBLE_LOWPASS ) - { - m_b0a0 = ((1.0f-tcos)*0.5f)*a0; - m_b1a0 = (1.0f-tcos)*a0; - m_b2a0 = m_b0a0;//((1.0f-tcos)/2.0f)*a0; - m_a1a0 = (-2.0f*tcos)*a0; - if( m_type == DOUBLE_LOWPASS ) - { - if( m_subFilter == NULL ) - { - m_subFilter = - new basicFilters( static_cast( - 1.0f / m_sampleRate ) ); - } - m_subFilter->calcFilterCoeffs( - LOWPASS, _freq, _q ); - } - } - else if( m_type == HIPASS ) - { - m_b0a0 = ((1.0f+tcos)*0.5f)*a0; - m_b1a0 = (-1.0f-tcos)*a0; - m_b2a0 = m_b0a0;//((1.0f+tcos)/2.0f)*a0; - m_a1a0 = (-2.0f*tcos)*a0; - } - else if( m_type == BANDPASS_CSG ) - { - m_b0a0 = tsin*0.5f*a0; - m_b1a0 = 0.0f; - m_b2a0 = -tsin*0.5f*a0; - m_a1a0 = (-2.0f*tcos)*a0; - } - else if( m_type == BANDPASS_CZPG ) - { - m_b0a0 = alpha*a0; - m_b1a0 = 0.0f; - m_b2a0 = (-alpha)*a0; - m_a1a0 = (-2.0f*tcos)*a0; - } - else if( m_type == NOTCH ) - { - m_b0a0 = a0; - m_b1a0 = (-2.0f*tcos)*a0; - m_b2a0 = a0; - m_a1a0 = m_b1a0;//(-2.0f*tcos)*a0; - } - else if( m_type == ALLPASS ) - { - m_b0a0 = (1.0f-alpha)*a0; - m_b1a0 = (-2.0f*tcos)*a0; - m_b2a0 = 1.0;//(1.0f+alpha)*a0; - m_a1a0 = m_b1a0;//(-2.0f*tcos)*a0; - //m_a2a0 = m_b0a0;//(1.0f-alpha)*a0; - } - m_a2a0 = (1.0f-alpha)*a0; break; - } } + + // other filters + const float omega = F_2PI * _freq / m_sampleRate; + const float tsin = sinf( omega ); + const float tcos = cosf( omega ); + //float alpha; + + //if (q_is_bandwidth) + //alpha = tsin*sinhf(logf(2.0f)/2.0f*q*omega/ + // tsin); + //else + const float alpha = 0.5f * tsin / _q; + + const float a0 = 1.0f / ( 1.0f + alpha ); + + switch( m_type ) + { + case LOWPASS: + case DOUBLE_LOWPASS: + m_b0a0 = ( 1.0f - tcos ) * 0.5f * a0; + m_b1a0 = ( 1.0f - tcos ) * a0; + m_b2a0 = m_b0a0;//((1.0f-tcos)/2.0f)*a0; + m_a1a0 = -2.0f * tcos * a0; + if( m_type == DOUBLE_LOWPASS ) + { + if( m_subFilter == NULL ) + { + m_subFilter = + new basicFilters( static_cast( + m_sampleRate ) ); + m_subFilter->setType( LOWPASS ); + } + m_subFilter->calcFilterCoeffs( _freq, + _q ); + } + break; + case HIPASS: + m_b0a0 = ( 1.0f + tcos ) * 0.5f * a0; + m_b1a0 = ( -1.0f - tcos ) * a0; + m_b2a0 = m_b0a0;//((1.0f+tcos)/2.0f)*a0; + m_a1a0 = -2.0f * tcos * a0; + break; + case BANDPASS_CSG: + m_b0a0 = tsin * 0.5f * a0; + m_b1a0 = 0.0f; + m_b2a0 = -tsin * 0.5f * a0; + m_a1a0 = -2.0f * tcos * a0; + break; + case BANDPASS_CZPG: + m_b0a0 = alpha * a0; + m_b1a0 = 0.0f; + m_b2a0 = -alpha * a0; + m_a1a0 = -2.0f * tcos * a0; + break; + case NOTCH: + m_b0a0 = a0; + m_b1a0 = -2.0f * tcos * a0; + m_b2a0 = a0; + m_a1a0 = m_b1a0;//(-2.0f*tcos)*a0; + break; + case ALLPASS: + m_b0a0 = ( 1.0f - alpha ) * a0; + m_b1a0 = -2.0f * tcos * a0; + m_b2a0 = 1.0f;//(1.0f+alpha)*a0; + m_a1a0 = m_b1a0;//(-2.0f*tcos)*a0; + //m_a2a0 = m_b0a0;//(1.0f-alpha)*a0; + break; + default: + break; + } + m_a2a0 = ( 1.0f - alpha ) * a0; } diff --git a/include/buffer_allocator.h b/include/buffer_allocator.h deleted file mode 100644 index 51b68218f..000000000 --- a/include/buffer_allocator.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * buffer_allocator.h - namespace bufferAllocator providing routines for own - * optimized memory-management for audio-buffers - * - * Copyright (c) 2005-2006 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - - -#ifndef _BUFFER_ALLOCATOR_H -#define _BUFFER_ALLOCATOR_H - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "types.h" - - - - -namespace bufferAllocator -{ - void * FASTCALL allocBytes( const Uint32 _bytes ); - - template - inline T * FASTCALL alloc( const Uint32 _n ) - { - return( (T *) allocBytes( sizeof( T ) * _n ) ); - } - - // free given buffer - void FASTCALL free( void * _buf ); - - // try to cleanup _level unused buffers - void FASTCALL cleanUp( const Uint16 _level ); - - // disable autocleanup-mechanisms - void FASTCALL disableAutoCleanup( const bool _disabled ); - - - // simple class for automatically freeing buffer in complex functions - template - class autoCleaner - { - public: - autoCleaner( T * _ptr ) : - m_ptr( _ptr ) - { - } - ~autoCleaner() - { - bufferAllocator::free( m_ptr ); - } - inline const T * ptr( void ) const - { - return( m_ptr ); - } - - private: - T * m_ptr; - } ; - -} ; - - -#endif diff --git a/include/envelope_and_lfo_widget.h b/include/envelope_and_lfo_widget.h index 2ff7b889f..c10a974cd 100644 --- a/include/envelope_and_lfo_widget.h +++ b/include/envelope_and_lfo_widget.h @@ -77,9 +77,9 @@ public: track * _track ); virtual ~envelopeAndLFOWidget(); - static inline float expKnobVal( float val ) + static inline float expKnobVal( float _val ) { - return( ( ( val < 0 ) ? -1 : 1 ) * val*val ); + return( ( ( _val < 0 ) ? -_val : _val ) * _val ); } static void triggerLFO( void ); diff --git a/include/tempo_sync_knob.h b/include/tempo_sync_knob.h index 96ee52f73..bb01a7b1c 100644 --- a/include/tempo_sync_knob.h +++ b/include/tempo_sync_knob.h @@ -114,7 +114,8 @@ private: QString m_tempoSyncDescription; tempoSyncMode m_tempoLastSyncMode; - meterDialog * m_custom; + QPointer m_custom; + } ; diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index e003f695a..f3581ab32 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -50,7 +50,6 @@ #include "instrument_track.h" #include "note_play_handle.h" #include "interpolation.h" -#include "buffer_allocator.h" #include "file_browser.h" #include "pixmap_button.h" #include "knob.h" @@ -393,7 +392,7 @@ void audioFileProcessor::setAudioFile( const QString & _audio_file, bool _rename void audioFileProcessor::playNote( notePlayHandle * _n, bool ) { const Uint32 frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; // calculate frequency of note const float note_freq = getInstrumentTrack()->frequency( _n ); @@ -409,7 +408,7 @@ void audioFileProcessor::playNote( notePlayHandle * _n, bool ) { getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); } - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index 544a0bfcd..d24d15815 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -56,7 +56,6 @@ using namespace std; #include "instrument_track.h" #include "note_play_handle.h" #include "templates.h" -#include "buffer_allocator.h" #include "knob.h" #include "pixmap_button.h" #include "tooltip.h" @@ -701,7 +700,7 @@ void bitInvader::playNote( notePlayHandle * _n, bool ) } const fpab_t frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; bSynth * ps = static_cast( _n->m_pluginData ); for( fpab_t frame = 0; frame < frames; ++frame ) @@ -715,7 +714,7 @@ void bitInvader::playNote( notePlayHandle * _n, bool ) getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 5cb055dcf..7c90b4e8d 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -42,7 +42,6 @@ #include "instrument_track.h" #include "note_play_handle.h" #include "sweep_oscillator.h" -#include "buffer_allocator.h" #include "knob.h" #undef SINGLE_SOURCE_COMPILE @@ -201,7 +200,7 @@ void kickerInstrument::playNote( notePlayHandle * _n, bool ) const float f1 = m_startFreqKnob->value() + tfp * fdiff / decfr; const float f2 = m_startFreqKnob->value() + (frames+tfp-1)*fdiff/decfr; - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; sweepOsc * so = static_cast( _n->m_pluginData ); @@ -223,7 +222,7 @@ void kickerInstrument::playNote( notePlayHandle * _n, bool ) getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/ladspa_base/ladspa_control.cpp b/plugins/ladspa_base/ladspa_control.cpp index ae9a47f3c..cc2c9af7f 100644 --- a/plugins/ladspa_base/ladspa_control.cpp +++ b/plugins/ladspa_base/ladspa_control.cpp @@ -37,6 +37,7 @@ #include "ladspa_control.h" +#include "automatable_object_templates.h" #include "ladspa_base.h" #include "tooltip.h" #include "tempo_sync_knob.h" diff --git a/plugins/ladspa_effect/caps/Makefile.am b/plugins/ladspa_effect/caps/Makefile.am index 35b2473fa..1a11b1e11 100644 --- a/plugins/ladspa_effect/caps/Makefile.am +++ b/plugins/ladspa_effect/caps/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 AM_CXXFLAGS := $(AM_CXXFLAGS) -O6 -ffast-math -funroll-loops -ftracer -I../../../include -DEST = $(libdir)/$(PACKAGE)/ladspa +DEST = $(DESTDIR)$(libdir)/$(PACKAGE)/ladspa SOURCES = $(wildcard *.cc) HDRS = $(wildcard *.h) $(wildcard dsp/*.h) OBJECTS = $(SOURCES:.cc=.o) diff --git a/plugins/ladspa_effect/ladspa_effect.cpp b/plugins/ladspa_effect/ladspa_effect.cpp index 45f8d9163..1fc191d22 100644 --- a/plugins/ladspa_effect/ladspa_effect.cpp +++ b/plugins/ladspa_effect/ladspa_effect.cpp @@ -40,7 +40,6 @@ #include "ladspa_effect.h" #include "mixer.h" #include "config_mgr.h" -#include "buffer_allocator.h" #include "audio_device.h" #include "ladspa_control.h" #include "ladspa_subplugin_features.h" diff --git a/plugins/ladspa_effect/ladspa_effect.h b/plugins/ladspa_effect/ladspa_effect.h index db57904fa..18641e082 100644 --- a/plugins/ladspa_effect/ladspa_effect.h +++ b/plugins/ladspa_effect/ladspa_effect.h @@ -32,6 +32,7 @@ #include "qt3support.h" #include "effect.h" +#include "engine.h" #include "ladspa_2_lmms.h" #include "mixer.h" #include "ladspa_control.h" diff --git a/plugins/ladspa_effect/ladspa_subplugin_features.cpp b/plugins/ladspa_effect/ladspa_subplugin_features.cpp index 45d670b90..6c5017d70 100644 --- a/plugins/ladspa_effect/ladspa_subplugin_features.cpp +++ b/plugins/ladspa_effect/ladspa_subplugin_features.cpp @@ -36,7 +36,8 @@ #else -#include +#include +//#include #include #include @@ -67,10 +68,14 @@ void ladspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent, QLabel * label = new QLabel( _parent ); label->setText( QWidget::tr( "Name: " ) + lm->getName( lkey ) ); +#ifndef QT3 QWidget * maker = new QWidget( _parent ); QHBoxLayout * l = new QHBoxLayout( maker ); l->setMargin( 0 ); l->setSpacing( 0 ); +#else + QHBox * maker = new QHBox( _parent ); +#endif QLabel * maker_label = new QLabel( maker ); maker_label->setText( QWidget::tr( "Maker: " ) ); @@ -79,16 +84,21 @@ void ladspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent, maker_content->setText( lm->getMaker( lkey ) ); #ifndef QT3 maker_content->setWordWrap( TRUE ); + l->setStretchFactor( maker_content, 100 ); #else maker_content->setAlignment( Qt::WordBreak ); + maker->setStretchFactor( maker_content, 100 ); #endif - l->setStretchFactor( maker_content, 100 ); +#ifndef QT3 QWidget * copyright = new QWidget( _parent ); l = new QHBoxLayout( copyright ); l->setMargin( 0 ); l->setSpacing( 0 ); +#else + QHBox * copyright = new QHBox( _parent ); +#endif copyright->setMinimumWidth( _parent->minimumWidth() ); QLabel * copyright_label = new QLabel( copyright ); @@ -98,10 +108,11 @@ void ladspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent, copyright_content->setText( lm->getCopyright( lkey ) ); #ifndef QT3 copyright_content->setWordWrap( TRUE ); + l->setStretchFactor( copyright_content, 100 ); #else copyright_content->setAlignment( Qt::WordBreak ); + copyright->setStretchFactor( copyright_content, 100 ); #endif - l->setStretchFactor( copyright_content, 100 ); QLabel * requiresRealTime = new QLabel( _parent ); requiresRealTime->setText( QWidget::tr( "Requires Real Time: " ) + diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 918ea8be4..61ef37cc8 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -46,7 +46,6 @@ #include "instrument_play_handle.h" #include "note_play_handle.h" #include "templates.h" -#include "buffer_allocator.h" #include "knob.h" #undef SINGLE_SOURCE_COMPILE @@ -731,14 +730,12 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) } const Uint32 frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame *buf = bufferAllocator::alloc( frames ); + sampleFrame *buf = new sampleFrame[frames]; - if (buf) { process(buf, frames); getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); - } + delete[] buf; lastFramesPlayed = _n->totalFramesPlayed(); } diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index d2623d58b..270783241 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -54,7 +54,6 @@ using namespace std; #include "instrument_track.h" #include "note_play_handle.h" #include "templates.h" -#include "buffer_allocator.h" #include "knob.h" #include "pixmap_button.h" #include "tooltip.h" @@ -371,7 +370,7 @@ void organicInstrument::playNote( notePlayHandle * _n, bool ) )->oscRight; const fpab_t frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; osc_l->update( buf, frames, 0 ); osc_r->update( buf, frames, 1 ); @@ -394,7 +393,7 @@ void organicInstrument::playNote( notePlayHandle * _n, bool ) getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/patman/patman.cpp b/plugins/patman/patman.cpp index 218be652f..fd1da1413 100644 --- a/plugins/patman/patman.cpp +++ b/plugins/patman/patman.cpp @@ -29,17 +29,18 @@ #include #include +#include #else #include +#include #include #include #endif #include "patman.h" -#include "buffer_allocator.h" #include "endian_handling.h" #include "file_browser.h" #include "note_play_handle.h" @@ -211,7 +212,7 @@ QString patmanSynth::nodeName( void ) const void patmanSynth::playNote( notePlayHandle * _n, bool ) { const Uint32 frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; float freq = getInstrumentTrack()->frequency( _n ); @@ -228,7 +229,7 @@ void patmanSynth::playNote( notePlayHandle * _n, bool ) { getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); } - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/plucked_string_synth/plucked_string_synth.cpp b/plugins/plucked_string_synth/plucked_string_synth.cpp index 1f8ff7e42..04d88e57b 100644 --- a/plugins/plucked_string_synth/plucked_string_synth.cpp +++ b/plugins/plucked_string_synth/plucked_string_synth.cpp @@ -40,7 +40,6 @@ #include "instrument_track.h" #include "note_play_handle.h" #include "templates.h" -#include "buffer_allocator.h" #include "knob.h" #undef SINGLE_SOURCE_COMPILE @@ -144,7 +143,7 @@ void pluckedStringSynth::playNote( notePlayHandle * _n, bool ) } const Uint32 frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; pluckSynth * ps = static_cast( _n->m_pluginData ); for( Uint32 frame = 0; frame < frames; ++frame ) @@ -158,7 +157,7 @@ void pluckedStringSynth::playNote( notePlayHandle * _n, bool ) getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/polyb302/polyb302.cpp b/plugins/polyb302/polyb302.cpp index 5174f943d..48ab195f7 100644 --- a/plugins/polyb302/polyb302.cpp +++ b/plugins/polyb302/polyb302.cpp @@ -30,7 +30,6 @@ #include "polyb302.h" -#include "buffer_allocator.h" #include "knob.h" #include "led_checkbox.h" #include "note_play_handle.h" @@ -558,15 +557,12 @@ void polyb302Synth::playNote( notePlayHandle * _n, bool ) } const Uint32 frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; - if( buf ) - { - hstate->process( buf, frames, freq ); - getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); + hstate->process( buf, frames, freq ); + getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); - } + delete[] buf; hstate->m_lastFramesPlayed = _n->totalFramesPlayed(); } diff --git a/plugins/singerbot/singerbot.cpp b/plugins/singerbot/singerbot.cpp index 1c98f16ae..161684368 100644 --- a/plugins/singerbot/singerbot.cpp +++ b/plugins/singerbot/singerbot.cpp @@ -30,17 +30,18 @@ #include #include #include +#include #else #include +#include #include #include #endif #include "singerbot.h" -#include "buffer_allocator.h" #include "instrument_track.h" #include "note_play_handle.h" #include "pattern.h" @@ -145,7 +146,7 @@ singerBot::~singerBot() void singerBot::playNote( notePlayHandle * _n, bool ) { const Uint32 frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; if( !_n->m_pluginData ) { @@ -163,7 +164,7 @@ void singerBot::playNote( notePlayHandle * _n, bool ) getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); } sharedObject::unref( sample_buffer ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index 07f614058..5938d127b 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -92,8 +92,7 @@ mallets::mallets( instrumentTrack * _channel_track ) : m_spread->move( 178, 173 ); m_spread->setHintText( tr( "Spread:" ) + " ", "" ); - m_buffer = bufferAllocator::alloc( - engine::getMixer()->framesPerAudioBuffer() ); + m_buffer = new sampleFrame[engine::getMixer()->framesPerAudioBuffer()]; } @@ -101,7 +100,7 @@ mallets::mallets( instrumentTrack * _channel_track ) : mallets::~mallets() { - bufferAllocator::free( m_buffer ); + delete[] m_buffer; } @@ -539,7 +538,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, m_voice = NULL; } - m_delay = bufferAllocator::alloc( 256 ); + m_delay = new StkFloat[256]; m_delayRead = 0; m_delayWrite = _delay; for( Uint16 i = 0; i < 256; i++ ) @@ -587,7 +586,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, m_voice = NULL; } - m_delay = bufferAllocator::alloc( 256 ); + m_delay = new StkFloat[256]; m_delayRead = 0; m_delayWrite = _delay; for( Uint16 i = 0; i < 256; i++ ) @@ -637,7 +636,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, m_voice = NULL; } - m_delay = bufferAllocator::alloc( 256 ); + m_delay = new StkFloat[256]; m_delayRead = 0; m_delayWrite = _delay; for( Uint16 i = 0; i < 256; i++ ) diff --git a/plugins/stk/mallets/mallets.h b/plugins/stk/mallets/mallets.h index 380f077d3..a862fa0a8 100644 --- a/plugins/stk/mallets/mallets.h +++ b/plugins/stk/mallets/mallets.h @@ -1,7 +1,7 @@ /* * mallets.h - tuned instruments that one would bang upon * - * Copyright (c) 2006 Danny McRae + * Copyright (c) 2006-2007 Danny McRae * * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net @@ -33,7 +33,6 @@ #include "combobox.h" #include "led_checkbox.h" #include "track.h" -#include "buffer_allocator.h" class knob; class notePlayHandle; @@ -81,7 +80,7 @@ public: inline ~malletsSynth( void ) { m_voice->noteOff( 0.0 ); - bufferAllocator::free( m_delay ); + delete[] m_delay; delete m_voice; } diff --git a/plugins/triple_oscillator/artwork.png b/plugins/triple_oscillator/artwork.png index dcb172f1940ae74f6405817223e828ae2626150d..3842120b1f3e83514ad7cc392e5275b9c2974316 100644 GIT binary patch literal 23652 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

380=hfBxs;2u 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

byCG zu{>)4w%y)r6>8mlDK0j{Hy^VH!JVJr0w}poV`A|4XNA2c3U^%Qu*XC^_hxFRElmCY z{CWmx^YJt^Tq@BMSN^c;i?Tr1d06H=@tgoEF*l|cW@eu-1mgO9gN9DU*VjO8VA<@+4EaWFQxk}TBaAop zw`BgSqs>k!=&k5$HHAOFG+heBA81~r^78-$JywI$)1xnrxPWb=Ur>v6iG+aZisji_ zr~Wcy0nMDtyLqXz^ult9xVuXGXh`3WSl!Wns&DxO!*oh2xW=hu79=4d(OR##PRNDi z`JD5FlpL^JG7?uPDQi_&JU~hsvBD(S%%#>;oUq>4YOl?Bcwaa;eYyHd<<$GNpcziO z5+Av=z0~sdu?-*;$hRTeg|;8kZy zSIwMh^^b3AU9Zr>!tfkvdP?&4Y~6~hs|rOj{murkZsy##(z}J$yF7gmq~?q}1q7;X zn>tCJDoxV_PxRZ6QZ*O)%0ZEE(9{9;mY^uwrkX4E@P|Q!<2P2aO+Je~3W`-yOj1&u zfoD79=_9fjFx3DpJB1Ek&>s|PaSZ*uQ!?1(kq<6_LF{~c${S_jVq-%Vy5Q=HY;6#FRe zB*jx~psD*X*^Fm01^jGOKk=~7ef%5YKfK!QQ|HEH8XE7WWKXmhA71MzC?w=At4Yd8 z%F2%R+TF3Iu_gEScEMt_nlw14W9b*gMm4`~6y=92E4j${xHE)#3~_tn$~TluJ}l7X zpr}=4zlkDoS#Fx09vp0LZYBgMD70V$zEm1lOdcEvMs;qu*I8H~U0mQd*8x45*rCxS zlX_|!{)xo~tcknSM1+J`!D#|gWfD)v*O$!sQYR-x@Ng1E&7}bP`c2Uv77;c`0D!{5 z+QDH_zb@=Fl@~iy&I>MqX;M-V5f|~|eZs@8c7g*SP|*63@X;YsLZYqQ+|p%M;qES> zsxsm9!1|fFxu@B}uL5=R4`;0HLqnomc9?KZvhm!sxP%L#E++FkZZzR;qlZ+up>7Jx&H3w9xKO4Fnx~py z&2fY8;k5vRtE;&(;Sxr6-&jFv<>7U6-#y9nOP1o>a zuixOHL}Wjdio~@>|BV3nPRjBVe@+@lK+bd_`^IZ< zR`|@#Kq$#7;2O41;by+DmarT+u*k=R?@Tostodk&4^1C4OwM6WMjbrSqfrg7P{wifuvzs;+&F} zbx1)J*t8||Vfj-D*L0btdG~6yn;IO_r_(2wrLr=4A{mGFb6ObIk z{^~=YwWs%>v=Y0ibUR6~4sSZ>v=s$muhV~zEy%Ve~O2g1?dka3SU0aq%ZY8-i9 zmvG9mEQH1A{G_bSFQ%8}J4NAhc0_QrP$T=&vgm}>F>RV6LOas{i< Fe*)qJNG<>X diff --git a/plugins/triple_oscillator/triple_oscillator.cpp b/plugins/triple_oscillator/triple_oscillator.cpp index f9e27c6e0..6da5522bc 100644 --- a/plugins/triple_oscillator/triple_oscillator.cpp +++ b/plugins/triple_oscillator/triple_oscillator.cpp @@ -48,7 +48,6 @@ #include "instrument_track.h" #include "note_play_handle.h" #include "knob.h" -#include "buffer_allocator.h" #include "debug.h" #include "tooltip.h" #include "sample_buffer.h" @@ -103,7 +102,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : #endif pixmapButton * pm_osc1_btn = new pixmapButton( this, NULL, NULL ); - pm_osc1_btn->move( 80, 50 ); + pm_osc1_btn->move( 46, 50 ); pm_osc1_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); pm_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -115,7 +114,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : "oscillator 1" ) ); pixmapButton * am_osc1_btn = new pixmapButton( this, NULL, NULL ); - am_osc1_btn->move( 120, 50 ); + am_osc1_btn->move( 86, 50 ); am_osc1_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); am_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -127,7 +126,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : "oscillator 1" ) ); pixmapButton * mix_osc1_btn = new pixmapButton( this, NULL, NULL ); - mix_osc1_btn->move( 160, 50 ); + mix_osc1_btn->move( 126, 50 ); mix_osc1_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); mix_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -137,7 +136,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : toolTip::add( mix_osc1_btn, tr( "mix output of oscillator 1 & 2" ) ); pixmapButton * sync_osc1_btn = new pixmapButton( this, NULL, NULL ); - sync_osc1_btn->move( 200, 50 ); + sync_osc1_btn->move( 166, 50 ); sync_osc1_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sync_active" ) ); sync_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -148,7 +147,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : "oscillator 2" ) ); pixmapButton * fm_osc1_btn = new pixmapButton( this, NULL, NULL ); - fm_osc1_btn->move( 330, 50 ); + fm_osc1_btn->move( 206, 50 ); fm_osc1_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_active" ) ); fm_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -174,7 +173,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : pixmapButton * pm_osc2_btn = new pixmapButton( this, NULL, NULL ); - pm_osc2_btn->move( 80, 70 ); + pm_osc2_btn->move( 46, 68 ); pm_osc2_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); pm_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -186,7 +185,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : "oscillator 2" ) ); pixmapButton * am_osc2_btn = new pixmapButton( this, NULL, NULL ); - am_osc2_btn->move( 120, 70 ); + am_osc2_btn->move( 86, 68 ); am_osc2_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); am_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -198,7 +197,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : "oscillator 2" ) ); pixmapButton * mix_osc2_btn = new pixmapButton( this, NULL, NULL ); - mix_osc2_btn->move( 160, 70 ); + mix_osc2_btn->move( 126, 68 ); mix_osc2_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); mix_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -208,7 +207,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : toolTip::add( mix_osc2_btn, tr("mix output of oscillator 2 & 3" ) ); pixmapButton * sync_osc2_btn = new pixmapButton( this, NULL, NULL ); - sync_osc2_btn->move( 200, 70 ); + sync_osc2_btn->move( 166, 68 ); sync_osc2_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sync_active" ) ); sync_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -219,7 +218,7 @@ tripleOscillator::tripleOscillator( instrumentTrack * _channel_track ) : "oscillator 3" ) ); pixmapButton * fm_osc2_btn = new pixmapButton( this, NULL, NULL ); - fm_osc2_btn->move( 330, 70 ); + fm_osc2_btn->move( 206, 68 ); fm_osc2_btn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_active" ) ); fm_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( @@ -740,14 +739,14 @@ void tripleOscillator::playNote( notePlayHandle * _n, bool ) )->oscRight; const fpab_t frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; osc_l->update( buf, frames, 0 ); osc_r->update( buf, frames, 1 ); getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index c16d79c89..7c107807d 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -51,7 +51,6 @@ #include "instrument_track.h" #include "note_play_handle.h" -#include "buffer_allocator.h" #include "mixer.h" #include "instrument_play_handle.h" #include "pixmap_button.h" @@ -298,7 +297,7 @@ void vestigeInstrument::waitForWorkerThread( void ) } const fpab_t frames = engine::getMixer()->framesPerAudioBuffer(); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; if( m_plugin->waitForProcessingFinished( buf ) ) { @@ -307,7 +306,7 @@ void vestigeInstrument::waitForWorkerThread( void ) m_pluginMutex.unlock(); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index a7b95179e..aff5978dd 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -48,7 +48,6 @@ #include "note_play_handle.h" #include "instrument_track.h" #include "templates.h" -#include "buffer_allocator.h" #include "knob.h" #include "tooltip.h" #include "oscillator.h" @@ -582,7 +581,7 @@ void vibed::playNote( notePlayHandle * _n, bool ) stringContainer * ps = static_cast( _n->m_pluginData ); - sampleFrame * buf = bufferAllocator::alloc( frames ); + sampleFrame * buf = new sampleFrame[frames]; for( fpab_t i = 0; i < frames; ++i ) { @@ -609,7 +608,7 @@ void vibed::playNote( notePlayHandle * _n, bool ) getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - bufferAllocator::free( buf ); + delete[] buf; } diff --git a/plugins/vibed/vibed.h b/plugins/vibed/vibed.h index 37238dc7b..690eb7698 100644 --- a/plugins/vibed/vibed.h +++ b/plugins/vibed/vibed.h @@ -1,6 +1,6 @@ /* vibed_strings.h - * - * Copyright (c) 2006 Danny McRae + * Copyright (c) 2006-2007 Danny McRae * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -29,7 +29,6 @@ #include "sample_buffer.h" #include "graph.h" #include "pixmap_button.h" -#include "buffer_allocator.h" #include "led_checkbox.h" #include "impulse_editor.h" #include "lcd_spinbox.h" diff --git a/plugins/vibed/vibrating_string.cpp b/plugins/vibed/vibrating_string.cpp index c3e89ef6e..995d7f7ca 100644 --- a/plugins/vibed/vibrating_string.cpp +++ b/plugins/vibed/vibrating_string.cpp @@ -1,7 +1,7 @@ /* * vibrating_sring.h - model of a vibrating string lifted from pluckedSynth * - * Copyright (c) 2006 Danny McRae + * Copyright (c) 2006-2007 Danny McRae * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -44,7 +44,7 @@ vibratingString::vibratingString( float _pitch, m_stringLoss( 1.0f - _string_loss ), m_state( 0.1f ) { - m_outsamp = bufferAllocator::alloc( m_oversample ); + m_outsamp = new sample_t[m_oversample]; int string_length; string_length = static_cast( m_oversample * _sample_rate / @@ -55,12 +55,12 @@ vibratingString::vibratingString( float _pitch, if( not _state ) { - m_impulse = bufferAllocator::alloc( string_length ); + m_impulse = new float[string_length]; resample( _impulse, _len, string_length ); } else { - m_impulse = bufferAllocator::alloc( _len ); + m_impulse = new float[_len]; for( Uint32 i = 0; i < _len; i++ ) { m_impulse[i] = _impulse[i]; diff --git a/plugins/vibed/vibrating_string.h b/plugins/vibed/vibrating_string.h index 372f5cd45..4f7c36a48 100644 --- a/plugins/vibed/vibrating_string.h +++ b/plugins/vibed/vibrating_string.h @@ -1,7 +1,7 @@ /* * vibrating_string.h - model of a vibrating string lifted from pluckedSynth * - * Copyright (c) 2006 Danny McRae + * Copyright (c) 2006-2007 Danny McRae * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -29,7 +29,6 @@ #include "config.h" #include "types.h" -#include "buffer_allocator.h" class vibratingString { @@ -49,8 +48,8 @@ public: inline ~vibratingString( void ) { - bufferAllocator::free( m_outsamp ); - bufferAllocator::free( m_impulse ); + delete[] m_outsamp; + delete[] m_impulse; vibratingString::freeDelayLine( m_fromBridge ); vibratingString::freeDelayLine( m_toBridge ); } diff --git a/plugins/vst_effect/vst_effect.cpp b/plugins/vst_effect/vst_effect.cpp index c279eafd1..4d62367ff 100644 --- a/plugins/vst_effect/vst_effect.cpp +++ b/plugins/vst_effect/vst_effect.cpp @@ -38,7 +38,6 @@ #include "vst_subplugin_features.h" #include "song_editor.h" #include "text_float.h" -#include "buffer_allocator.h" #undef SINGLE_SOURCE_COMPILE @@ -98,8 +97,7 @@ bool FASTCALL vstEffect::processAudioBuffer( surroundSampleFrame * _buf, if( m_plugin ) { - sampleFrame * buf = bufferAllocator::alloc( - _frames ); + sampleFrame * buf = new sampleFrame[_frames]; for( fpab_t f = 0; f < _frames; ++f ) { for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) @@ -121,7 +119,7 @@ bool FASTCALL vstEffect::processAudioBuffer( surroundSampleFrame * _buf, out_sum += _buf[f][ch]*_buf[f][ch]; } } - bufferAllocator::free( buf ); + delete[] buf; if( out_sum <= getGate() ) { incrementBufferCount(); diff --git a/src/audio/audio_alsa.cpp b/src/audio/audio_alsa.cpp index 3952b8d59..052c65877 100644 --- a/src/audio/audio_alsa.cpp +++ b/src/audio/audio_alsa.cpp @@ -48,7 +48,6 @@ #ifdef ALSA_SUPPORT #include "endian_handling.h" -#include "buffer_allocator.h" #include "config_mgr.h" #include "lcd_spinbox.h" #include "gui_templates.h" @@ -214,13 +213,11 @@ void audioALSA::stopProcessing( void ) void audioALSA::run( void ) { surroundSampleFrame * temp = - bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() ); - int_sample_t * outbuf = bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() * - channels() ); - int_sample_t * pcmbuf = bufferAllocator::alloc( - m_periodSize * channels() ); + new surroundSampleFrame[getMixer()->framesPerAudioBuffer()]; + int_sample_t * outbuf = + new int_sample_t[getMixer()->framesPerAudioBuffer() * + channels()]; + int_sample_t * pcmbuf = new int_sample_t[m_periodSize * channels()]; int outbuf_size = getMixer()->framesPerAudioBuffer() * channels(); int outbuf_pos = 0; @@ -286,9 +283,9 @@ void audioALSA::run( void ) } } - bufferAllocator::free( temp ); - bufferAllocator::free( outbuf ); - bufferAllocator::free( pcmbuf ); + delete[] temp; + delete[] outbuf; + delete[] pcmbuf; } diff --git a/src/audio/audio_device.cpp b/src/audio/audio_device.cpp index 9f88bb2c2..5b1383895 100644 --- a/src/audio/audio_device.cpp +++ b/src/audio/audio_device.cpp @@ -33,7 +33,6 @@ #include "audio_device.h" -#include "buffer_allocator.h" #include "debug.h" @@ -43,8 +42,7 @@ audioDevice::audioDevice( const sample_rate_t _sample_rate, m_sampleRate( _sample_rate ), m_channels( _channels ), m_mixer( _mixer ), - m_buffer( bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() ) ) + m_buffer( new surroundSampleFrame[getMixer()->framesPerAudioBuffer()] ) { #ifdef HAVE_SAMPLERATE_H int error; @@ -70,7 +68,7 @@ audioDevice::~audioDevice() #ifdef HAVE_SAMPLERATE_H src_delete( m_srcState ); #endif - bufferAllocator::free( m_buffer ); + delete[] m_buffer; #ifdef QT3 if( m_devMutex.locked() ) { @@ -85,15 +83,17 @@ audioDevice::~audioDevice() -bool audioDevice::processNextBuffer( void ) +void audioDevice::processNextBuffer( void ) { const fpab_t frames = getNextBuffer( m_buffer ); - if( !frames ) + if( frames ) { - return( FALSE ); + writeBuffer( m_buffer, frames, getMixer()->masterGain() ); + } + else + { + m_in_process = FALSE; } - writeBuffer( m_buffer, frames, getMixer()->masterGain() ); - return( TRUE ); } @@ -136,7 +136,10 @@ fpab_t audioDevice::getNextBuffer( surroundSampleFrame * _ab ) void audioDevice::stopProcessing( void ) { - while( processNextBuffer() ); + while( m_in_process ) + { + processNextBuffer(); + } } diff --git a/src/audio/audio_file_device.cpp b/src/audio/audio_file_device.cpp index 4cc181a3c..f32258e18 100644 --- a/src/audio/audio_file_device.cpp +++ b/src/audio/audio_file_device.cpp @@ -41,7 +41,6 @@ #include "audio_file_device.h" #include "export_project_dialog.h" -#include "buffer_allocator.h" audioFileDevice::audioFileDevice( const sample_rate_t _sample_rate, diff --git a/src/audio/audio_file_wave.cpp b/src/audio/audio_file_wave.cpp index 6abf746d9..cf324cb96 100644 --- a/src/audio/audio_file_wave.cpp +++ b/src/audio/audio_file_wave.cpp @@ -29,7 +29,6 @@ #include "audio_file_wave.h" #include "endian_handling.h" -#include "buffer_allocator.h" #include @@ -96,13 +95,12 @@ void FASTCALL audioFileWave::writeBuffer( const surroundSampleFrame * _ab, const fpab_t _frames, const float _master_gain ) { - int_sample_t * outbuf = bufferAllocator::alloc( - _frames * channels() ); + int_sample_t * outbuf = new int_sample_t[_frames * channels()]; Uint32 bytes = convertToS16( _ab, _frames, _master_gain, outbuf, !isLittleEndian() ); writeData( outbuf, bytes ); - bufferAllocator::free( outbuf ); + delete[] outbuf; m_bytesWritten += bytes; } diff --git a/src/audio/audio_jack.cpp b/src/audio/audio_jack.cpp index 384e6bf6a..325e24093 100644 --- a/src/audio/audio_jack.cpp +++ b/src/audio/audio_jack.cpp @@ -51,7 +51,6 @@ #include "debug.h" #include "templates.h" #include "gui_templates.h" -#include "buffer_allocator.h" #include "config_mgr.h" #include "lcd_spinbox.h" #include "audio_port.h" @@ -69,8 +68,7 @@ audioJACK::audioJACK( const sample_rate_t _sample_rate, bool & _success_ful, m_active( FALSE ), // m_processCallbackMutex(), m_stop_semaphore( 1 ), - m_outBuf( bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() ) ), + m_outBuf( new surroundSampleFrame[getMixer()->framesPerAudioBuffer()] ), m_framesDoneInCurBuf( 0 ), m_framesToDoInCurBuf( 0 ) { @@ -202,7 +200,7 @@ audioJACK::~audioJACK() jack_client_close( m_client ); } - bufferAllocator::free( m_outBuf ); + delete[] m_outBuf; } diff --git a/src/audio/audio_oss.cpp b/src/audio/audio_oss.cpp index 3cc94b42a..2da17b9a0 100644 --- a/src/audio/audio_oss.cpp +++ b/src/audio/audio_oss.cpp @@ -47,7 +47,6 @@ #endif -#include "buffer_allocator.h" #include "endian_handling.h" #include "lcd_spinbox.h" #include "gui_templates.h" @@ -317,11 +316,10 @@ void audioOSS::stopProcessing( void ) void audioOSS::run( void ) { surroundSampleFrame * temp = - bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() ); - int_sample_t * outbuf = bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() * - channels() ); + new surroundSampleFrame[getMixer()->framesPerAudioBuffer()]; + int_sample_t * outbuf = + new int_sample_t[getMixer()->framesPerAudioBuffer() * + channels()]; while( TRUE ) { @@ -337,8 +335,8 @@ void audioOSS::run( void ) write( m_audioFD, outbuf, bytes ); } - bufferAllocator::free( temp ); - bufferAllocator::free( outbuf ); + delete[] temp; + delete[] outbuf; } diff --git a/src/audio/audio_port.cpp b/src/audio/audio_port.cpp index 02dab03d5..fe9b484df 100644 --- a/src/audio/audio_port.cpp +++ b/src/audio/audio_port.cpp @@ -30,15 +30,14 @@ #include "audio_port.h" #include "audio_device.h" -#include "buffer_allocator.h" #include "engine.h" audioPort::audioPort( const QString & _name ) : m_bufferUsage( NONE ), - m_firstBuffer( bufferAllocator::alloc( - engine::getMixer()->framesPerAudioBuffer() ) ), - m_secondBuffer( bufferAllocator::alloc( - engine::getMixer()->framesPerAudioBuffer() ) ), + m_firstBuffer( new surroundSampleFrame[ + engine::getMixer()->framesPerAudioBuffer()] ), + m_secondBuffer( new surroundSampleFrame[ + engine::getMixer()->framesPerAudioBuffer()] ), m_extOutputEnabled( FALSE ), m_nextFxChannel( -1 ), m_name( "unnamed port" ) @@ -63,8 +62,8 @@ audioPort::~audioPort() { engine::getMixer()->audioDev()->unregisterPort( this ); } - bufferAllocator::free( m_firstBuffer ); - bufferAllocator::free( m_secondBuffer ); + delete[] m_firstBuffer; + delete[] m_secondBuffer; } diff --git a/src/audio/audio_sample_recorder.cpp b/src/audio/audio_sample_recorder.cpp index c74cec3ae..9d7d6f951 100644 --- a/src/audio/audio_sample_recorder.cpp +++ b/src/audio/audio_sample_recorder.cpp @@ -30,7 +30,6 @@ #include "audio_sample_recorder.h" #include "sample_buffer.h" -#include "buffer_allocator.h" #include "debug.h" @@ -52,7 +51,7 @@ audioSampleRecorder::~audioSampleRecorder() { while( !m_buffers.empty() ) { - bufferAllocator::free( m_buffers.front().first ); + delete[] m_buffers.front().first; m_buffers.erase( m_buffers.begin() ); } } @@ -78,9 +77,9 @@ void audioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf ) { const f_cnt_t frames = framesRecorded(); // create buffer to store all recorded buffers in - sampleFrame * data = bufferAllocator::alloc( frames ); + sampleFrame * data = new sampleFrame[frames]; // make sure buffer is cleaned up properly at the end... - bufferAllocator::autoCleaner ac( data ); + sampleFrame * data_ptr = data; #ifdef LMMS_DEBUG assert( data != NULL ); @@ -89,12 +88,14 @@ void audioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf ) for( bufferList::const_iterator it = m_buffers.begin(); it != m_buffers.end(); ++it ) { - memcpy( data, ( *it ).first, ( *it ).second * + memcpy( data_ptr, ( *it ).first, ( *it ).second * sizeof( sampleFrame ) ); - data += ( *it ).second; + data_ptr += ( *it ).second; } // create according sample-buffer out of big buffer - *_sample_buf = new sampleBuffer( ac.ptr(), frames ); + *_sample_buf = new sampleBuffer( data, frames ); + ( *_sample_buf )->setSampleRate( sampleRate() ); + delete[] data; } @@ -103,7 +104,7 @@ void audioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf ) void audioSampleRecorder::writeBuffer( const surroundSampleFrame * _ab, const fpab_t _frames, const float ) { - sampleFrame * buf = bufferAllocator::alloc( _frames ); + sampleFrame * buf = new sampleFrame[_frames]; for( fpab_t frame = 0; frame < _frames; ++frame ) { for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) diff --git a/src/audio/audio_sdl.cpp b/src/audio/audio_sdl.cpp index f78c1a133..209481fa3 100644 --- a/src/audio/audio_sdl.cpp +++ b/src/audio/audio_sdl.cpp @@ -43,7 +43,6 @@ #endif -#include "buffer_allocator.h" #include "debug.h" #include "config_mgr.h" #include "gui_templates.h" @@ -55,8 +54,7 @@ audioSDL::audioSDL( const sample_rate_t _sample_rate, bool & _success_ful, mixer * _mixer ) : audioDevice( _sample_rate, DEFAULT_CHANNELS, _mixer ), - m_outBuf( bufferAllocator::alloc( - getMixer()->framesPerAudioBuffer() ) ), + m_outBuf( new surroundSampleFrame[getMixer()->framesPerAudioBuffer()] ), m_convertedBuf_pos( 0 ), m_convertEndian( FALSE ), m_stop_semaphore( 1 ) @@ -65,8 +63,7 @@ audioSDL::audioSDL( const sample_rate_t _sample_rate, bool & _success_ful, m_convertedBuf_size = getMixer()->framesPerAudioBuffer() * channels() * sizeof( int_sample_t ); - m_convertedBuf = (Uint8 *)bufferAllocator::allocBytes( - m_convertedBuf_size ); + m_convertedBuf = new Uint8[m_convertedBuf_size]; /* // if device is set, we set AUDIODEV-environment-variable, so that // SDL can evaluate and use it @@ -130,8 +127,8 @@ audioSDL::~audioSDL() #endif SDL_CloseAudio(); SDL_Quit(); - bufferAllocator::free( m_convertedBuf ); - bufferAllocator::free( m_outBuf ); + delete[] m_convertedBuf; + delete[] m_outBuf; } diff --git a/src/core/automation_editor.cpp b/src/core/automation_editor.cpp index 7c8384005..35ecd3e8b 100644 --- a/src/core/automation_editor.cpp +++ b/src/core/automation_editor.cpp @@ -65,6 +65,7 @@ #include "song_editor.h" #include "main_window.h" #include "embed.h" +#include "engine.h" #include "pixmap_button.h" #include "templates.h" #include "gui_templates.h" diff --git a/src/core/bb_editor.cpp b/src/core/bb_editor.cpp index 8ac9fbdea..ce4d01cb4 100644 --- a/src/core/bb_editor.cpp +++ b/src/core/bb_editor.cpp @@ -46,6 +46,7 @@ #include "bb_editor.h" #include "song_editor.h" #include "embed.h" +#include "engine.h" #include "tool_button.h" #include "track_container.h" #include "bb_track.h" diff --git a/src/core/envelope_and_lfo_widget.cpp b/src/core/envelope_and_lfo_widget.cpp index d621ff1f4..ecb14a41f 100644 --- a/src/core/envelope_and_lfo_widget.cpp +++ b/src/core/envelope_and_lfo_widget.cpp @@ -49,6 +49,7 @@ #include "envelope_and_lfo_widget.h" #include "song_editor.h" #include "embed.h" +#include "engine.h" #include "knob.h" #include "pixmap_button.h" #include "oscillator.h" diff --git a/src/core/envelope_tab_widget.cpp b/src/core/envelope_tab_widget.cpp index 7dbadea9e..63afa3e1e 100644 --- a/src/core/envelope_tab_widget.cpp +++ b/src/core/envelope_tab_widget.cpp @@ -253,7 +253,7 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, const fpab_t _frames, notePlayHandle * _n ) { - f_cnt_t total_frames = _n->totalFramesPlayed(); + const f_cnt_t total_frames = _n->totalFramesPlayed(); f_cnt_t release_begin = total_frames - _n->releaseFramesDone() + _n->framesBeforeRelease(); @@ -263,67 +263,49 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } // because of optimizations, there's special code for several cases: - // - volume-, cut- and res-lfo/envelope active - // - volume- and cut-lfo/envelope active - // - volume- and res-lfo/envelope active + // - cut- and res-lfo/envelope active // - cut-lfo/envelope active // - res-lfo/envelope active - // - volume-lfo/envelope active // - no lfo/envelope active but filter is used - // now there's a lot of similar code but I didn't found a way to - // generalize it yet... may be later we could do that - // by using preprocessor and macro-expansion... (like in oscillator.cpp) // only use filter, if it is really needed - if( _n->m_filter == NULL ) - { - _n->m_filter = new basicFilters<>( - engine::getMixer()->sampleRate() ); - } - - m_envLFOWidgets[VOLUME]->lock(); - m_envLFOWidgets[CUT]->lock(); - m_envLFOWidgets[RES]->lock(); - - float * vol_buf = NULL; - float * cut_buf = NULL; - float * res_buf = NULL; - - if( m_envLFOWidgets[VOLUME]->used() ) - { - vol_buf = new float[_frames]; - m_envLFOWidgets[VOLUME]->fillLevel( vol_buf, total_frames, - release_begin, _frames ); - } - if( m_envLFOWidgets[CUT]->used() ) - { - cut_buf = new float[_frames]; - m_envLFOWidgets[CUT]->fillLevel( cut_buf, total_frames, - release_begin, _frames ); - } - if( m_envLFOWidgets[RES]->used() ) - { - res_buf = new float[_frames]; - m_envLFOWidgets[RES]->fillLevel( res_buf, total_frames, - release_begin, _frames ); - } - if( m_filterGroupBox->isActive() ) { int old_filter_cut = 0; int old_filter_res = 0; - basicFilters<>::filterTypes filter = - basicFilters<>::getFilterType( - m_filterComboBox->value() ); + if( _n->m_filter == NULL ) + { + _n->m_filter = new basicFilters<>( + engine::getMixer()->sampleRate() ); + } + _n->m_filter->setType( basicFilters<>::getFilterType( + m_filterComboBox->value() ) ); - if( m_envLFOWidgets[VOLUME]->used() && - m_envLFOWidgets[CUT]->used() && + float * cut_buf = NULL; + float * res_buf = NULL; + + m_envLFOWidgets[CUT]->lock(); + m_envLFOWidgets[RES]->lock(); + + if( m_envLFOWidgets[CUT]->used() ) + { + cut_buf = new float[_frames]; + m_envLFOWidgets[CUT]->fillLevel( cut_buf, total_frames, + release_begin, _frames ); + } + if( m_envLFOWidgets[RES]->used() ) + { + res_buf = new float[_frames]; + m_envLFOWidgets[RES]->fillLevel( res_buf, total_frames, + release_begin, _frames ); + } + + if( m_envLFOWidgets[CUT]->used() && m_envLFOWidgets[RES]->used() ) { - for( fpab_t frame = 0; frame < _frames; - ++frame, ++total_frames ) + for( fpab_t frame = 0; frame < _frames; ++frame ) { float new_cut_val = envelopeAndLFOWidget::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER + m_filterCutKnob->value(); @@ -334,76 +316,27 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, if( static_cast( new_cut_val ) != old_filter_cut || static_cast( new_res_val*RES_PRECISION ) != old_filter_res ) { - _n->m_filter->calcFilterCoeffs( filter, new_cut_val, new_res_val ); + _n->m_filter->calcFilterCoeffs( new_cut_val, new_res_val ); old_filter_cut = static_cast( new_cut_val ); old_filter_res = static_cast( new_res_val*RES_PRECISION ); } - float vol_level = vol_buf[frame]; - vol_level = vol_level*vol_level; - for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) { - _ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl ); + _ab[frame][chnl] = _n->m_filter->update( _ab[frame][chnl], chnl ); } } } - else if( m_envLFOWidgets[VOLUME]->used() && m_envLFOWidgets[CUT]->used() ) - { - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) - { - float new_cut_val = envelopeAndLFOWidget::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER + - m_filterCutKnob->value(); - - if( static_cast( new_cut_val ) != old_filter_cut ) - { - _n->m_filter->calcFilterCoeffs( filter, new_cut_val, m_filterResKnob->value() ); - old_filter_cut = static_cast( new_cut_val ); - } - - float vol_level = vol_buf[frame]; - vol_level = vol_level*vol_level; - - for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) - { - _ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl ); - } - } - } - else if( m_envLFOWidgets[VOLUME]->used() && m_envLFOWidgets[RES]->used() ) - { - - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) - { - float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER * - res_buf[frame]; - - if( static_cast( new_res_val*RES_PRECISION ) != old_filter_res ) - { - _n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), new_res_val ); - old_filter_res = static_cast( new_res_val*RES_PRECISION ); - } - - float vol_level = vol_buf[frame]; - vol_level = vol_level*vol_level; - - for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) - { - _ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl ); - } - } - - } else if( m_envLFOWidgets[CUT]->used() ) { - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) + for( fpab_t frame = 0; frame < _frames; ++frame ) { float new_cut_val = envelopeAndLFOWidget::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER + m_filterCutKnob->value(); if( static_cast( new_cut_val ) != old_filter_cut ) { - _n->m_filter->calcFilterCoeffs( filter, new_cut_val, m_filterResKnob->value() ); + _n->m_filter->calcFilterCoeffs( new_cut_val, m_filterResKnob->value() ); old_filter_cut = static_cast( new_cut_val ); } @@ -415,14 +348,14 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } else if( m_envLFOWidgets[RES]->used() ) { - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) + for( fpab_t frame = 0; frame < _frames; ++frame ) { float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER * res_buf[frame]; if( static_cast( new_res_val*RES_PRECISION ) != old_filter_res ) { - _n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), new_res_val ); + _n->m_filter->calcFilterCoeffs( m_filterCutKnob->value(), new_res_val ); old_filter_res = static_cast( new_res_val*RES_PRECISION ); } @@ -432,26 +365,11 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } } } - else if( m_envLFOWidgets[VOLUME]->used() ) - { - _n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), m_filterResKnob->value() ); - - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) - { - float vol_level = vol_buf[frame]; - vol_level = vol_level*vol_level; - - for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) - { - _ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl ); - } - } - } else { - _n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), m_filterResKnob->value() ); + _n->m_filter->calcFilterCoeffs( m_filterCutKnob->value(), m_filterResKnob->value() ); - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) + for( fpab_t frame = 0; frame < _frames; ++frame ) { for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) { @@ -459,24 +377,39 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } } } + + m_envLFOWidgets[RES]->unlock(); + m_envLFOWidgets[CUT]->unlock(); + + delete[] cut_buf; + delete[] res_buf; } - else if( m_envLFOWidgets[VOLUME]->used() /*&& m_envLFOWidgets[PANNING]->used() == FALSE*/ ) + + m_envLFOWidgets[VOLUME]->lock(); + if( m_envLFOWidgets[VOLUME]->used() ) { - // only use volume-envelope... - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) + float * vol_buf = new float[_frames]; + m_envLFOWidgets[VOLUME]->fillLevel( vol_buf, total_frames, + release_begin, _frames ); + + for( fpab_t frame = 0; frame < _frames; ++frame ) { float vol_level = vol_buf[frame]; - vol_level = vol_level*vol_level; - for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + vol_level = vol_level * vol_level; + for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; + ++chnl ) { _ab[frame][chnl] = vol_level * _ab[frame][chnl]; } } + delete[] vol_buf; } + m_envLFOWidgets[VOLUME]->unlock(); + /* else if( m_envLFOWidgets[VOLUME]->used() == FALSE && m_envLFOWidgets[PANNING]->used() ) { // only use panning-envelope... - for( fpab_t frame = 0; frame < _frames; ++frame, ++total_frames ) + for( fpab_t frame = 0; frame < _frames; ++frame ) { float vol_level = pan_buf[frame]; vol_level = vol_level*vol_level; @@ -486,14 +419,6 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } } }*/ - - delete[] vol_buf; - delete[] cut_buf; - delete[] res_buf; - - m_envLFOWidgets[RES]->unlock(); - m_envLFOWidgets[CUT]->unlock(); - m_envLFOWidgets[VOLUME]->unlock(); } diff --git a/src/core/export_project_dialog.cpp b/src/core/export_project_dialog.cpp index 0fbfbd9f2..cf3dae63a 100644 --- a/src/core/export_project_dialog.cpp +++ b/src/core/export_project_dialog.cpp @@ -55,6 +55,7 @@ #include "combobox.h" #include "led_checkbox.h" #include "embed.h" +#include "engine.h" #include "audio_file_wave.h" #include "audio_file_ogg.h" @@ -383,7 +384,8 @@ void exportProjectDialog::exportBtnClicked( void ) songEditor::PLAY_SONG ); while( engine::getSongEditor()->exportDone() == FALSE && - engine::getSongEditor()->exporting() == TRUE ) + engine::getSongEditor()->exporting() == TRUE + && !m_deleteFile ) { dev->processNextBuffer(); int pval = pp * 100 / @@ -401,13 +403,7 @@ void exportProjectDialog::exportBtnClicked( void ) qApp->processEvents(); } - // if m_deleteFile == TRUE, user aborted export and finalization- - // routines were already called, so we only need to call them if - // export went through without any problems - if( m_deleteFile == FALSE ) - { - finishProjectExport(); - } + finishProjectExport(); } @@ -432,8 +428,6 @@ void exportProjectDialog::cancelBtnClicked( void ) void exportProjectDialog::abortProjectExport( void ) { m_deleteFile = TRUE; - - finishProjectExport(); } diff --git a/src/core/main_window.cpp b/src/core/main_window.cpp index a26a1807c..29f4e725e 100644 --- a/src/core/main_window.cpp +++ b/src/core/main_window.cpp @@ -75,7 +75,6 @@ #include "config_mgr.h" #include "mixer.h" #include "project_notes.h" -#include "buffer_allocator.h" #include "setup_dialog.h" #include "audio_dummy.h" #include "tool.h" diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index d258151fa..8fe921353 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -32,7 +32,6 @@ #include "song_editor.h" #include "templates.h" #include "envelope_and_lfo_widget.h" -#include "buffer_allocator.h" #include "debug.h" #include "engine.h" #include "config_mgr.h" @@ -109,8 +108,7 @@ mixer::mixer( void ) : for( Uint8 i = 0; i < 3; i++ ) { - m_readBuf = bufferAllocator::alloc( - m_framesPerAudioBuffer ); + m_readBuf = new surroundSampleFrame[m_framesPerAudioBuffer]; clearAudioBuffer( m_readBuf, m_framesPerAudioBuffer ); m_bufferPool.push_back( m_readBuf ); @@ -135,7 +133,7 @@ mixer::~mixer() for( Uint8 i = 0; i < 3; i++ ) { - bufferAllocator::free( m_bufferPool[i] ); + delete[] m_bufferPool[i]; } } @@ -165,11 +163,12 @@ void mixer::startProcessing( void ) void mixer::stopProcessing( void ) { m_fifo_writer->finish(); + + m_audioDev->stopProcessing(); + m_fifo_writer->wait( 1000 ); m_fifo_writer->terminate(); delete m_fifo_writer; - - m_audioDev->stopProcessing(); } diff --git a/src/core/note.cpp b/src/core/note.cpp index 2e721e794..4b749cc6c 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -39,8 +39,8 @@ #include -#include "debug.h" #include "note.h" +#include "automatable_object_templates.h" #include "knob.h" #include "templates.h" diff --git a/src/core/note_play_handle.cpp b/src/core/note_play_handle.cpp index 5b6008c97..563d6cdb4 100644 --- a/src/core/note_play_handle.cpp +++ b/src/core/note_play_handle.cpp @@ -27,6 +27,7 @@ #include "note_play_handle.h" +#include "automatable_object_templates.h" #include "instrument_track.h" #include "envelope_tab_widget.h" #include "midi.h" diff --git a/src/core/piano_roll.cpp b/src/core/piano_roll.cpp index 3fcfe09f2..48f435cf0 100644 --- a/src/core/piano_roll.cpp +++ b/src/core/piano_roll.cpp @@ -62,6 +62,7 @@ #include "piano_roll.h" +#include "automatable_object_templates.h" #include "song_editor.h" #include "main_window.h" #include "pattern.h" diff --git a/src/core/piano_widget.cpp b/src/core/piano_widget.cpp index 150a52b30..afe66b31a 100644 --- a/src/core/piano_widget.cpp +++ b/src/core/piano_widget.cpp @@ -48,6 +48,7 @@ #include "piano_widget.h" +#include "automatable_object_templates.h" #include "instrument_track.h" #include "midi.h" #include "templates.h" diff --git a/src/core/sample_play_handle.cpp b/src/core/sample_play_handle.cpp index 9bac56cc6..3dbb18eb4 100644 --- a/src/core/sample_play_handle.cpp +++ b/src/core/sample_play_handle.cpp @@ -31,7 +31,6 @@ #include "pattern.h" #include "sample_buffer.h" #include "sample_track.h" -#include "buffer_allocator.h" #include "audio_port.h" @@ -132,8 +131,7 @@ void samplePlayHandle::play( const fpab_t _frame_base, bool ) if( !( m_track && m_track->muted() ) && !( m_bbTrack && m_bbTrack->muted() ) ) { - sampleFrame * buf = bufferAllocator::alloc( - frames ); + sampleFrame * buf = new sampleFrame[frames]; volumeVector v = { { m_volume, m_volume #ifndef DISABLE_SURROUND , m_volume, m_volume @@ -143,7 +141,7 @@ void samplePlayHandle::play( const fpab_t _frame_base, bool ) engine::getMixer()->bufferToPort( buf, frames, _frame_base, v, m_audioPort ); - bufferAllocator::free( buf ); + delete[] buf; } m_frame += frames; diff --git a/src/core/setup_dialog.cpp b/src/core/setup_dialog.cpp index 92c81ad38..2382b95ec 100644 --- a/src/core/setup_dialog.cpp +++ b/src/core/setup_dialog.cpp @@ -61,6 +61,7 @@ #include "project_journal.h" #include "config_mgr.h" #include "embed.h" +#include "engine.h" #include "debug.h" #include "tooltip.h" #include "led_checkbox.h" diff --git a/src/core/song_editor.cpp b/src/core/song_editor.cpp index 8cc6e2d9d..df6bf77cd 100644 --- a/src/core/song_editor.cpp +++ b/src/core/song_editor.cpp @@ -69,6 +69,7 @@ #include "song_editor.h" +#include "automatable_object_templates.h" #include "automatable_slider.h" #include "bb_editor.h" #include "rename_dialog.h" diff --git a/src/core/surround_area.cpp b/src/core/surround_area.cpp index 57fa42668..f90d87c05 100644 --- a/src/core/surround_area.cpp +++ b/src/core/surround_area.cpp @@ -52,6 +52,7 @@ #include #include "surround_area.h" +#include "automatable_object_templates.h" #include "embed.h" #include "templates.h" #include "tooltip.h" diff --git a/src/core/track.cpp b/src/core/track.cpp index 74c31cb1e..cb698c99d 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -50,6 +50,7 @@ #include "track.h" +#include "automation_pattern.h" #include "track_container.h" #include "automation_track.h" #include "instrument_track.h" diff --git a/src/lib/buffer_allocator.cpp b/src/lib/buffer_allocator.cpp deleted file mode 100644 index 4efd7bf21..000000000 --- a/src/lib/buffer_allocator.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef SINGLE_SOURCE_COMPILE - -/* - * buffer_allocator.cpp - namespace bufferAllocator providing routines for own - * optimized memory-management for audio-buffers - * - * Copyright (c) 2005-2006 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - - -#include "qt3support.h" - -#ifdef QT4 - -#include -#include - -#else - -#include -#include -#include - -#define qSort qHeapSort - -#endif - -#include -#include - -#include "buffer_allocator.h" -#include "templates.h" -#include "mixer.h" -#include "debug.h" - - -struct bufDesc -{ - bool free; - char * origPtr; - void * buf; - Uint32 bytes; - Uint32 timesUsed; - -} ; - - -inline bool operator<( const bufDesc & _bd1, const bufDesc & _bd2 ) -{ - return( _bd1.timesUsed < _bd2.timesUsed ); -} - -#ifndef QT3 - -inline bool operator==( const bufDesc & _bd1, const bufDesc & _bd2 ) -{ - return( memcmp( &_bd1, &_bd2, sizeof( bufDesc ) ) == 0 ); -} - -#else - -inline bool operator!=( const bufDesc & _bd1, const bufDesc & _bd2 ) -{ - return( memcmp( &_bd1, &_bd2, sizeof( bufDesc ) ) != 0 ); -} - -#endif - - -static vlist s_buffers; -typedef vlist::iterator bufIt; - -static int s_freeBufs = 0; -static bool s_autoCleanupDisabled = FALSE; -static QMutex s_buffersMutex; - - -const int BUFFER_ALIGN = 16; -const int BUFFER_ALIGN_MASK = BUFFER_ALIGN - 1; - - - -void bufferAllocator::cleanUp( Uint16 _level ) -{ - // first insert all unused bufs into an array - vlist bufsToRemove; - for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it ) - { - if( ( *it ).free ) - { - bufsToRemove.push_back( *it ); - } - } - - // sort array by usage of each buffer - // ( operator<(...) compares bufDesc::timesUsed ) - qSort( bufsToRemove ); - - const Sint16 todo = tMin( s_buffers.size() - _level, - bufsToRemove.size() ); - - // now cleanup the first n elements of sorted array - for( Sint16 i = 0; i < todo; ++i ) - { - delete[] bufsToRemove[i].origPtr; - s_buffers.erase( qFind( s_buffers.begin(), s_buffers.end(), - bufsToRemove[i] ) ); - --s_freeBufs; - } - -#ifdef LMMS_DEBUG - //printf( "cleaned up %d buffers\n", todo ); -#endif -} - - - - -void bufferAllocator::free( void * _buf ) -{ - s_buffersMutex.lock(); - - // look for buffer - for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it ) - { - if( !( *it ).free && ( *it ).buf == _buf ) - { - ++( *it ).timesUsed; - ( *it ).free = TRUE; - ++s_freeBufs; - break; - } - } - - // do clean-up if neccessary - static const csize CLEANUP_LEVEL = static_cast( 768 / ( logf( - /*mixer::inst()->framesPerAudioBuffer()*/ - 128 ) / - logf( 2 ) ) ); - static int count = 0; - // only cleanup every 10th time, because otherwise there's a lot of - // overhead e.g. when freeing a lot of single buffers - if( s_autoCleanupDisabled == FALSE && - s_buffers.size() > CLEANUP_LEVEL && ++count > 10 ) - { - cleanUp( CLEANUP_LEVEL ); - count = 0; - } - - s_buffersMutex.unlock(); -} - - - - -void * bufferAllocator::allocBytes( Uint32 _bytes ) -{ - QMutexLocker ml( &s_buffersMutex ); - - // there's a low probability that we find a matching buffer, if there're - // less than 2 bufs available, so do not search - this speeds up - // processes like pattern-freezing because this way we do not have to - // search for a free buffer in an array, containing several - // 10.000 buffers - if( (csize) s_freeBufs > s_buffers.size() / 10 ) - { - bufIt free_buf = s_buffers.end(); - - // look whether there's a buffer matching to the one wanted and - // find out the most used one (higher chances for being in CPU- - // cache) - for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it ) - { - if( ( *it ).free && ( *it ).bytes == _bytes ) - { - if( free_buf == s_buffers.end() || - ( *it ).timesUsed > - ( *free_buf ).timesUsed ) - { - free_buf = it; - } - } - } - - if( free_buf != s_buffers.end() ) - { - --s_freeBufs; - ( *free_buf ).free = FALSE; - return( ( *free_buf ).buf ); - } - } - - - // got nothing so far, so we'll alloc a new (aligned) buf - bufDesc d = { FALSE, new char[_bytes + BUFFER_ALIGN], NULL, _bytes, 0 }; - d.buf = (void *)( (size_t) d.origPtr + ( BUFFER_ALIGN - - ( (size_t) d.origPtr & - BUFFER_ALIGN_MASK ) ) ); - s_buffers.push_back( d ); - return( d.buf ); -} - - - - -void bufferAllocator::disableAutoCleanup( bool _disabled ) -{ - s_autoCleanupDisabled = _disabled; -} - - -#endif diff --git a/src/lmms_single_source.cpp b/src/lmms_single_source.cpp index eff314158..9cbcef877 100644 --- a/src/lmms_single_source.cpp +++ b/src/lmms_single_source.cpp @@ -4,7 +4,6 @@ #include "src/core/effect_tab_widget.cpp" #include "src/core/midi_tab_widget.cpp" #include "src/lib/string_pair_drag.cpp" -#include "src/lib/buffer_allocator.cpp" #include "src/lib/journalling_object.cpp" #include "src/lib/project_journal.cpp" #include "src/lib/embed.cpp" diff --git a/src/tracks/instrument_track.cpp b/src/tracks/instrument_track.cpp index f241720d8..f9c64d3d9 100644 --- a/src/tracks/instrument_track.cpp +++ b/src/tracks/instrument_track.cpp @@ -69,6 +69,7 @@ #include "arp_and_chords_tab_widget.h" #include "instrument.h" #include "audio_port.h" +#include "automation_pattern.h" #include "midi_client.h" #include "midi_port.h" #include "midi_tab_widget.h" diff --git a/src/tracks/pattern.cpp b/src/tracks/pattern.cpp index 434901cc7..c6462f0b6 100644 --- a/src/tracks/pattern.cpp +++ b/src/tracks/pattern.cpp @@ -68,7 +68,6 @@ #include "tooltip.h" #include "bb_editor.h" #include "string_pair_drag.h" -#include "buffer_allocator.h" #include "main_window.h" @@ -1317,8 +1316,6 @@ patternFreezeThread::~patternFreezeThread() void patternFreezeThread::run( void ) { - bufferAllocator::disableAutoCleanup( TRUE ); - // create and install audio-sample-recorder bool b; // we cannot create local copy, because at a later stage @@ -1368,8 +1365,6 @@ void patternFreezeThread::run( void ) m_pattern->m_frozenPatternMutex.unlock(); } - bufferAllocator::disableAutoCleanup( FALSE ); - // restore original audio-device engine::getMixer()->restoreAudioDevice(); diff --git a/src/tracks/sample_track.cpp b/src/tracks/sample_track.cpp index c58c22301..cef54f25a 100644 --- a/src/tracks/sample_track.cpp +++ b/src/tracks/sample_track.cpp @@ -49,9 +49,11 @@ #include "sample_track.h" #include "song_editor.h" #include "embed.h" +#include "engine.h" #include "templates.h" #include "tooltip.h" #include "audio_port.h" +#include "automation_pattern.h" #include "sample_play_handle.h" #include "string_pair_drag.h" #include "knob.h" diff --git a/src/widgets/automatable_button.cpp b/src/widgets/automatable_button.cpp index 9f6dcfac9..99b7750ff 100644 --- a/src/widgets/automatable_button.cpp +++ b/src/widgets/automatable_button.cpp @@ -45,6 +45,7 @@ #endif +#include "automatable_object_templates.h" #include "embed.h" @@ -296,7 +297,7 @@ void automatableButtonGroup::setValue( const int _value ) #ifdef QT3 -#undef findIndex +#undef indexOf #endif diff --git a/src/widgets/automatable_slider.cpp b/src/widgets/automatable_slider.cpp index 9be9b5b7e..7c6e0cdc0 100644 --- a/src/widgets/automatable_slider.cpp +++ b/src/widgets/automatable_slider.cpp @@ -42,6 +42,7 @@ #endif +#include "automatable_object_templates.h" #include "embed.h" diff --git a/src/widgets/combobox.cpp b/src/widgets/combobox.cpp index 6b602567d..b83e544b7 100644 --- a/src/widgets/combobox.cpp +++ b/src/widgets/combobox.cpp @@ -26,6 +26,7 @@ #include "combobox.h" +#include "automatable_object_templates.h" #include "templates.h" #include "embed.h" #include "gui_templates.h" diff --git a/src/widgets/effect_label.cpp b/src/widgets/effect_label.cpp index bf7a3b06d..8918faece 100644 --- a/src/widgets/effect_label.cpp +++ b/src/widgets/effect_label.cpp @@ -29,6 +29,7 @@ #include "effect_label.h" #include "sample_track.h" #include "embed.h" +#include "engine.h" #include "gui_templates.h" #include "rename_dialog.h" #include "main_window.h" diff --git a/src/widgets/knob.cpp b/src/widgets/knob.cpp index 75b5a94e9..947a4432e 100644 --- a/src/widgets/knob.cpp +++ b/src/widgets/knob.cpp @@ -66,6 +66,7 @@ #include #include "knob.h" +#include "automatable_object_templates.h" /*#include "midi_client.h"*/ #include "embed.h" #include "spc_bg_hndl_widget.h" diff --git a/src/widgets/lcd_spinbox.cpp b/src/widgets/lcd_spinbox.cpp index 85ddcafd8..e4c4f6a04 100644 --- a/src/widgets/lcd_spinbox.cpp +++ b/src/widgets/lcd_spinbox.cpp @@ -46,6 +46,7 @@ #include "lcd_spinbox.h" +#include "automatable_object_templates.h" #include "embed.h" #include "gui_templates.h" #include "templates.h" diff --git a/src/widgets/led_checkbox.cpp b/src/widgets/led_checkbox.cpp index 8fb2a9565..584f14c49 100644 --- a/src/widgets/led_checkbox.cpp +++ b/src/widgets/led_checkbox.cpp @@ -42,6 +42,7 @@ #include "led_checkbox.h" +#include "automatable_object_templates.h" #include "embed.h" #include "gui_templates.h" #include "spc_bg_hndl_widget.h" diff --git a/src/widgets/pixmap_button.cpp b/src/widgets/pixmap_button.cpp index 0979e8b39..c792aab69 100644 --- a/src/widgets/pixmap_button.cpp +++ b/src/widgets/pixmap_button.cpp @@ -41,6 +41,7 @@ #include "pixmap_button.h" +#include "automatable_object_templates.h" #include "embed.h" diff --git a/src/widgets/rack_plugin.cpp b/src/widgets/rack_plugin.cpp index d2856aa99..ed7fe9a2a 100644 --- a/src/widgets/rack_plugin.cpp +++ b/src/widgets/rack_plugin.cpp @@ -59,6 +59,7 @@ #include "tooltip.h" #include "effect_control_dialog.h" #include "embed.h" +#include "engine.h" #include "gui_templates.h" #include "main_window.h" diff --git a/src/widgets/tempo_sync_knob.cpp b/src/widgets/tempo_sync_knob.cpp index c6ccd1041..46a907836 100644 --- a/src/widgets/tempo_sync_knob.cpp +++ b/src/widgets/tempo_sync_knob.cpp @@ -47,6 +47,7 @@ #include "tempo_sync_knob.h" +#include "automatable_object_templates.h" #include "song_editor.h" #include "embed.h" #include "main_window.h" @@ -76,7 +77,10 @@ tempoSyncKnob::tempoSyncKnob( int _knob_num, QWidget * _parent, tempoSyncKnob::~tempoSyncKnob() { - m_custom->deleteLater(); + if( m_custom ) + { + m_custom->deleteLater(); + } } diff --git a/src/widgets/visualization_widget.cpp b/src/widgets/visualization_widget.cpp index d5fb9f8f8..dc4d806e1 100644 --- a/src/widgets/visualization_widget.cpp +++ b/src/widgets/visualization_widget.cpp @@ -46,7 +46,6 @@ #include "visualization_widget.h" #include "embed.h" #include "engine.h" -#include "buffer_allocator.h" #include "templates.h" #include "tooltip.h" @@ -68,7 +67,7 @@ visualizationWidget::visualizationWidget( const QPixmap & _bg, QWidget * _p, const fpab_t frames = engine::getMixer()->framesPerAudioBuffer(); - m_buffer = bufferAllocator::alloc( frames ); + m_buffer = new surroundSampleFrame[frames]; engine::getMixer()->clearAudioBuffer( m_buffer, frames ); @@ -94,6 +93,7 @@ visualizationWidget::visualizationWidget( const QPixmap & _bg, QWidget * _p, visualizationWidget::~visualizationWidget() { + delete[] m_buffer; } diff --git a/src/widgets/volume_knob.cpp b/src/widgets/volume_knob.cpp index f49dc2f02..b866a8da6 100644 --- a/src/widgets/volume_knob.cpp +++ b/src/widgets/volume_knob.cpp @@ -28,8 +28,10 @@ #include #include "volume_knob.h" +#include "automatable_object_templates.h" #include "main_window.h" #include "config_mgr.h" +#include "engine.h" #include "text_float.h" #include "string_pair_drag.h"