From f7009c3afd27dfca20beb0fb274ce38d4f08ed6c Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Mon, 18 Dec 2006 16:05:08 +0000 Subject: [PATCH] bugfixes and improvements git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@440 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 35 +++++++++ include/effect_lib.h | 77 +++++++++++++++---- include/note.h | 4 +- .../bassbooster_control_dialog.cpp | 48 ++++++++---- .../bass_booster/bassbooster_control_dialog.h | 8 +- .../plucked_string_synth.h | 4 +- plugins/vestige/vestige.cpp | 38 ++++++--- plugins/vestige/vestige.h | 8 ++ src/core/instrument.cpp | 1 + src/core/mixer.cpp | 13 +--- src/lib/oscillator.cpp | 12 +-- src/tracks/instrument_track.cpp | 7 +- 12 files changed, 190 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed48b9dcf..5f3a153ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2006-12-18 Tobias Doerffel + + * plugins/bass_booster/bassboster_control_dialog.h: + * plugins/bass_booster/bassboster_control_dialog.cpp: + set changed parameters directly using new set...-methods of effect-lib + (preserves current effect-state and therefore avoids clicks in sound- + stream) + + * include/effect_lib.h: + - renamed class "base" to "monoBase" + - monoToStereoAdaptor can now have different effects for the two + channels + - added stereoToMonoAdaptor + - extended baseBoost-class by several methods + + * plugins/vestige/vestige.h: + * plugins/vestige/vestige.cpp: + added note-state-array for handling sequences of "note-on note-off" + events while the according note is already on which for example is the + case when placing the two notes at the same key next to each other - + until now the plugin started playing the second note but stopped + immediately as the note-off-event of the first note arrived later than + the note-on-event of the second one + + * src/core/instrument.cpp: + always call invalidate() in destructor so (instrumentPlayHandle- + driven) plugins do not have to care about it + + * src/tracks/instrument_track.cpp: + make sure value returned by masterKey() is within allowed range + + * src/core/mixer.cpp: + fixed bug which caused LMMS to crash when using parallelizing-level + above 1 and invalidated play-handles were existing + 2006-12-17 Tobias Doerffel * plugins/bass_booster/bassboster_control_dialog.cpp: diff --git a/include/effect_lib.h b/include/effect_lib.h index 4a17f5b26..a2895b5aa 100644 --- a/include/effect_lib.h +++ b/include/effect_lib.h @@ -1,5 +1,5 @@ /* - * effect_lib.h - library with simple inline-effects + * effect_lib.h - library with template-based inline-effects * * Copyright (c) 2006 Tobias Doerffel * @@ -32,11 +32,11 @@ namespace effectLib { template - class base + class monoBase { public: typedef SAMPLE sampleType; - virtual ~base() + virtual ~monoBase() { } virtual SAMPLE nextSample( const SAMPLE _in ) const = 0; @@ -54,18 +54,25 @@ namespace effectLib SAMPLE & _in_right ) const = 0; } ; - template - class monoToStereoAdaptor : public stereoBase + template + class monoToStereoAdaptor : public stereoBase { public: - typedef typename FX::sampleType sampleType; + typedef typename FXL::sampleType sampleType; - monoToStereoAdaptor( const FX & _mono_fx ) : + monoToStereoAdaptor( const FXL & _mono_fx ) : m_leftFX( _mono_fx ), m_rightFX( _mono_fx ) { } + monoToStereoAdaptor( const FXL & _left_fx, + const FXR & _right_fx ) : + m_leftFX( _left_fx ), + m_rightFX( _right_fx ) + { + } + virtual void nextSample( sampleType & _in_left, sampleType & _in_right ) const { @@ -73,9 +80,42 @@ namespace effectLib _in_right = m_rightFX.nextSample( _in_right ); } + FXL & leftFX( void ) + { + return( m_leftFX ); + } + + FXR & rightFX( void ) + { + return( m_rightFX ); + } + private: - FX m_leftFX; - FX m_rightFX; + FXL m_leftFX; + FXR m_rightFX; + } ; + + + template + class stereoToMonoAdaptor : public monoBase + { + public: + typedef typename FX::sampleType sampleType; + + stereoToMonoAdaptor( const FX & _stereo_fx ) : + m_FX( _stereo_fx ) + { + } + + virtual sampleType nextSample( const sampleType _in ) const + { + sampleType s[2] = { _in, _in }; + m_FX.nextSample( s[0], s[1] ); + return( ( s[0] + s[1] ) / 2.0f ); + } + + private: + FX m_FX; } ; @@ -87,17 +127,19 @@ namespace effectLib template - class bassBoost : public base + class bassBoost : public monoBase { public: bassBoost( const float _selectivity, const float _gain, - const float _ratio ) : - m_selectivity( _selectivity ), + const float _ratio, + const bassBoost & _orig = + bassBoost() ) : + m_selectivity( tMax( _selectivity, 10.0f ) ), m_gain1( 1.0f / ( m_selectivity + 1.0f ) ), m_gain2( _gain ), m_ratio( _ratio ), - m_cap( 0.0f ) + m_cap( _orig.m_cap ) { } @@ -112,7 +154,7 @@ namespace effectLib m_gain2/* )*/ ); } -/* void setSelectivity( const float _selectivity ) + void setSelectivity( const float _selectivity ) { m_selectivity = _selectivity; m_gain1 = 1.0f / ( m_selectivity + 1.0f ); @@ -126,9 +168,14 @@ namespace effectLib void setRatio( const float _ratio ) { m_ratio = _ratio; - }*/ + } private: + bassBoost() : + m_cap( 0.0f ) + { + } + float m_selectivity; float m_gain1; float m_gain2; diff --git a/include/note.h b/include/note.h index fa2fc537a..971341cbf 100644 --- a/include/note.h +++ b/include/note.h @@ -85,8 +85,8 @@ const octaves MAX_OCTAVE = OCTAVE_8; const int WHITE_KEYS_PER_OCTAVE = 7; const int BLACK_KEYS_PER_OCTAVE = 5; const int NOTES_PER_OCTAVE = WHITE_KEYS_PER_OCTAVE + BLACK_KEYS_PER_OCTAVE; -const int OCTAVES = 9; - +const int OCTAVES = MAX_OCTAVE+1; +const int NOTES = OCTAVES*NOTES_PER_OCTAVE; class knob; diff --git a/plugins/bass_booster/bassbooster_control_dialog.cpp b/plugins/bass_booster/bassbooster_control_dialog.cpp index 4037dbbe1..8a7e1325f 100644 --- a/plugins/bass_booster/bassbooster_control_dialog.cpp +++ b/plugins/bass_booster/bassbooster_control_dialog.cpp @@ -52,7 +52,7 @@ bassBoosterControlDialog::bassBoosterControlDialog( QWidget * _parent, m_freqKnob->setLabel( tr( "FREQ" ) ); m_freqKnob->setHintText( tr( "Frequency:" ) + " ", "Hz" ); connect( m_freqKnob, SIGNAL( valueChanged( float ) ), - this, SLOT( changeFrequency( float ) ) ); + this, SLOT( changeFrequency( void ) ) ); m_gainKnob = new knob( knobBright_26, this, tr( "Gain" ), eng(), NULL ); m_gainKnob->setRange( 0.1f, 5.0f, 0.1f ); @@ -60,7 +60,7 @@ bassBoosterControlDialog::bassBoosterControlDialog( QWidget * _parent, m_gainKnob->setLabel( tr( "GAIN" ) ); m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); connect( m_gainKnob, SIGNAL( valueChanged( float ) ), - this, SLOT( changeGain( float ) ) ); + this, SLOT( changeGain( void ) ) ); m_ratioKnob = new knob( knobBright_26, this, tr( "Ratio" ), eng(), NULL ); @@ -69,49 +69,69 @@ bassBoosterControlDialog::bassBoosterControlDialog( QWidget * _parent, m_ratioKnob->setLabel( tr( "RATIO" ) ); m_ratioKnob->setHintText( tr( "Ratio:" ) + " ", "" ); connect( m_ratioKnob, SIGNAL( valueChanged( float ) ), - this, SLOT( changeRatio( float ) ) ); + this, SLOT( changeRatio( void ) ) ); l->addWidget( m_freqKnob ); l->addWidget( m_gainKnob ); l->addWidget( m_ratioKnob ); - updateEffect(); + changeFrequency(); + changeGain(); + changeRatio(); } -void bassBoosterControlDialog::changeFrequency( float ) +void bassBoosterControlDialog::changeFrequency( void ) { - updateEffect(); + m_effect->m_bbFX.leftFX().setSelectivity( m_freqKnob->value() ); + m_effect->m_bbFX.rightFX().setSelectivity( m_freqKnob->value() ); } -void bassBoosterControlDialog::changeGain( float ) +void bassBoosterControlDialog::changeGain( void ) { - updateEffect(); + m_effect->m_bbFX.leftFX().setGain( m_gainKnob->value() ); + m_effect->m_bbFX.rightFX().setGain( m_gainKnob->value() ); } -void bassBoosterControlDialog::changeRatio( float ) +void bassBoosterControlDialog::changeRatio( void ) { - updateEffect(); + m_effect->m_bbFX.leftFX().setRatio( m_ratioKnob->value() ); + m_effect->m_bbFX.rightFX().setRatio( m_ratioKnob->value() ); } +/* void bassBoosterControlDialog::updateEffect( void ) { - // TODO: try to preserve effect and just change params - m_effect->m_bbFX = effectLib::bassBoost<>( m_freqKnob->value(), - m_gainKnob->value(), m_ratioKnob->value() ); + //m_effect->m_bbFX = effectLib::bassBoost<>( m_freqKnob->value(), + // m_gainKnob->value(), m_ratioKnob->value() ); + m_effect->m_bbFX = effectLib::monoToStereoAdaptor< + effectLib::bassBoost<> >( + effectLib::bassBoost<>( m_freqKnob->value(), + m_gainKnob->value(), m_ratioKnob->value(), + m_effect->m_bbFX.leftFX() ), + effectLib::bassBoost<>( m_freqKnob->value(), + m_gainKnob->value(), m_ratioKnob->value(), + m_effect->m_bbFX.rightFX() ) + ); + m_effect->m_bbFX.leftFX().setSelectivity( m_freqKnob->value() ); + m_effect->m_bbFX.rightFX().setSelectivity( m_freqKnob->value() ); + m_effect->m_bbFX.leftFX().setGain( m_gainKnob->value() ); + m_effect->m_bbFX.rightFX().setGain( m_gainKnob->value() ); + m_effect->m_bbFX.leftFX().setRatio( m_ratioKnob->value() ); + m_effect->m_bbFX.rightFX().setRatio( m_ratioKnob->value() ); } - +*/ diff --git a/plugins/bass_booster/bassbooster_control_dialog.h b/plugins/bass_booster/bassbooster_control_dialog.h index 9f159ff5c..03c94cd7d 100644 --- a/plugins/bass_booster/bassbooster_control_dialog.h +++ b/plugins/bass_booster/bassbooster_control_dialog.h @@ -55,14 +55,12 @@ public: private slots: - void changeFrequency( float ); - void changeGain( float ); - void changeRatio( float ); + void changeFrequency( void ); + void changeGain( void ); + void changeRatio( void ); private: - void updateEffect( void ); - bassBoosterEffect * m_effect; knob * m_freqKnob; knob * m_gainKnob; diff --git a/plugins/plucked_string_synth/plucked_string_synth.h b/plugins/plucked_string_synth/plucked_string_synth.h index 8986b9f93..51c27b31e 100644 --- a/plugins/plucked_string_synth/plucked_string_synth.h +++ b/plugins/plucked_string_synth/plucked_string_synth.h @@ -1,6 +1,6 @@ /* - * plucked_string_sytn.h - declaration of class pluckedStringSynth which - * is a synth for plucked string-sounds + * plucked_string_synth.h - declaration of class pluckedStringSynth which + * is a synth for plucked string-sounds * * Copyright (c) 2004-2006 Tobias Doerffel * diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 62a9e05cc..b42a37630 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -88,8 +88,8 @@ plugin::descriptor vestige_plugin_descriptor = QPixmap * vestigeInstrument::s_artwork = NULL; -vestigeInstrument::vestigeInstrument( instrumentTrack * _channel_track ) : - instrument( _channel_track, &vestige_plugin_descriptor ), +vestigeInstrument::vestigeInstrument( instrumentTrack * _instrument_track ) : + instrument( _instrument_track, &vestige_plugin_descriptor ), specialBgHandlingWidget( PLUGIN_NAME::getIconPixmap( "artwork" ) ), m_plugin( NULL ), m_pluginMutex() @@ -153,6 +153,11 @@ vestigeInstrument::vestigeInstrument( instrumentTrack * _channel_track ) : connect( note_off_all_btn, SIGNAL( clicked() ), this, SLOT( noteOffAll() ) ); + for( int i = 0; i < NOTES; ++i ) + { + m_noteStates[i] = OFF; + } + // now we need a play-handle which cares for calling play() instrumentPlayHandle * iph = new instrumentPlayHandle( this ); eng()->getMixer()->addPlayHandle( iph ); @@ -163,9 +168,6 @@ vestigeInstrument::vestigeInstrument( instrumentTrack * _channel_track ) : vestigeInstrument::~vestigeInstrument() { - // this single call automates the rest of cleanup like trashing our - // play-handle and so on - invalidate(); closePlugin(); } @@ -339,8 +341,18 @@ void vestigeInstrument::playNote( notePlayHandle * _n, bool ) m_pluginMutex.lock(); if( _n->totalFramesPlayed() == 0 && m_plugin != NULL ) { - m_plugin->enqueueMidiEvent( midiEvent( NOTE_ON, 0, - getInstrumentTrack()->masterKey( _n ), + const int k = getInstrumentTrack()->masterKey( _n ); + if( m_noteStates[k] > OFF ) + { + m_plugin->enqueueMidiEvent( midiEvent( NOTE_OFF, 0, + k, 0 ), 0 ); + m_noteStates[k] = IGNORE_NEXT_NOTEOFF; + } + else + { + m_noteStates[k] = ON; + } + m_plugin->enqueueMidiEvent( midiEvent( NOTE_ON, 0, k, _n->getVolume() ), _n->framesAhead() ); } m_pluginMutex.unlock(); @@ -354,9 +366,17 @@ void vestigeInstrument::deleteNotePluginData( notePlayHandle * _n ) m_pluginMutex.lock(); if( m_plugin != NULL ) { - m_plugin->enqueueMidiEvent( midiEvent( NOTE_OFF, 0, - getInstrumentTrack()->masterKey( _n ), + const int k = getInstrumentTrack()->masterKey( _n ); + if( m_noteStates[k] == ON ) + { + m_plugin->enqueueMidiEvent( midiEvent( NOTE_OFF, 0, k, 0 ), 0 ); + m_noteStates[k] = OFF; + } + else if( m_noteStates[k] == IGNORE_NEXT_NOTEOFF ) + { + m_noteStates[k] = ON; + } } m_pluginMutex.unlock(); } diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 4140f96fc..7ffa39fa0 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -103,6 +103,14 @@ private: static QPixmap * s_artwork; + enum states + { + OFF, + ON, + IGNORE_NEXT_NOTEOFF + } ; + states m_noteStates[NOTES]; + remoteVSTPlugin * m_plugin; QMutex m_pluginMutex; diff --git a/src/core/instrument.cpp b/src/core/instrument.cpp index 344def9d6..456542c7e 100644 --- a/src/core/instrument.cpp +++ b/src/core/instrument.cpp @@ -46,6 +46,7 @@ instrument::instrument( instrumentTrack * _instrument_track, instrument::~instrument() { + invalidate(); } diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index 4fe40f421..a45ffc6c1 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -295,23 +295,18 @@ const surroundSampleFrame * mixer::renderNextBuffer( void ) idx = 0; while( idx < m_playHandles.size() ) { - playHandle * n =m_playHandles[idx]; - if( n->supportsParallelizing() ) - { - ++idx; - continue; - } - else if( n->done() ) + playHandle * n = m_playHandles[idx]; + if( n->done() ) { delete n; m_playHandles.erase( m_playHandles.begin() + idx ); } - else + else if( !n->supportsParallelizing() ) { n->play(); - ++idx; } + ++idx; } for( playHandleVector::iterator it = par_hndls.begin(); it != par_hndls.end(); ++it ) diff --git a/src/lib/oscillator.cpp b/src/lib/oscillator.cpp index 024a30bd4..ed9e5bb4d 100644 --- a/src/lib/oscillator.cpp +++ b/src/lib/oscillator.cpp @@ -115,7 +115,7 @@ void oscillator::updatePM( sampleFrame * _ab, const fpab_t _frames, { m_subOsc->update( _ab, _frames, _chnl ); recalcPhase(); - float osc_coeff = *m_freq * *m_detuning; + const float osc_coeff = *m_freq * *m_detuning; for( fpab_t frame = 0; frame < _frames; ++frame ) { @@ -132,7 +132,7 @@ void oscillator::updateAM( sampleFrame * _ab, const fpab_t _frames, { m_subOsc->update( _ab, _frames, _chnl ); recalcPhase(); - float osc_coeff = *m_freq * *m_detuning; + const float osc_coeff = *m_freq * *m_detuning; for( fpab_t frame = 0; frame < _frames; ++frame ) { @@ -148,7 +148,7 @@ void oscillator::updateMix( sampleFrame * _ab, const fpab_t _frames, { m_subOsc->update( _ab, _frames, _chnl ); recalcPhase(); - float osc_coeff = *m_freq * *m_detuning; + const float osc_coeff = *m_freq * *m_detuning; for( fpab_t frame = 0; frame < _frames; ++frame ) { @@ -163,9 +163,9 @@ void oscillator::updateMix( sampleFrame * _ab, const fpab_t _frames, void oscillator::updateSync( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ) { - float sub_osc_coeff = m_subOsc->syncInit( _ab, _frames, _chnl ); + const float sub_osc_coeff = m_subOsc->syncInit( _ab, _frames, _chnl ); recalcPhase(); - float osc_coeff = *m_freq * *m_detuning; + const float osc_coeff = *m_freq * *m_detuning; for( fpab_t frame = 0; frame < _frames ; ++frame ) { @@ -187,7 +187,7 @@ void oscillator::updateFM( sampleFrame * _ab, const fpab_t _frames, { m_subOsc->update( _ab, _frames, _chnl ); recalcPhase(); - float osc_coeff = *m_freq * *m_detuning; + const float osc_coeff = *m_freq * *m_detuning; for( fpab_t frame = 0; frame < _frames; ++frame ) { diff --git a/src/tracks/instrument_track.cpp b/src/tracks/instrument_track.cpp index 6a54be35a..15f07bb7b 100644 --- a/src/tracks/instrument_track.cpp +++ b/src/tracks/instrument_track.cpp @@ -134,7 +134,7 @@ instrumentTrack::instrumentTrack( trackContainer * _tc ) : #endif { m_notesMutex.lock(); - for( int i = 0; i < NOTES_PER_OCTAVE * OCTAVES; ++i ) + for( int i = 0; i < NOTES; ++i ) { m_notes[i] = NULL; } @@ -899,7 +899,8 @@ int instrumentTrack::masterKey( notePlayHandle * _n ) const { int key = baseTone() + baseOctave() * NOTES_PER_OCTAVE + eng()->getSongEditor()->masterPitch(); - return( _n->key() - ( key - A - DEFAULT_OCTAVE * NOTES_PER_OCTAVE ) ); + return( tLimit( _n->key() - + ( key - A - DEFAULT_OCTAVE * NOTES_PER_OCTAVE ), 0, NOTES ) ); } @@ -1288,7 +1289,7 @@ void instrumentTrack::invalidateAllMyNPH( void ) m_trackType = NULL_TRACK; m_notesMutex.lock(); - for( int i = 0; i < NOTES_PER_OCTAVE * OCTAVES; ++i ) + for( int i = 0; i < NOTES; ++i ) { m_notes[i] = NULL; }