diff --git a/include/MidiTime.h b/include/MidiTime.h index ce5ead739cd..afec55e42b7 100644 --- a/include/MidiTime.h +++ b/include/MidiTime.h @@ -97,6 +97,7 @@ class EXPORT MidiTime static tick_t ticksPerTact( const TimeSig &sig ); static int stepsPerTact(); static void setTicksPerTact( tick_t tpt ); + static MidiTime stepPosition( int step ); private: tick_t m_ticks; diff --git a/include/Pattern.h b/include/Pattern.h index 0e6ab452939..6270f390d6a 100644 --- a/include/Pattern.h +++ b/include/Pattern.h @@ -70,11 +70,11 @@ class EXPORT Pattern : public TrackContentObject // note management Note * addNote( const Note & _new_note, const bool _quant_pos = true ); - void removeNote( const Note * _note_to_del ); + void removeNote( Note * _note_to_del ); Note * noteAtStep( int _step ); - Note * rearrangeNote( const Note * _note_to_proc, + Note * rearrangeNote( Note * _note_to_proc, const bool _quant_pos = true ); void rearrangeAllNotes(); void clearNotes(); @@ -84,7 +84,8 @@ class EXPORT Pattern : public TrackContentObject return m_notes; } - void setStep( int _step, bool _enabled ); + Note * addStepNote( int step ); + void setStep( int step, bool enabled ); // pattern-type stuff inline PatternTypes type() const @@ -122,7 +123,6 @@ class EXPORT Pattern : public TrackContentObject protected: - void ensureBeatNotes(); void updateBBTrack(); diff --git a/src/core/midi/MidiTime.cpp b/src/core/midi/MidiTime.cpp index b80c31b85a3..11c99a0df11 100644 --- a/src/core/midi/MidiTime.cpp +++ b/src/core/midi/MidiTime.cpp @@ -198,3 +198,9 @@ void MidiTime::setTicksPerTact( tick_t tpt ) { s_ticksPerTact = tpt; } + + +MidiTime MidiTime::stepPosition( int step ) +{ + return step * ticksPerTact() / stepsPerTact(); +} diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 497a6d6b2a7..3e66a5c594a 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -1627,17 +1627,8 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) m_mouseDownRight = true; if( it != notes.begin()-1 ) { - Note *note = *it; m_pattern->addJournalCheckPoint(); - if( note->length() > 0 ) - { - m_pattern->removeNote( note ); - } - else - { - note->setLength( 0 ); - m_pattern->dataChanged(); - } + m_pattern->removeNote( *it ); Engine::getSong()->setModified(); } } @@ -2288,19 +2279,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) ) { // delete this note - if( it != notes.end() ) - { - if( note->length() > 0 ) - { - m_pattern->removeNote( note ); - } - else - { - note->setLength( 0 ); - m_pattern->dataChanged(); - } - Engine::getSong()->setModified(); - } + m_pattern->removeNote( note ); + Engine::getSong()->setModified(); } else { @@ -3700,7 +3680,7 @@ void PianoRoll::cutSelectedNotes() Engine::getSong()->setModified(); - for( const Note *note : selected_notes ) + for( Note *note : selected_notes ) { // note (the memory of it) is also deleted by // pattern::removeNote(...) so we don't have to do that diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 18db5b5292c..b7394bfed72 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -656,25 +656,21 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames, while( nit != notes.end() && ( cur_note = *nit )->pos() == cur_start ) { - if( cur_note->length() != 0 ) - { - const f_cnt_t note_frames = - cur_note->length().frames( - frames_per_tick ); - - NotePlayHandle* notePlayHandle = NotePlayHandleManager::acquire( this, _offset, note_frames, *cur_note ); - notePlayHandle->setBBTrack( bb_track ); - // are we playing global song? - if( _tco_num < 0 ) - { - // then set song-global offset of pattern in order to - // properly perform the note detuning - notePlayHandle->setSongGlobalParentOffset( p->startPosition() ); - } + const f_cnt_t note_frames = + cur_note->length().frames( frames_per_tick ); - Engine::mixer()->addPlayHandle( notePlayHandle ); - played_a_note = true; + NotePlayHandle* notePlayHandle = NotePlayHandleManager::acquire( this, _offset, note_frames, *cur_note ); + notePlayHandle->setBBTrack( bb_track ); + // are we playing global song? + if( _tco_num < 0 ) + { + // then set song-global offset of pattern in order to + // properly perform the note detuning + notePlayHandle->setSongGlobalParentOffset( p->startPosition() ); } + + Engine::mixer()->addPlayHandle( notePlayHandle ); + played_a_note = true; ++nit; } } diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 25dbc8a75f8..47385af0149 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -151,8 +151,6 @@ void Pattern::init() this, SLOT( changeTimeSignature() ) ); saveJournallingState( false ); - ensureBeatNotes(); - changeLength( length() ); restoreJournallingState(); } @@ -256,7 +254,7 @@ Note * Pattern::addNote( const Note & _new_note, const bool _quant_pos ) -void Pattern::removeNote( const Note * _note_to_del ) +void Pattern::removeNote( Note * _note_to_del ) { instrumentTrack()->lock(); NoteVector::Iterator it = m_notes.begin(); @@ -288,7 +286,8 @@ Note * Pattern::noteAtStep( int _step ) for( NoteVector::Iterator it = m_notes.begin(); it != m_notes.end(); ++it ) { - if( ( *it )->pos() == ( _step * MidiTime::ticksPerTact() ) / MidiTime::stepsPerTact() ) + if( ( *it )->pos() == MidiTime::stepPosition( _step ) + && ( *it )->length() < 0 ) { return *it; } @@ -297,8 +296,7 @@ Note * Pattern::noteAtStep( int _step ) } -Note * Pattern::rearrangeNote( const Note * _note_to_proc, - const bool _quant_pos ) +Note * Pattern::rearrangeNote( Note * _note_to_proc, const bool _quant_pos ) { // just rearrange the position of the note by removing it and adding // a copy of it -> addNote inserts it at the correct position @@ -336,17 +334,29 @@ void Pattern::clearNotes() -void Pattern::setStep( int _step, bool _enabled ) +Note * Pattern::addStepNote( int step ) { - for( NoteVector::Iterator it = m_notes.begin(); it != m_notes.end(); - ++it ) + return addNote( Note( MidiTime( -DefaultTicksPerTact ), + MidiTime::stepPosition( step ) ), false ); +} + + + + +void Pattern::setStep( int step, bool enabled ) +{ + if( enabled ) { - if( ( *it )->pos() == ( _step * MidiTime::ticksPerTact() ) / MidiTime::stepsPerTact() && - ( *it )->length() <= 0 ) + if ( !noteAtStep( step ) ) { - ( *it )->setLength( _enabled ? - -DefaultTicksPerTact : 0 ); + addStepNote( step ); } + return; + } + + while( Note * note = noteAtStep( step ) ) + { + removeNote( note ); } } @@ -407,10 +417,7 @@ void Pattern::saveSettings( QDomDocument & _doc, QDomElement & _this ) for( NoteVector::Iterator it = m_notes.begin(); it != m_notes.end(); ++it ) { - if( ( *it )->length() ) - { - ( *it )->saveState( _doc, _this ); - } + ( *it )->saveState( _doc, _this ); } } @@ -453,7 +460,6 @@ void Pattern::loadSettings( const QDomElement & _this ) m_steps = MidiTime::stepsPerTact(); } - ensureBeatNotes(); checkType(); emit dataChanged(); @@ -494,7 +500,6 @@ void Pattern::clear() { addJournalCheckPoint(); clearNotes(); - ensureBeatNotes(); } @@ -503,7 +508,6 @@ void Pattern::clear() void Pattern::addSteps() { m_steps += MidiTime::stepsPerTact(); - ensureBeatNotes(); emit dataChanged(); updateBBTrack(); } @@ -512,7 +516,6 @@ void Pattern::cloneSteps() { int oldLength = m_steps; m_steps *= 2; // cloning doubles the track - ensureBeatNotes(); for(int i = 0; i < oldLength; ++i ) { Note *toCopy = noteAtStep( i ); @@ -526,7 +529,6 @@ void Pattern::cloneSteps() newNote->setVolume( toCopy->getVolume() ); } } - ensureBeatNotes(); emit dataChanged(); updateBBTrack(); } @@ -541,18 +543,7 @@ void Pattern::removeSteps() { for( int i = m_steps - n; i < m_steps; ++i ) { - for( NoteVector::Iterator it = m_notes.begin(); - it != m_notes.end(); ++it ) - { - if( ( *it )->pos() == - ( i * MidiTime::ticksPerTact() ) / - MidiTime::stepsPerTact() && - ( *it )->length() <= 0 ) - { - removeNote( *it ); - break; - } - } + setStep( i, false ); } m_steps -= n; emit dataChanged(); @@ -571,66 +562,6 @@ TrackContentObjectView * Pattern::createView( TrackView * _tv ) - -void Pattern::ensureBeatNotes() -{ - // make sure, that all step-note exist - for( int i = 0; i < m_steps; ++i ) - { - bool found = false; - NoteVector::Iterator it; - - for( it = m_notes.begin(); it != m_notes.end(); ++it ) - { - Note *note = *it; - // if a note in this position is the one we want - if( note->pos() == - ( i * MidiTime::ticksPerTact() ) / MidiTime::stepsPerTact() - && note->length() <= 0 ) - { - found = true; - break; - } - } - if( found == false ) - { - addNote( Note( MidiTime( 0 ), MidiTime( ( i * - MidiTime::ticksPerTact() ) / - MidiTime::stepsPerTact() ) ), false ); - } - } - - // remove notes we no longer need: - // that is, disabled notes that no longer fall to the steps of the new time sig - - for( NoteVector::Iterator it = m_notes.begin(); it != m_notes.end(); ) - { - bool needed = false; - Note *note = *it; - - for( int i = 0; i < m_steps; ++i ) - { - if( note->pos() == ( i * MidiTime::ticksPerTact() ) / MidiTime::stepsPerTact() - || note->length() != 0 ) - { - needed = true; - break; - } - } - if( needed == false ) - { - delete note; - it = m_notes.erase( it ); - } - else { - ++it; - } - } -} - - - - void Pattern::updateBBTrack() { if( getTrack()->trackContainer() == Engine::getBBTrackContainer() ) @@ -676,23 +607,8 @@ void Pattern::changeTimeSignature() } } last_pos = last_pos.nextFullTact() * MidiTime::ticksPerTact(); - for( NoteVector::Iterator it = m_notes.begin(); it != m_notes.end(); ) - { - if( ( *it )->length() == 0 && ( *it )->pos() >= last_pos ) - { - delete *it; - it = m_notes.erase( it ); - --m_steps; - } - else - { - ++it; - } - } - m_steps = qMax( - qMax( m_steps, MidiTime::stepsPerTact() ), + m_steps = qMax( MidiTime::stepsPerTact(), last_pos.getTact() * MidiTime::stepsPerTact() ); - ensureBeatNotes(); updateBBTrack(); } @@ -865,28 +781,14 @@ void PatternView::mousePressEvent( QMouseEvent * _me ) Note * n = m_pat->noteAtStep( step ); - // if note at step not found, ensureBeatNotes and try again if( n == NULL ) { - m_pat -> ensureBeatNotes(); - n = m_pat->noteAtStep( step ); - if( n == NULL ) // still can't find a note? bail! - { - qDebug( "Something went wrong in pattern.cpp: couldn't add note at step %d!", step ); - return; - } + m_pat->addStepNote( step ); } else // note at step found { m_pat->addJournalCheckPoint(); - if( n->length() < 0 ) - { - n->setLength( 0 ); // set note as enabled beat note - } - else - { - n->setLength( -DefaultTicksPerTact ); // set note as disabled beat note - } + m_pat->setStep( step, false ); } Engine::getSong()->setModified(); @@ -941,21 +843,17 @@ void PatternView::wheelEvent( QWheelEvent * _we ) return; } - int vol = 0; - int len = 0; - Note * n = m_pat->noteAtStep( step ); + if( !n && _we->delta() > 0 ) + { + n = m_pat->addStepNote( step ); + n->setVolume( 0 ); + } if( n != NULL ) { - vol = n->getVolume(); - len = n->length(); + int vol = n->getVolume(); - if( len == 0 && _we->delta() > 0 ) - { - n->setLength( -DefaultTicksPerTact ); - n->setVolume( 5 ); - } - else if( _we->delta() > 0 ) + if( _we->delta() > 0 ) { n->setVolume( qMin( 100, vol + 5 ) ); } @@ -1150,14 +1048,9 @@ void PatternView::paintEvent( QPaintEvent * ) const int x = TCO_BORDER_WIDTH + static_cast( it * w / steps ); const int y = height() - s_stepBtnOff->height() - 1; - // get volume and length of note, if noteAtStep returned null - // (meaning, note at step doesn't exist for some reason) - // then set both at zero, ie. treat as an off step - const int vol = ( n != NULL ? n->getVolume() : 0 ); - const int len = ( n != NULL ? int( n->length() ) : 0 ); - - if( len < 0 ) + if( n ) { + const int vol = n->getVolume(); p.drawPixmap( x, y, stepoff ); for( int i = 0; i < vol / 5 + 1; ++i ) {