bugfixes and improvements

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@440 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2006-12-18 16:05:08 +00:00
parent 64aa78c4f6
commit f7009c3afd
12 changed files with 190 additions and 65 deletions

View File

@@ -1,3 +1,38 @@
2006-12-18 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* 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 <tobydox/at/users/dot/sourceforge/dot/net>
* plugins/bass_booster/bassboster_control_dialog.cpp:

View File

@@ -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 <tobydox/at/users.sourceforge.net>
*
@@ -32,11 +32,11 @@
namespace effectLib
{
template<typename SAMPLE = sample_t>
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 FX>
class monoToStereoAdaptor : public stereoBase<typename FX::sampleType>
template<class FXL, class FXR = FXL>
class monoToStereoAdaptor : public stereoBase<typename FXL::sampleType>
{
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 FX>
class stereoToMonoAdaptor : public monoBase<typename FX::sampleType>
{
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<typename SAMPLE = sample_t>
class bassBoost : public base<SAMPLE>
class bassBoost : public monoBase<SAMPLE>
{
public:
bassBoost( const float _selectivity,
const float _gain,
const float _ratio ) :
m_selectivity( _selectivity ),
const float _ratio,
const bassBoost<SAMPLE> & _orig =
bassBoost<SAMPLE>() ) :
m_selectivity( tMax<SAMPLE>( _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;

View File

@@ -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;

View File

@@ -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() );
}
*/

View File

@@ -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;

View File

@@ -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 <tobydox/at/users.sourceforge.net>
*

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -46,6 +46,7 @@ instrument::instrument( instrumentTrack * _instrument_track,
instrument::~instrument()
{
invalidate();
}

View File

@@ -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 )

View File

@@ -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 )
{

View File

@@ -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<int>( _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;
}