Alias-free oscillators (#5826)
Add a band-limited, alias-free wavetable oscillator option to the `Oscillator` class. Use it by default for Triple Oscillator. Savefiles which do not have this feature enabled (e.g. old savefiles) will be loaded without this feature to keep the sound consistent. Original author: @curlymorphic. Fixed: @he29-net.
This commit is contained in:
@@ -87,6 +87,7 @@ OscillatorObject::OscillatorObject( Model * _parent, int _idx ) :
|
||||
m_modulationAlgoModel( Oscillator::SignalMix, 0,
|
||||
Oscillator::NumModulationAlgos-1, this,
|
||||
tr( "Modulation type %1" ).arg( _idx+1 ) ),
|
||||
m_useWaveTableModel(true),
|
||||
|
||||
m_sampleBuffer( new SampleBuffer ),
|
||||
m_volumeLeft( 0.0f ),
|
||||
@@ -94,7 +95,8 @@ OscillatorObject::OscillatorObject( Model * _parent, int _idx ) :
|
||||
m_detuningLeft( 0.0f ),
|
||||
m_detuningRight( 0.0f ),
|
||||
m_phaseOffsetLeft( 0.0f ),
|
||||
m_phaseOffsetRight( 0.0f )
|
||||
m_phaseOffsetRight( 0.0f ),
|
||||
m_useWaveTable( true )
|
||||
{
|
||||
// Connect knobs with Oscillators' inputs
|
||||
connect( &m_volumeModel, SIGNAL( dataChanged() ),
|
||||
@@ -120,6 +122,9 @@ OscillatorObject::OscillatorObject( Model * _parent, int _idx ) :
|
||||
this, SLOT( updatePhaseOffsetRight() ), Qt::DirectConnection );
|
||||
connect( &m_stereoPhaseDetuningModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updatePhaseOffsetLeft() ), Qt::DirectConnection );
|
||||
connect ( &m_useWaveTableModel, SIGNAL(dataChanged()),
|
||||
this, SLOT( updateUseWaveTable()));
|
||||
|
||||
updatePhaseOffsetLeft();
|
||||
updatePhaseOffsetRight();
|
||||
|
||||
@@ -206,6 +211,11 @@ void OscillatorObject::updatePhaseOffsetRight()
|
||||
m_phaseOffsetRight = m_phaseOffsetModel.value() / 360.0f;
|
||||
}
|
||||
|
||||
void OscillatorObject::updateUseWaveTable()
|
||||
{
|
||||
m_useWaveTable = m_useWaveTableModel.value();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -253,6 +263,8 @@ void TripleOscillator::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
"wavetype" + is );
|
||||
m_osc[i]->m_modulationAlgoModel.saveSettings( _doc, _this,
|
||||
"modalgo" + QString::number( i+1 ) );
|
||||
m_osc[i]->m_useWaveTableModel.saveSettings( _doc, _this,
|
||||
"useWaveTable" + QString::number (i+1 ) );
|
||||
_this.setAttribute( "userwavefile" + is,
|
||||
m_osc[i]->m_sampleBuffer->audioFile() );
|
||||
}
|
||||
@@ -279,6 +291,8 @@ void TripleOscillator::loadSettings( const QDomElement & _this )
|
||||
is );
|
||||
m_osc[i]->m_modulationAlgoModel.loadSettings( _this,
|
||||
"modalgo" + QString::number( i+1 ) );
|
||||
m_osc[i]->m_useWaveTableModel.loadSettings( _this,
|
||||
"useWaveTable" + QString::number (i+1 ) );
|
||||
m_osc[i]->m_sampleBuffer->setAudioFile( _this.attribute(
|
||||
"userwavefile" + is ) );
|
||||
}
|
||||
@@ -316,6 +330,7 @@ void TripleOscillator::playNote( NotePlayHandle * _n,
|
||||
m_osc[i]->m_detuningLeft,
|
||||
m_osc[i]->m_phaseOffsetLeft,
|
||||
m_osc[i]->m_volumeLeft );
|
||||
oscs_l[i]->setUseWaveTable(m_osc[i]->m_useWaveTable);
|
||||
oscs_r[i] = new Oscillator(
|
||||
&m_osc[i]->m_waveShapeModel,
|
||||
&m_osc[i]->m_modulationAlgoModel,
|
||||
@@ -323,6 +338,7 @@ void TripleOscillator::playNote( NotePlayHandle * _n,
|
||||
m_osc[i]->m_detuningRight,
|
||||
m_osc[i]->m_phaseOffsetRight,
|
||||
m_osc[i]->m_volumeRight );
|
||||
oscs_r[i]->setUseWaveTable(m_osc[i]->m_useWaveTable);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -334,6 +350,7 @@ void TripleOscillator::playNote( NotePlayHandle * _n,
|
||||
m_osc[i]->m_phaseOffsetLeft,
|
||||
m_osc[i]->m_volumeLeft,
|
||||
oscs_l[i + 1] );
|
||||
oscs_l[i]->setUseWaveTable(m_osc[i]->m_useWaveTable);
|
||||
oscs_r[i] = new Oscillator(
|
||||
&m_osc[i]->m_waveShapeModel,
|
||||
&m_osc[i]->m_modulationAlgoModel,
|
||||
@@ -342,6 +359,7 @@ void TripleOscillator::playNote( NotePlayHandle * _n,
|
||||
m_osc[i]->m_phaseOffsetRight,
|
||||
m_osc[i]->m_volumeRight,
|
||||
oscs_r[i + 1] );
|
||||
oscs_r[i]->setUseWaveTable(m_osc[i]->m_useWaveTable);
|
||||
}
|
||||
|
||||
oscs_l[i]->setUserWave( m_osc[i]->m_sampleBuffer );
|
||||
@@ -660,6 +678,15 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument,
|
||||
"usr_shape_inactive" ) );
|
||||
ToolTip::add( uwb, tr( "User-defined wave" ) );
|
||||
|
||||
PixmapButton * uwt = new PixmapButton( this, NULL );
|
||||
uwt->move( 110, btn_y );
|
||||
uwt->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"wavetable_active" ) );
|
||||
uwt->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"wavetable_inactive" ) );
|
||||
uwt->setCheckable(true);
|
||||
ToolTip::add( uwt, tr( "Use alias-free wavetable oscillators." ) );
|
||||
|
||||
automatableButtonGroup * wsbg =
|
||||
new automatableButtonGroup( this );
|
||||
|
||||
@@ -672,8 +699,9 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument,
|
||||
wsbg->addButton( white_noise_btn );
|
||||
wsbg->addButton( uwb );
|
||||
|
||||
|
||||
m_oscKnobs[i] = OscillatorKnobs( vk, pk, ck, flk, frk, pok,
|
||||
spdk, uwb, wsbg );
|
||||
spdk, uwb, wsbg, uwt );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,6 +739,9 @@ void TripleOscillatorView::modelChanged()
|
||||
&t->m_osc[i]->m_stereoPhaseDetuningModel );
|
||||
m_oscKnobs[i].m_waveShapeBtnGrp->setModel(
|
||||
&t->m_osc[i]->m_waveShapeModel );
|
||||
m_oscKnobs[i].m_multiBandWaveTableButton->setModel(
|
||||
&t->m_osc[i]->m_useWaveTableModel );
|
||||
|
||||
connect( m_oscKnobs[i].m_userWaveButton,
|
||||
SIGNAL( doubleClicked() ),
|
||||
t->m_osc[i], SLOT( oscUserDefWaveDblClick() ) );
|
||||
|
||||
@@ -60,6 +60,7 @@ private:
|
||||
FloatModel m_stereoPhaseDetuningModel;
|
||||
IntModel m_waveShapeModel;
|
||||
IntModel m_modulationAlgoModel;
|
||||
BoolModel m_useWaveTableModel;
|
||||
SampleBuffer* m_sampleBuffer;
|
||||
|
||||
float m_volumeLeft;
|
||||
@@ -71,6 +72,7 @@ private:
|
||||
// normalized offset -> x/360
|
||||
float m_phaseOffsetLeft;
|
||||
float m_phaseOffsetRight;
|
||||
bool m_useWaveTable;
|
||||
|
||||
friend class TripleOscillator;
|
||||
friend class TripleOscillatorView;
|
||||
@@ -84,6 +86,7 @@ private slots:
|
||||
void updateDetuningRight();
|
||||
void updatePhaseOffsetLeft();
|
||||
void updatePhaseOffsetRight();
|
||||
void updateUseWaveTable();
|
||||
|
||||
} ;
|
||||
|
||||
@@ -161,7 +164,8 @@ private:
|
||||
Knob * po,
|
||||
Knob * spd,
|
||||
PixmapButton * uwb,
|
||||
automatableButtonGroup * wsbg ) :
|
||||
automatableButtonGroup * wsbg,
|
||||
PixmapButton * wt) :
|
||||
m_volKnob( v ),
|
||||
m_panKnob( p ),
|
||||
m_coarseKnob( c ),
|
||||
@@ -170,7 +174,8 @@ private:
|
||||
m_phaseOffsetKnob( po ),
|
||||
m_stereoPhaseDetuningKnob( spd ),
|
||||
m_userWaveButton( uwb ),
|
||||
m_waveShapeBtnGrp( wsbg )
|
||||
m_waveShapeBtnGrp( wsbg ),
|
||||
m_multiBandWaveTableButton( wt )
|
||||
{
|
||||
}
|
||||
OscillatorKnobs()
|
||||
@@ -185,6 +190,7 @@ private:
|
||||
Knob * m_stereoPhaseDetuningKnob;
|
||||
PixmapButton * m_userWaveButton;
|
||||
automatableButtonGroup * m_waveShapeBtnGrp;
|
||||
PixmapButton * m_multiBandWaveTableButton;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
BIN
plugins/triple_oscillator/wavetable_active.png
Normal file
BIN
plugins/triple_oscillator/wavetable_active.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
plugins/triple_oscillator/wavetable_inactive.png
Normal file
BIN
plugins/triple_oscillator/wavetable_inactive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user