diff --git a/include/InstrumentFunctionViews.h b/include/InstrumentFunctionViews.h index c8c91f302a1..d989c21fb70 100644 --- a/include/InstrumentFunctionViews.h +++ b/include/InstrumentFunctionViews.h @@ -78,6 +78,8 @@ class InstrumentFunctionArpeggioView : public QWidget, public ModelView GroupBox * m_arpGroupBox; ComboBox * m_arpComboBox; Knob * m_arpRangeKnob; + Knob * m_arpSkipKnob; + Knob * m_arpMissKnob; TempoSyncKnob * m_arpTimeKnob; Knob * m_arpGateKnob; diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index b69744c8bf9..e39580ddec2 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -196,6 +196,8 @@ class InstrumentFunctionArpeggio : public Model, public JournallingObject BoolModel m_arpEnabledModel; ComboBoxModel m_arpModel; FloatModel m_arpRangeModel; + FloatModel m_arpSkipModel; + FloatModel m_arpMissModel; TempoSyncKnobModel m_arpTimeModel; FloatModel m_arpGateModel; ComboBoxModel m_arpDirectionModel; diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 130799b0709..6cbf0a74a99 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -196,6 +196,12 @@ class EXPORT NotePlayHandle : public PlayHandle, public Note return m_subNotes.size() > 0 || m_hadChildren; } + void setMasterNote() + { + m_hadChildren = true; + setUsesBuffer( false ); + } + /*! Returns whether note is muted */ bool isMuted() const { diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index fd169fc37e4..886edf2d8e7 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -268,8 +268,6 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) } } } - - } @@ -303,6 +301,8 @@ 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_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" ) ), @@ -408,7 +408,36 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) continue; } - const int dir = m_arpDirectionModel.value(); + // Skip notes randomly + if( m_arpSkipModel.value() ) + { + + if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpSkipModel.value() ) + { + if( cur_arp_idx == 0 ) + { + _n->setMasterNote(); + } + // update counters + frames_processed += arp_frames; + cur_frame += arp_frames; + continue; + } + } + + int dir = m_arpDirectionModel.value(); + + // Miss notes randomly. We intercept int dir and abuse it + // after need. :) + + if( m_arpMissModel.value() ) + { + if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpMissModel.value() ) + { + dir = ArpDirRandom; + } + } + // process according to arpeggio-direction... if( dir == ArpDirUp ) { @@ -497,6 +526,8 @@ 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_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" ); @@ -512,6 +543,8 @@ void InstrumentFunctionArpeggio::loadSettings( const QDomElement & _this ) m_arpEnabledModel.loadSettings( _this, "arp-enabled" ); m_arpModel.loadSettings( _this, "arp" ); m_arpRangeModel.loadSettings( _this, "arprange" ); + 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/widgets/InstrumentFunctionViews.cpp b/src/gui/widgets/InstrumentFunctionViews.cpp index 632526a25fb..4106f0131d2 100644 --- a/src/gui/widgets/InstrumentFunctionViews.cpp +++ b/src/gui/widgets/InstrumentFunctionViews.cpp @@ -103,6 +103,8 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpGroupBox( new GroupBox( tr( "ARPEGGIO" ) ) ), m_arpComboBox( new ComboBox() ), m_arpRangeKnob( 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 +139,22 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti "number of octaves." ) ); + m_arpSkipKnob->setLabel( tr( "SKIP" ) ); + m_arpSkipKnob->setHintText( tr( "Skip rate:" ), tr( "%" ) ); + m_arpSkipKnob->setWhatsThis( + tr( "The skip function will make the arpeggiator pause one step " + "randomly. From its start in full counter clockwise " + "position and no effect it will gradually progress to " + "full amnesia at maximum setting.") ); + + + m_arpMissKnob->setLabel( tr( "MISS" ) ); + m_arpMissKnob->setHintText( tr( "Miss 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 +171,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 +189,10 @@ 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_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 +215,8 @@ 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_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 );