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:
Martin Pavelek
2021-07-04 13:14:59 +02:00
committed by GitHub
parent f8d7fa3b87
commit 6f8c6dba82
14 changed files with 580 additions and 75 deletions

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB