From fa77617d9990c1367bfe7a3ae7104d8aca021239 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Mon, 22 Jun 2015 16:12:13 +0200 Subject: [PATCH] Extended arpeggiator functions --- include/InstrumentFunctionViews.h | 3 + include/InstrumentFunctions.h | 3 + src/core/InstrumentFunctions.cpp | 65 ++++++++++++++++++++- src/gui/SetupDialog.cpp | 2 +- src/gui/widgets/InstrumentFunctionViews.cpp | 34 ++++++++++- 5 files changed, 104 insertions(+), 3 deletions(-) diff --git a/include/InstrumentFunctionViews.h b/include/InstrumentFunctionViews.h index c8c91f302a1..8c23a486dc0 100644 --- a/include/InstrumentFunctionViews.h +++ b/include/InstrumentFunctionViews.h @@ -78,6 +78,9 @@ class InstrumentFunctionArpeggioView : public QWidget, public ModelView GroupBox * m_arpGroupBox; ComboBox * m_arpComboBox; Knob * m_arpRangeKnob; + Knob * m_arpCycleKnob; + Knob * m_arpSkipKnob; + Knob * m_arpMissKnob; TempoSyncKnob * m_arpTimeKnob; Knob * m_arpGateKnob; diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index d6abef16a40..28820e6d320 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -196,6 +196,9 @@ class InstrumentFunctionArpeggio : public Model, public JournallingObject BoolModel m_arpEnabledModel; ComboBoxModel m_arpModel; FloatModel m_arpRangeModel; + FloatModel m_arpCycleModel; + FloatModel m_arpSkipModel; + FloatModel m_arpMissModel; TempoSyncKnobModel m_arpTimeModel; FloatModel m_arpGateModel; ComboBoxModel m_arpDirectionModel; diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 1083a3052d0..918c41900ea 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -302,6 +302,9 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : m_arpEnabledModel( false ), m_arpModel( this, tr( "Arpeggio type" ) ), m_arpRangeModel( 1.0f, 1.0f, 9.0f, 1.0f, this, tr( "Arpeggio range" ) ), + m_arpCycleModel( 0.0f, 0.0f, 6.0f, 1.0f, this, tr( "Cycle steps" ) ), + m_arpSkipModel( 0.0f, 0.0f, 100.0f, 1.0f, this, tr( "Skip rate" ) ), + m_arpMissModel( 0.0f, 0.0f, 100.0f, 1.0f, this, tr( "Miss rate" ) ), m_arpTimeModel( 100.0f, 25.0f, 2000.0f, 1.0f, 2000, this, tr( "Arpeggio time" ) ), m_arpGateModel( 100.0f, 1.0f, 200.0f, 1.0f, this, tr( "Arpeggio gate" ) ), m_arpDirectionModel( this, tr( "Arpeggio direction" ) ), @@ -407,7 +410,38 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) continue; } - const int dir = m_arpDirectionModel.value(); + int dir = m_arpDirectionModel.value(); + + /* TODO: Muting the notes, as it's done nown (see further down) + the code is a bit wasteful. Skipped notes should be + handled early in the while loop by actually skipping over + notes and not by muting them.*/ +/* + // Skip notes randomly + if( m_arpSkipModel.value() ) + { + if( 101 * ( (float) rand() / (float) RAND_MAX ) < m_arpSkipModel.value() ) + { + // update counters + frames_processed += arp_frames; + cur_frame += arp_frames; + continue; + } + } +*/ + + // Miss notes randomly. We intercept int dir and abuse it + // after need. :) + + int miss = m_arpMissModel.value(); + if( miss ) + { + if( 100 * ( (float) rand() / (float) RAND_MAX ) < ( miss * miss ) / 100 ) + { + dir = ArpDirRandom; + } + } + // process according to arpeggio-direction... if( dir == ArpDirUp ) { @@ -451,6 +485,20 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) cur_arp_idx = (int)( range * ( (float) rand() / (float) RAND_MAX ) ); } + + // Cycle notes + const int cycle = m_arpCycleModel.value(); + if( cycle ) + { + cur_arp_idx *= cycle + 1; + int i = 0; + while( cur_arp_idx >= (int)( range /*/ m_arpRepeatsModel.value()*/ ) ) + { + cur_arp_idx -= range; + i++; + } + } + // now calculate final key for our arp-note const int sub_note_key = base_note_key + (cur_arp_idx / cur_chord_size ) * KeysPerOctave + chord_table[selected_arp][cur_arp_idx % cur_chord_size]; @@ -469,6 +517,15 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) vol_level = _n->volumeLevel( cur_frame + gated_frames ); } + // Skip notes randomly by muting. + if( m_arpSkipModel.value() ) + { + if( 101 * ( (float) rand() / (float) RAND_MAX ) < m_arpSkipModel.value() ) + { + vol_level = 0.0f; + } + } + // create new arp-note // create sub-note-play-handle, only ptr to note is different @@ -496,6 +553,9 @@ void InstrumentFunctionArpeggio::saveSettings( QDomDocument & _doc, QDomElement m_arpEnabledModel.saveSettings( _doc, _this, "arp-enabled" ); m_arpModel.saveSettings( _doc, _this, "arp" ); m_arpRangeModel.saveSettings( _doc, _this, "arprange" ); + m_arpCycleModel.saveSettings( _doc, _this, "arpcycle" ); + m_arpSkipModel.saveSettings( _doc, _this, "arpskip" ); + m_arpMissModel.saveSettings( _doc, _this, "arpmiss" ); m_arpTimeModel.saveSettings( _doc, _this, "arptime" ); m_arpGateModel.saveSettings( _doc, _this, "arpgate" ); m_arpDirectionModel.saveSettings( _doc, _this, "arpdir" ); @@ -511,6 +571,9 @@ void InstrumentFunctionArpeggio::loadSettings( const QDomElement & _this ) m_arpEnabledModel.loadSettings( _this, "arp-enabled" ); m_arpModel.loadSettings( _this, "arp" ); m_arpRangeModel.loadSettings( _this, "arprange" ); + m_arpCycleModel.loadSettings( _this, "arpcycle" ); + m_arpSkipModel.loadSettings( _this, "arpskip" ); + m_arpMissModel.loadSettings( _this, "arpmiss" ); m_arpTimeModel.loadSettings( _this, "arptime" ); m_arpGateModel.loadSettings( _this, "arpgate" ); m_arpDirectionModel.loadSettings( _this, "arpdir" ); diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 7ca9911ce41..b993224be2b 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -950,7 +950,7 @@ void SetupDialog::accept() ConfigManager::inst()->setValue( "app", "displaydbv", QString::number( m_displaydBV ) ); ConfigManager::inst()->setValue( "app", "nommpz", - QString::number( !m_MMPZ ) ); + QString::number( !m_MMPZ ) ); ConfigManager::inst()->setValue( "app", "disablebackup", QString::number( !m_disableBackup ) ); ConfigManager::inst()->setValue( "mixer", "hqaudio", diff --git a/src/gui/widgets/InstrumentFunctionViews.cpp b/src/gui/widgets/InstrumentFunctionViews.cpp index 632526a25fb..818888539e1 100644 --- a/src/gui/widgets/InstrumentFunctionViews.cpp +++ b/src/gui/widgets/InstrumentFunctionViews.cpp @@ -103,6 +103,9 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpGroupBox( new GroupBox( tr( "ARPEGGIO" ) ) ), m_arpComboBox( new ComboBox() ), m_arpRangeKnob( new Knob( knobBright_26 ) ), + m_arpCycleKnob( new Knob( knobBright_26 ) ), + m_arpSkipKnob( new Knob( knobBright_26 ) ), + m_arpMissKnob( new Knob( knobBright_26 ) ), m_arpTimeKnob( new TempoSyncKnob( knobBright_26 ) ), m_arpGateKnob( new Knob( knobBright_26 ) ), m_arpDirectionComboBox( new ComboBox() ), @@ -137,6 +140,28 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti "number of octaves." ) ); + m_arpCycleKnob->setLabel( tr( "CYCLE" ) ); + m_arpCycleKnob->setHintText( tr( "Cycle notes:" ) + " ", " " + tr( "note(s)" ) ); + m_arpCycleKnob->setWhatsThis( + tr( "Changes the path the cycle takes." ) ); + + + m_arpSkipKnob->setLabel( tr( "SKIP" ) ); + m_arpSkipKnob->setHintText( tr( "Fail rate:" ) + " ", " " + tr( "%" ) ); + m_arpSkipKnob->setWhatsThis( + tr( "The skip function will make the arpeggiator pause one step " + "randomly. From it's start in full counter clockwise " + "position and no effect it will gradually progress to " + "more or less full amnesia at maximum setting.") ); + + + m_arpMissKnob->setLabel( tr( "MISS" ) ); + m_arpMissKnob->setHintText( tr( "Fail rate:" ) + " ", " " + tr( "%" ) ); + m_arpMissKnob->setWhatsThis( + tr( "The miss function will make the arpeggiator miss the " + "intended note.") ); + + m_arpTimeKnob->setLabel( tr( "TIME" ) ); m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ), " " + tr( "ms" ) ); m_arpTimeKnob->setWhatsThis( @@ -153,6 +178,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti "arpeggio-tone that should be played. With this you " "can make cool staccato arpeggios." ) ); + QLabel* arpChordLabel = new QLabel( tr( "Chord:" ) ); arpChordLabel->setFont( pointSize<8>( arpChordLabel->font() ) ); @@ -170,8 +196,11 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti mainLayout->addWidget( m_arpModeComboBox, 7, 0 ); mainLayout->addWidget( m_arpRangeKnob, 0, 1, 2, 1, Qt::AlignHCenter ); - mainLayout->addWidget( m_arpTimeKnob, 3, 1, 2, 1, Qt::AlignHCenter ); + mainLayout->addWidget( m_arpCycleKnob, 0, 2, 2, 1, Qt::AlignHCenter ); + mainLayout->addWidget( m_arpSkipKnob, 3, 1, 2, 1, Qt::AlignHCenter ); + mainLayout->addWidget( m_arpMissKnob, 3, 2, 2, 1, Qt::AlignHCenter ); mainLayout->addWidget( m_arpGateKnob, 6, 1, 2, 1, Qt::AlignHCenter ); + mainLayout->addWidget( m_arpTimeKnob, 6, 2, 2, 1, Qt::AlignHCenter ); mainLayout->setRowMinimumHeight( 2, 10 ); mainLayout->setRowMinimumHeight( 5, 10 ); @@ -194,6 +223,9 @@ void InstrumentFunctionArpeggioView::modelChanged() m_arpGroupBox->setModel( &m_a->m_arpEnabledModel ); m_arpComboBox->setModel( &m_a->m_arpModel ); m_arpRangeKnob->setModel( &m_a->m_arpRangeModel ); + m_arpCycleKnob->setModel( &m_a->m_arpCycleModel ); + m_arpSkipKnob->setModel( &m_a->m_arpSkipModel ); + m_arpMissKnob->setModel( &m_a->m_arpMissModel ); m_arpTimeKnob->setModel( &m_a->m_arpTimeModel ); m_arpGateKnob->setModel( &m_a->m_arpGateModel ); m_arpDirectionComboBox->setModel( &m_a->m_arpDirectionModel );