From c45aafc748e94582df6e19b4563497b352f46815 Mon Sep 17 00:00:00 2001 From: Wong Cho Ching Date: Fri, 24 Jan 2014 22:55:32 +0800 Subject: [PATCH] Make LFO controller accept custom waveforms --- include/LfoController.h | 9 ++ include/SampleBuffer.h | 3 +- include/graph.h | 2 +- plugins/bit_invader/bit_invader.cpp | 93 ++++++++++--------- plugins/bit_invader/bit_invader.h | 16 ++-- .../triple_oscillator/TripleOscillator.cpp | 3 +- plugins/vibed/vibed.cpp | 6 +- src/core/LfoController.cpp | 16 +++- src/core/SampleBuffer.cpp | 17 ++++ src/gui/LfoControllerDialog.cpp | 33 +++++-- src/gui/widgets/graph.cpp | 19 ++++ 11 files changed, 147 insertions(+), 70 deletions(-) diff --git a/include/LfoController.h b/include/LfoController.h index 45118e9e1..59bea8689 100644 --- a/include/LfoController.h +++ b/include/LfoController.h @@ -75,6 +75,8 @@ protected: sample_t (*m_sampleFunction)( const float ); +private: + SampleBuffer * m_userDefSampleBuffer; protected slots: void updateSampleFunction(); @@ -107,6 +109,13 @@ protected: automatableButtonGroup * m_waveBtnGrp; automatableButtonGroup * m_multiplierBtnGrp; + +private: + pixmapButton * m_userWaveBtn; + +private slots: + void askUserDefWave(); + } ; #endif diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index cd5a243e1..e42d3690e 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -172,7 +172,8 @@ public: return m_data; } - QString openAudioFile() const; + QString openAudioFile() const; + QString openAndSetAudioFile(); QString & toBase64( QString & _dst ) const; diff --git a/include/graph.h b/include/graph.h index 9be552f33..20437996e 100644 --- a/include/graph.h +++ b/include/graph.h @@ -151,7 +151,7 @@ public slots: void setWaveToSaw(); void setWaveToSquare(); void setWaveToNoise(); - //void setWaveToUser( ); + QString setWaveToUser( ); void smooth(); void normalize(); diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index df588eeb4..080c424f3 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -243,7 +243,7 @@ void bitInvader::normalize() const float f = fabsf( samples[i] ); if (f > max) { max = f; } } - normalizeFactor = 1.0 / max; + m_normalizeFactor = 1.0 / max; } @@ -270,7 +270,7 @@ void bitInvader::playNote( notePlayHandle * _n, } else { - factor = normalizeFactor; + factor = m_normalizeFactor; } _n->m_pluginData = new bSynth( @@ -350,69 +350,69 @@ bitInvaderView::bitInvaderView( Instrument * _instrument, m_graph->setPalette( pal ); - sinWaveBtn = new pixmapButton( this, tr( "Sine wave" ) ); - sinWaveBtn->move( 188, 120 ); - sinWaveBtn->setActiveGraphic( embed::getIconPixmap( + m_sinWaveBtn = new pixmapButton( this, tr( "Sine wave" ) ); + m_sinWaveBtn->move( 188, 120 ); + m_sinWaveBtn->setActiveGraphic( embed::getIconPixmap( "sin_wave_active" ) ); - sinWaveBtn->setInactiveGraphic( embed::getIconPixmap( + m_sinWaveBtn->setInactiveGraphic( embed::getIconPixmap( "sin_wave_inactive" ) ); - toolTip::add( sinWaveBtn, + toolTip::add( m_sinWaveBtn, tr( "Click for a sine-wave." ) ); - triangleWaveBtn = new pixmapButton( this, tr( "Triangle wave" ) ); - triangleWaveBtn->move( 188, 136 ); - triangleWaveBtn->setActiveGraphic( + m_triangleWaveBtn = new pixmapButton( this, tr( "Triangle wave" ) ); + m_triangleWaveBtn->move( 188, 136 ); + m_triangleWaveBtn->setActiveGraphic( embed::getIconPixmap( "triangle_wave_active" ) ); - triangleWaveBtn->setInactiveGraphic( + m_triangleWaveBtn->setInactiveGraphic( embed::getIconPixmap( "triangle_wave_inactive" ) ); - toolTip::add( triangleWaveBtn, + toolTip::add( m_triangleWaveBtn, tr( "Click here for a triangle-wave." ) ); - sawWaveBtn = new pixmapButton( this, tr( "Saw wave" ) ); - sawWaveBtn->move( 188, 152 ); - sawWaveBtn->setActiveGraphic( embed::getIconPixmap( + m_sawWaveBtn = new pixmapButton( this, tr( "Saw wave" ) ); + m_sawWaveBtn->move( 188, 152 ); + m_sawWaveBtn->setActiveGraphic( embed::getIconPixmap( "saw_wave_active" ) ); - sawWaveBtn->setInactiveGraphic( embed::getIconPixmap( + m_sawWaveBtn->setInactiveGraphic( embed::getIconPixmap( "saw_wave_inactive" ) ); - toolTip::add( sawWaveBtn, + toolTip::add( m_sawWaveBtn, tr( "Click here for a saw-wave." ) ); - sqrWaveBtn = new pixmapButton( this, tr( "Square wave" ) ); - sqrWaveBtn->move( 188, 168 ); - sqrWaveBtn->setActiveGraphic( embed::getIconPixmap( + m_sqrWaveBtn = new pixmapButton( this, tr( "Square wave" ) ); + m_sqrWaveBtn->move( 188, 168 ); + m_sqrWaveBtn->setActiveGraphic( embed::getIconPixmap( "square_wave_active" ) ); - sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap( + m_sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap( "square_wave_inactive" ) ); - toolTip::add( sqrWaveBtn, + toolTip::add( m_sqrWaveBtn, tr( "Click here for a square-wave." ) ); - whiteNoiseWaveBtn = new pixmapButton( this, + m_whiteNoiseWaveBtn = new pixmapButton( this, tr( "White noise wave" ) ); - whiteNoiseWaveBtn->move( 188, 184 ); - whiteNoiseWaveBtn->setActiveGraphic( + m_whiteNoiseWaveBtn->move( 188, 184 ); + m_whiteNoiseWaveBtn->setActiveGraphic( embed::getIconPixmap( "white_noise_wave_active" ) ); - whiteNoiseWaveBtn->setInactiveGraphic( + m_whiteNoiseWaveBtn->setInactiveGraphic( embed::getIconPixmap( "white_noise_wave_inactive" ) ); - toolTip::add( whiteNoiseWaveBtn, + toolTip::add( m_whiteNoiseWaveBtn, tr( "Click here for white-noise." ) ); - usrWaveBtn = new pixmapButton( this, tr( "User defined wave" ) ); - usrWaveBtn->move( 188, 200 ); - usrWaveBtn->setActiveGraphic( embed::getIconPixmap( + m_usrWaveBtn = new pixmapButton( this, tr( "User defined wave" ) ); + m_usrWaveBtn->move( 188, 200 ); + m_usrWaveBtn->setActiveGraphic( embed::getIconPixmap( "usr_wave_active" ) ); - usrWaveBtn->setInactiveGraphic( embed::getIconPixmap( + m_usrWaveBtn->setInactiveGraphic( embed::getIconPixmap( "usr_wave_inactive" ) ); - toolTip::add( usrWaveBtn, + toolTip::add( m_usrWaveBtn, tr( "Click here for a user-defined shape." ) ); - smoothBtn = new pixmapButton( this, tr( "Smooth" ) ); - smoothBtn->move( 35, 200 ); - smoothBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + m_smoothBtn = new pixmapButton( this, tr( "Smooth" ) ); + m_smoothBtn->move( 35, 200 ); + m_smoothBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth" ) ); - smoothBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + m_smoothBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth" ) ); - smoothBtn->setChecked( true ); - toolTip::add( smoothBtn, + m_smoothBtn->setChecked( true ); + toolTip::add( m_smoothBtn, tr( "Click here to smooth waveform." ) ); @@ -426,20 +426,20 @@ bitInvaderView::bitInvaderView( Instrument * _instrument, m_normalizeToggle->move( 55, 100 ); - connect( sinWaveBtn, SIGNAL (clicked () ), + connect( m_sinWaveBtn, SIGNAL (clicked () ), this, SLOT ( sinWaveClicked() ) ); - connect( triangleWaveBtn, SIGNAL ( clicked () ), + connect( m_triangleWaveBtn, SIGNAL ( clicked () ), this, SLOT ( triangleWaveClicked() ) ); - connect( sawWaveBtn, SIGNAL (clicked () ), + connect( m_sawWaveBtn, SIGNAL (clicked () ), this, SLOT ( sawWaveClicked() ) ); - connect( sqrWaveBtn, SIGNAL ( clicked () ), + connect( m_sqrWaveBtn, SIGNAL ( clicked () ), this, SLOT ( sqrWaveClicked() ) ); - connect( whiteNoiseWaveBtn, SIGNAL ( clicked () ), + connect( m_whiteNoiseWaveBtn, SIGNAL ( clicked () ), this, SLOT ( noiseWaveClicked() ) ); - connect( usrWaveBtn, SIGNAL ( clicked () ), + connect( m_usrWaveBtn, SIGNAL ( clicked () ), this, SLOT ( usrWaveClicked() ) ); - connect( smoothBtn, SIGNAL ( clicked () ), + connect( m_smoothBtn, SIGNAL ( clicked () ), this, SLOT ( smoothClicked() ) ); connect( m_interpolationToggle, SIGNAL( toggled( bool ) ), @@ -514,6 +514,9 @@ void bitInvaderView::noiseWaveClicked() void bitInvaderView::usrWaveClicked() { + QString fileName = m_graph->model()->setWaveToUser(); + toolTip::add( m_usrWaveBtn, fileName ); + engine::getSong()->setModified(); /* m_graph->model()->setWaveToNoise(); engine::getSong()->setModified(); diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index c38eb6b41..7a3217b47 100644 --- a/plugins/bit_invader/bit_invader.h +++ b/plugins/bit_invader/bit_invader.h @@ -99,7 +99,7 @@ private: BoolModel m_interpolation; BoolModel m_normalize; - float normalizeFactor; + float m_normalizeFactor; oscillator * m_osc; @@ -136,13 +136,13 @@ private: virtual void modelChanged(); knob * m_sampleLengthKnob; - pixmapButton * sinWaveBtn; - pixmapButton * triangleWaveBtn; - pixmapButton * sqrWaveBtn; - pixmapButton * sawWaveBtn; - pixmapButton * whiteNoiseWaveBtn; - pixmapButton * smoothBtn; - pixmapButton * usrWaveBtn; + pixmapButton * m_sinWaveBtn; + pixmapButton * m_triangleWaveBtn; + pixmapButton * m_sqrWaveBtn; + pixmapButton * m_sawWaveBtn; + pixmapButton * m_whiteNoiseWaveBtn; + pixmapButton * m_smoothBtn; + pixmapButton * m_usrWaveBtn; static QPixmap * s_artwork; diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index ae8510bab..20a017989 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -138,10 +138,9 @@ OscillatorObject::~OscillatorObject() void OscillatorObject::oscUserDefWaveDblClick() { - QString af = m_sampleBuffer->openAudioFile(); + QString af = m_sampleBuffer->openAndSetAudioFile(); if( af != "" ) { - m_sampleBuffer->setAudioFile( af ); // TODO: //toolTip::add( m_usrWaveBtn, m_sampleBuffer->audioFile() ); } diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index 7464e1daa..7872db7ca 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -728,9 +728,9 @@ void vibedView::noiseWaveClicked() void vibedView::usrWaveClicked() { - // TODO: load file - //m_graph->model()->setWaveToUser(); - //engine::getSongEditor()->setModified(); + QString fileName = m_graph->model()->setWaveToUser(); + toolTip::add( m_usrWaveBtn, fileName ); + engine::getSong()->setModified(); } diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp index a189d500e..fa14c8b2d 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -49,7 +49,8 @@ LfoController::LfoController( Model * _parent ) : m_duration( 1000 ), m_phaseCorrection( 0 ), m_phaseOffset( 0 ), - m_sampleFunction( &Oscillator::sinSample ) + m_sampleFunction( &Oscillator::sinSample ), + m_userDefSampleBuffer( new SampleBuffer ) { connect( &m_waveModel, SIGNAL( dataChanged() ), @@ -61,6 +62,7 @@ LfoController::LfoController( Model * _parent ) : LfoController::~LfoController() { + sharedObject::unref( m_userDefSampleBuffer ); m_baseModel.disconnect( this ); m_speedModel.disconnect( this ); m_amountModel.disconnect( this ); @@ -164,7 +166,9 @@ float LfoController::value( int _offset ) // 44100 frames/sec return m_baseModel.value() + ( m_amountModel.value() * - m_sampleFunction(sampleFrame) + ( m_sampleFunction != NULL ? + m_sampleFunction(sampleFrame): + m_userDefSampleBuffer->userWaveSample(sampleFrame) ) / 2.0f ); } @@ -196,6 +200,14 @@ void LfoController::updateSampleFunction() case Oscillator::WhiteNoise: m_sampleFunction = &Oscillator::noiseSample; break; + case Oscillator::UserDefinedWave: + m_sampleFunction = NULL; + /*TODO: If C++11 is allowed, should change the type of + m_sampleFunction be std::function + and use the line below: + */ + //m_sampleFunction = &(m_userDefSampleBuffer->userWaveSample) + break; } } diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 3308faf60..63f3a5993 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -894,6 +894,23 @@ QString SampleBuffer::openAudioFile() const } + + +QString SampleBuffer::openAndSetAudioFile() +{ + QString fileName = this->openAudioFile(); + + if(!fileName.isEmpty()) + { + this->setAudioFile( fileName ); + } + + return fileName; +} + + + + #undef LMMS_HAVE_FLAC_STREAM_ENCODER_H /* not yet... */ #undef LMMS_HAVE_FLAC_STREAM_DECODER_H diff --git a/src/gui/LfoControllerDialog.cpp b/src/gui/LfoControllerDialog.cpp index 05458085e..f9c151d70 100644 --- a/src/gui/LfoControllerDialog.cpp +++ b/src/gui/LfoControllerDialog.cpp @@ -178,15 +178,17 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent toolTip::add( white_noise_btn, tr( "Click here for white-noise." ) ); - pixmapButton * uwb = new pixmapButton( this, NULL ); - uwb->move( CD_LFO_SHAPES_X + 45, CD_LFO_SHAPES_Y + 15 ); - uwb->setActiveGraphic( embed::getIconPixmap( + m_userWaveBtn = new pixmapButton( this, NULL ); + m_userWaveBtn->move( CD_LFO_SHAPES_X + 45, CD_LFO_SHAPES_Y + 15 ); + m_userWaveBtn->setActiveGraphic( embed::getIconPixmap( "usr_wave_active" ) ); - uwb->setInactiveGraphic( embed::getIconPixmap( + m_userWaveBtn->setInactiveGraphic( embed::getIconPixmap( "usr_wave_inactive" ) ); - uwb->setEnabled( false ); - toolTip::add( uwb, tr( "Click here for a user-defined " - "shape." ) ); + connect( m_userWaveBtn, + SIGNAL( doubleClicked() ), + this, SLOT( askUserDefWave() ) ); + toolTip::add( m_userWaveBtn, + tr( "Click here for a user-defined shape." ) ); m_waveBtnGrp = new automatableButtonGroup( this ); m_waveBtnGrp->addButton( sin_wave_btn ); @@ -196,7 +198,7 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_waveBtnGrp->addButton( moog_saw_wave_btn ); m_waveBtnGrp->addButton( exp_wave_btn ); m_waveBtnGrp->addButton( white_noise_btn ); - m_waveBtnGrp->addButton( uwb ); + m_waveBtnGrp->addButton( m_userWaveBtn ); pixmapButton * x1 = new pixmapButton( this, NULL ); @@ -240,11 +242,26 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent LfoControllerDialog::~LfoControllerDialog() { + m_userWaveBtn->disconnect( this ); //delete m_subWindow; } +void LfoControllerDialog::askUserDefWave() +{ + SampleBuffer * sampleBuffer = dynamic_cast(this->model())-> + m_userDefSampleBuffer; + QString fileName = sampleBuffer->openAndSetAudioFile(); + if( fileName.isEmpty() == false ) + { + // TODO: + toolTip::add( m_userWaveBtn, sampleBuffer->audioFile() ); + } +} + + + void LfoControllerDialog::contextMenuEvent( QContextMenuEvent * ) { /* diff --git a/src/gui/widgets/graph.cpp b/src/gui/widgets/graph.cpp index 538bb2544..9a4347647 100644 --- a/src/gui/widgets/graph.cpp +++ b/src/gui/widgets/graph.cpp @@ -482,6 +482,25 @@ void graphModel::setWaveToNoise() emit samplesChanged( 0, length() - 1 ); }; +QString graphModel::setWaveToUser() +{ + SampleBuffer * sampleBuffer = new SampleBuffer; + QString fileName = sampleBuffer->openAndSetAudioFile(); + if( fileName.isEmpty() == false ) + { + for( int i = 0; i < length(); i++ ) + { + m_samples[i] = sampleBuffer->userWaveSample( + i / static_cast( length() ) ); + } + } + + sharedObject::unref( sampleBuffer ); + + emit samplesChanged( 0, length() - 1 ); + return fileName; +}; + void graphModel::smooth()