From bf077dd52003428553225f0527d1c2491ea38888 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 25 May 2008 22:43:53 +0000 Subject: [PATCH] implemented support for time-signatures other than 4/4 git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1021 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 30 +++++ include/meter_model.h | 11 +- include/midi_time.h | 71 +++++++----- include/pattern.h | 4 +- include/piano_roll.h | 2 +- include/song.h | 26 +++-- include/song_editor.h | 1 - include/timeline.h | 2 +- include/types.h | 2 +- src/core/bb_track_container.cpp | 15 +-- src/core/meter_model.cpp | 13 ++- src/core/song.cpp | 70 +++++------- src/core/timeline.cpp | 10 +- src/core/track.cpp | 49 ++++---- src/gui/automation_editor.cpp | 2 - src/gui/piano_roll.cpp | 107 ++++++++--------- src/gui/song_editor.cpp | 41 ++----- src/gui/track_container_view.cpp | 2 + src/gui/widgets/tempo_sync_knob.cpp | 4 +- src/tracks/bb_track.cpp | 7 +- src/tracks/pattern.cpp | 170 ++++++++++++++++++++-------- 21 files changed, 370 insertions(+), 269 deletions(-) diff --git a/ChangeLog b/ChangeLog index 822f08902..b9e030d27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,35 @@ 2008-05-25 Tobias Doerffel + * include/meter_model.h: + * include/song.h: + * include/pattern.h: + * include/piano_roll.h: + * include/song_editor.h: + * include/midi_time.h: + * include/types.h: + * include/timeline.h: + * src/core/bb_track_container.cpp: + * src/core/meter_model.cpp: + * src/core/song.cpp: + * src/core/timeline.cpp: + * src/core/track.cpp: + * src/gui/automation_editor.cpp: + * src/gui/piano_roll.cpp: + * src/gui/song_editor.cpp: + * src/gui/track_container_view.cpp: + * src/gui/widgets/tempo_sync_knob.cpp: + * src/tracks/bb_track.cpp: + * src/tracks/pattern.cpp: + implemented support for time-signatures other than 4/4 - still + incomplete and experimental! + + * include/controller_dialog.h: + * src/core/lfo_controller.cpp: + * src/gui/controller_dialog.cpp: + * src/gui/widgets/controller_view.cpp: + fixed order of member-initialization and miscellanous coding-style + corrections + * plugins/patman/select_file.png: * plugins/patman/logo.png: * plugins/patman/artwork.png: diff --git a/include/meter_model.h b/include/meter_model.h index 20a66ff7c..32f66b10c 100644 --- a/include/meter_model.h +++ b/include/meter_model.h @@ -40,12 +40,14 @@ public: void loadSettings( const QDomElement & _this, const QString & _name ); - inline int getNumerator( void ) + void reset( void ); + + inline int getNumerator( void ) const { return( m_numeratorModel.value() ); } - inline int getDenominator( void ) + inline int getDenominator( void ) const { return( m_denominatorModel.value() ); } @@ -56,11 +58,6 @@ private: lcdSpinBoxModel m_denominatorModel; -signals: - void numeratorChanged( void ); - void denominatorChanged( void ); - - friend class meterDialog; } ; diff --git a/include/midi_time.h b/include/midi_time.h index 69450beac..7e637931c 100644 --- a/include/midi_time.h +++ b/include/midi_time.h @@ -30,40 +30,39 @@ #include "types.h" const int DefaultTicksPerTact = 192; +const int DefaultStepsPerTact = 16; +const int DefaultBeatsPerTact = DefaultTicksPerTact / DefaultStepsPerTact; + class midiTime { public: inline midiTime( const tact _tact, const tick _ticks ) : - m_tact( _tact ), + m_ticks( _tact * s_ticksPerTact + _ticks ) + { + } + + inline midiTime( const tick _ticks = 0 ) : m_ticks( _ticks ) { } - inline midiTime( const int _abs = 0 ) : - m_tact( _abs / DefaultTicksPerTact ), - m_ticks( _abs % DefaultTicksPerTact ) + inline midiTime( const midiTime & _t ) : + m_ticks( _t.m_ticks ) { } - inline midiTime( const midiTime & _t ) - { - *this = _t; - } - inline midiTime toNearestTact( void ) const { - if( m_ticks >= DefaultTicksPerTact/2 ) + if( m_ticks % s_ticksPerTact >= s_ticksPerTact/2 ) { - return( m_tact * DefaultTicksPerTact + - DefaultTicksPerTact ); + return( ( getTact() + 1 ) * s_ticksPerTact ); } - return( m_tact * DefaultTicksPerTact ); + return( getTact() * s_ticksPerTact ); } inline midiTime & operator=( const midiTime & _t ) { - m_tact = _t.m_tact; m_ticks = _t.m_ticks; return( *this ); } @@ -80,14 +79,18 @@ public: static_cast( _t ) ); } - inline void setTact( tact _t ) - { - m_tact = _t; - } - inline tact getTact( void ) const { - return( m_tact ); + return( m_ticks / s_ticksPerTact ); + } + + inline tact nextFullTact( void ) const + { + if( m_ticks % s_ticksPerTact == 0 ) + { + return( m_ticks / s_ticksPerTact ); + } + return( m_ticks / s_ticksPerTact + 1 ); } inline void setTicks( tick _t ) @@ -100,21 +103,17 @@ public: return( m_ticks ); } - // converts time-class in an absolute value, useful for calculations, - // comparisons and so on... inline operator int( void ) const { - return( static_cast( m_tact ) * DefaultTicksPerTact + - static_cast( m_ticks ) ); + return( m_ticks ); } // calculate number of frame that are needed this time inline f_cnt_t frames( const float _frames_per_tick ) const { - if( m_tact >= 0 ) + if( m_ticks >= 0 ) { - return( static_cast( - ( m_tact * DefaultTicksPerTact + m_ticks ) * + return( static_cast( m_ticks * _frames_per_tick ) ); } return( 0 ); @@ -128,10 +127,26 @@ public: } + static tick ticksPerTact( void ) + { + return( s_ticksPerTact ); + } + + static int stepsPerTact( void ) + { + return( ticksPerTact() / DefaultBeatsPerTact ); + } + + static void setTicksPerTact( tick _tpt ) + { + s_ticksPerTact = _tpt; + } + private: - tact m_tact; tick m_ticks; + static tick s_ticksPerTact; + } ; diff --git a/include/pattern.h b/include/pattern.h index 2dd0ad03e..96d64be7e 100644 --- a/include/pattern.h +++ b/include/pattern.h @@ -47,8 +47,6 @@ class patternFreezeThread; class sampleBuffer; -const int DEFAULT_STEPS_PER_TACT = 16; -const int BEATS_PER_TACT = DefaultTicksPerTact/DEFAULT_STEPS_PER_TACT; @@ -70,6 +68,7 @@ public: virtual midiTime length( void ) const; + midiTime beatPatternLength( void ) const; note * addNote( const note & _new_note, const bool _quant_pos = TRUE ); @@ -159,6 +158,7 @@ protected slots: void clear( void ); void freeze( void ); void unfreeze( void ); + void changeTimeSignature( void ); private: diff --git a/include/piano_roll.h b/include/piano_roll.h index aba238391..e8e6de855 100644 --- a/include/piano_roll.h +++ b/include/piano_roll.h @@ -244,7 +244,7 @@ private: void copy_to_clipboard( const noteVector & _notes ) const; - void drawDetuningInfo( QPainter & _p, note * _n, Uint16 _x, Uint16 _y ); + void drawDetuningInfo( QPainter & _p, note * _n, int _x, int _y ); bool mouseOverNote( void ); note * noteUnderMouse( void ); noteVector::const_iterator noteIteratorUnderMouse( void ); diff --git a/include/song.h b/include/song.h index d66914627..1c9be2290 100644 --- a/include/song.h +++ b/include/song.h @@ -40,10 +40,10 @@ class pattern; class timeLine; -const bpm_t MIN_BPM = 10; -const bpm_t DEFAULT_BPM = 140; -const bpm_t MAX_BPM = 999; -const Uint16 MAX_SONG_LENGTH = 9999; +const bpm_t MinTempo = 10; +const bpm_t DefaultTempo = 140; +const bpm_t MaxTempo = 999; +const tick MaxSongLength = 9999 * DefaultTicksPerTact; class song : public trackContainer @@ -139,11 +139,6 @@ public: bpm_t getTempo( void ); virtual automationPattern * tempoAutomationPattern( void ); - const meterModel & getTimeSig( void ) const - { - return( m_timeSigModel ); - } - track * getAutomationTrack( void ) { return( m_automationTrack ); @@ -233,6 +228,13 @@ private: virtual ~song(); + inline int ticksPerTact( void ) const + { + return( DefaultTicksPerTact * + m_timeSigModel.getNumerator() / + m_timeSigModel.getDenominator() ); + } + inline tact currentTact( void ) const { return( m_playPos[m_playMode].getTact() ); @@ -242,7 +244,7 @@ private: { return( m_playPos[m_playMode].getTicks() ); } - void setPlayPos( tact _tact_num, tick _tick, PlayModes _play_mode ); + void setPlayPos( tick _ticks, PlayModes _play_mode ); void saveControllerStates( QDomDocument & _doc, QDomElement & _this ); void restoreControllerStates( const QDomElement & _this ); @@ -252,6 +254,7 @@ private: lcdSpinBoxModel m_tempoModel; meterModel m_timeSigModel; + int m_oldTicksPerTact; sliderModel m_masterVolumeModel; sliderModel m_masterPitchModel; @@ -296,7 +299,8 @@ private: signals: void tempoChanged( bpm_t _new_bpm ); - void timeSignatureChanged( int _num, int _den ); + void timeSignatureChanged( int _old_ticks_per_tact, + int _ticks_per_tact ); } ; diff --git a/include/song_editor.h b/include/song_editor.h index 7ac57dc1f..23efceed7 100644 --- a/include/song_editor.h +++ b/include/song_editor.h @@ -60,7 +60,6 @@ signals: private slots: void setHighQuality( bool ); void scrolled( int _new_pos ); - void updateTimeLinePosition( void ); void masterVolumeChanged( int _new_val ); void masterVolumePressed( void ); diff --git a/include/timeline.h b/include/timeline.h index 8fa88f31d..a1cc788e6 100644 --- a/include/timeline.h +++ b/include/timeline.h @@ -139,7 +139,7 @@ private: inline int markerX( const midiTime & _t ) const { return( m_xOffset + static_cast( ( _t - m_begin ) * - m_ppt / DefaultTicksPerTact ) ); + m_ppt / midiTime::ticksPerTact() ) ); } diff --git a/include/types.h b/include/types.h index 14a7e6b38..ef816e8b8 100644 --- a/include/types.h +++ b/include/types.h @@ -39,7 +39,7 @@ typedef signed int Sint32; typedef Uint32 minute; typedef Sint8 second; typedef Sint32 tact; -typedef Sint16 tick; +typedef Sint32 tick; typedef Uint8 volume; typedef Sint8 panning; diff --git a/src/core/bb_track_container.cpp b/src/core/bb_track_container.cpp index 0722ef32e..973ee8e6f 100644 --- a/src/core/bb_track_container.cpp +++ b/src/core/bb_track_container.cpp @@ -63,12 +63,11 @@ bool bbTrackContainer::play( midiTime _start, fpp_t _frames, bool played_a_note = FALSE; if( lengthOfBB( _tco_num ) <= 0 ) { - return( played_a_note ); + return( FALSE ); } - _start = ( _start.getTact() % lengthOfBB( _tco_num ) ) * - DefaultTicksPerTact + - _start.getTicks(); + _start = _start % ( lengthOfBB( _tco_num ) * midiTime::ticksPerTact() ); + QList tl = tracks(); for( int i = 0; i < tl.size(); ++i ) { @@ -98,7 +97,7 @@ void bbTrackContainer::updateAfterTrackAdd( void ) tact bbTrackContainer::lengthOfBB( int _bb ) { - midiTime max_length; + midiTime max_length = midiTime::ticksPerTact(); QList tl = tracks(); for( int i = 0; i < tl.size(); ++i ) @@ -106,12 +105,8 @@ tact bbTrackContainer::lengthOfBB( int _bb ) trackContentObject * tco = tl[i]->getTCO( _bb ); max_length = tMax( max_length, tco->length() ); } - if( max_length.getTicks() == 0 ) - { - return( max_length.getTact() ); - } - return( max_length.getTact() + 1 ); + return( max_length.nextFullTact() ); } diff --git a/src/core/meter_model.cpp b/src/core/meter_model.cpp index 7688f9a93..66eed0b69 100644 --- a/src/core/meter_model.cpp +++ b/src/core/meter_model.cpp @@ -35,9 +35,9 @@ meterModel::meterModel( ::model * _parent, track * _track ) : m_denominatorModel.setTrack( _track ); connect( &m_numeratorModel, SIGNAL( dataChanged() ), - this, SIGNAL( numeratorChanged() ) ); + this, SIGNAL( dataChanged() ) ); connect( &m_denominatorModel, SIGNAL( dataChanged() ), - this, SIGNAL( denominatorChanged() ) ); + this, SIGNAL( dataChanged() ) ); } @@ -50,6 +50,15 @@ meterModel::~meterModel() +void meterModel::reset( void ) +{ + m_numeratorModel.setValue( 4 ); + m_denominatorModel.setValue( 4 ); +} + + + + void meterModel::saveSettings( QDomDocument & _doc, QDomElement & _this, const QString & _name ) { diff --git a/src/core/song.cpp b/src/core/song.cpp index 35de2c262..1a14b2d82 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -71,14 +71,17 @@ #include "timeline.h" +tick midiTime::s_ticksPerTact = DefaultTicksPerTact; + song::song( void ) : trackContainer(), m_automationTrack( track::create( track::AutomationTrack, this ) ), - m_tempoModel( DEFAULT_BPM, MIN_BPM, MAX_BPM, intModel::defaultRelStep(), - this ), + m_tempoModel( DefaultTempo, MinTempo, MaxTempo, + intModel::defaultRelStep(), this ), m_timeSigModel( this, m_automationTrack ), + m_oldTicksPerTact( DefaultTicksPerTact ), m_masterVolumeModel( 100, 0, 200, 1, this ), m_masterPitchModel( 0, -12, 12, 1, this ), m_fileName(), @@ -151,8 +154,8 @@ void song::setTempo( void ) } } -// m_bpmSpinBox->setInitValue( _new_bpm ); engine::updateFramesPerTick(); + emit tempoChanged( tempo ); } @@ -161,8 +164,10 @@ void song::setTempo( void ) void song::setTimeSignature( void ) { - emit timeSignatureChanged( m_timeSigModel.getNumerator(), - m_timeSigModel.getDenominator() ); + midiTime::setTicksPerTact( ticksPerTact() ); + emit timeSignatureChanged( m_oldTicksPerTact, ticksPerTact() ); + emit dataChanged(); + m_oldTicksPerTact = ticksPerTact(); } @@ -185,15 +190,12 @@ void song::doActions( void ) switch( tl->behaviourAtStop() ) { case timeLine::BackToZero: - m_playPos[m_playMode].setTact( 0 ); m_playPos[m_playMode].setTicks( 0 ); break; case timeLine::BackToStart: if( tl->savedPos() >= 0 ) { - m_playPos[m_playMode].setTact( - tl->savedPos().getTact() ); m_playPos[m_playMode].setTicks( tl->savedPos().getTicks() ); tl->savePos( -1 ); @@ -208,7 +210,6 @@ void song::doActions( void ) } else { - m_playPos[m_playMode].setTact( 0 ); m_playPos[m_playMode].setTicks( 0 ); } @@ -353,8 +354,6 @@ void song::processNextBuffer( void ) if( m_playPos[m_playMode] < tl->loopBegin() || m_playPos[m_playMode] >= tl->loopEnd() ) { - m_playPos[m_playMode].setTact( - tl->loopBegin().getTact() ); m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); } @@ -376,7 +375,7 @@ void song::processNextBuffer( void ) int ticks = m_playPos[m_playMode].getTicks() + (int)( current_frame / frames_per_tick ); // did we play a whole tact? - if( ticks >= DefaultTicksPerTact ) + if( ticks >= midiTime::ticksPerTact() ) { // per default we just continue playing even if // there's no more stuff to play @@ -399,29 +398,23 @@ void song::processNextBuffer( void ) max_tact = m_patternToPlay->length() .getTact(); } + + // end of played object reached? if( m_playPos[m_playMode].getTact() + 1 - < max_tact ) + >= max_tact ) { - // next tact - m_playPos[m_playMode].setTact( - m_playPos[m_playMode].getTact() - + 1 ); - } - else - { - // first tact - m_playPos[m_playMode].setTact( 0 ); + // then start from beginning and keep + // offset + ticks = ticks % ( max_tact * + midiTime::ticksPerTact() ); } } - m_playPos[m_playMode].setTicks( ticks % - DefaultTicksPerTact ); + m_playPos[m_playMode].setTicks( ticks ); if( check_loop ) { if( m_playPos[m_playMode] >= tl->loopEnd() ) { - m_playPos[m_playMode].setTact( - tl->loopBegin().getTact() ); m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); } @@ -570,10 +563,9 @@ void song::updateLength( void ) -void song::setPlayPos( tact _tact_num, tick _tick, PlayModes _play_mode ) +void song::setPlayPos( tick _ticks, PlayModes _play_mode ) { - m_playPos[_play_mode].setTact( _tact_num ); - m_playPos[_play_mode].setTicks( _tick ); + m_playPos[_play_mode].setTicks( _ticks ); m_playPos[_play_mode].setCurrentFrame( 0.0f ); } @@ -795,7 +787,8 @@ void song::createNewProject( void ) "tripleoscillator" ); track::create( track::BBTrack, this ); - m_tempoModel.setInitValue( DEFAULT_BPM ); + m_tempoModel.setInitValue( DefaultTempo ); + m_timeSigModel.reset(); m_masterVolumeModel.setInitValue( 100 ); m_masterPitchModel.setInitValue( 0 ); @@ -847,6 +840,7 @@ void FASTCALL song::loadProject( const QString & _file_name ) // get the header information from the DOM m_tempoModel.loadSettings( mmp.head(), "bpm" ); + m_timeSigModel.loadSettings( mmp.head(), "timesig" ); m_masterVolumeModel.loadSettings( mmp.head(), "mastervol" ); m_masterPitchModel.loadSettings( mmp.head(), "masterpitch" ); @@ -928,6 +922,7 @@ bool song::saveProject( void ) multimediaProject mmp( multimediaProject::SongProject ); m_tempoModel.saveSettings( mmp, mmp.head(), "bpm" ); + m_timeSigModel.saveSettings( mmp, mmp.head(), "timesig" ); m_masterVolumeModel.saveSettings( mmp, mmp.head(), "mastervol" ); m_masterPitchModel.saveSettings( mmp, mmp.head(), "masterpitch" ); @@ -1028,21 +1023,14 @@ void song::restoreControllerStates( const QDomElement & _this ) -#warning TODO: move somewhere else -static inline QString baseName( const QString & _file ) -{ - return( QFileInfo( _file ).absolutePath() + "/" + - QFileInfo( _file ).completeBaseName() ); -} - - void song::exportProject( void ) { QString base_filename; if( m_fileName != "" ) { - base_filename = baseName( m_fileName ); + base_filename = QFileInfo( m_fileName ).absolutePath() + "/" + + QFileInfo( m_fileName ).completeBaseName(); } else { @@ -1115,6 +1103,8 @@ void song::setModified( void ) } + + void song::addController( controller * _c ) { if( _c != NULL && !m_controllers.contains( _c ) ) @@ -1125,6 +1115,8 @@ void song::addController( controller * _c ) } + + void song::removeController( controller * _controller ) { int index = m_controllers.indexOf( _controller ); diff --git a/src/core/timeline.cpp b/src/core/timeline.cpp index 5c7d2ef02..ac3e7d496 100644 --- a/src/core/timeline.cpp +++ b/src/core/timeline.cpp @@ -248,14 +248,15 @@ void timeLine::paintEvent( QPaintEvent * ) tact tact_num = m_begin.getTact(); int x = m_xOffset + s_posMarkerPixmap->width() / 2 - ( ( static_cast( m_begin * m_ppt ) / - DefaultTicksPerTact ) % + midiTime::ticksPerTact() ) % static_cast( m_ppt ) ); for( int i = 0; x + i * m_ppt < width(); ++i ) { ++tact_num; if( ( tact_num - 1 ) % - tMax( 1, static_cast( (float) DefaultTicksPerTact / + tMax( 1, static_cast( + (float) midiTime::ticksPerTact() / m_ppt ) ) == 0 ) { p.setPen( QColor( 224, 224, 224 ) ); @@ -295,7 +296,7 @@ void timeLine::mousePressEvent( QMouseEvent * _me ) { const midiTime t = m_begin + static_cast( _me->x() * - DefaultTicksPerTact / m_ppt ); + midiTime::ticksPerTact() / m_ppt ); m_action = MoveLoopBegin; if( m_loopPos[0] > m_loopPos[1] ) { @@ -325,11 +326,10 @@ void timeLine::mouseMoveEvent( QMouseEvent * _me ) { const midiTime t = m_begin + static_cast( tMax( _me->x() - m_xOffset - m_moveXOff, 0 ) * - DefaultTicksPerTact / m_ppt ); + midiTime::ticksPerTact() / m_ppt ); switch( m_action ) { case MovePositionMarker: - m_pos.setTact( t.getTact() ); m_pos.setTicks( t.getTicks() ); m_pos.setCurrentFrame( 0 ); updatePosition(); diff --git a/src/core/track.cpp b/src/core/track.cpp index 27e6ffb47..bd0bde669 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -285,7 +285,7 @@ void trackContentObjectView::updateLength( void ) { setFixedWidth( static_cast( m_tco->length() * pixelsPerTact() / - DefaultTicksPerTact ) + + midiTime::ticksPerTact() ) + TCO_BORDER_WIDTH * 2-1 ); } m_trackView->getTrackContainerView()->update(); @@ -462,7 +462,7 @@ void trackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) const int x = mapToParent( _me->pos() ).x() - m_initialMouseX; midiTime t = tMax( 0, (int) m_trackView->getTrackContainerView()->currentPosition()+ - static_cast( x * DefaultTicksPerTact / + static_cast( x * midiTime::ticksPerTact() / ppt ) ); if( engine::getMainWindow()->isCtrlPressed() == FALSE && _me->button() == Qt::NoButton ) @@ -473,7 +473,8 @@ void trackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) m_trackView->getTrackContentWidget()->changePosition(); s_textFloat->setText( QString( "%1:%2" ). arg( m_tco->startPosition().getTact() + 1 ). - arg( m_tco->startPosition().getTicks() ) ); + arg( m_tco->startPosition().getTicks() % + midiTime::ticksPerTact() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, 8 ) ); } else if( m_action == MoveSelection ) @@ -498,23 +499,23 @@ void trackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) tcos.push_back( tco ); smallest_pos = tMin( smallest_pos, (int)tco->startPosition() + - static_cast( dx * - DefaultTicksPerTact / ppt ) ); + static_cast( dx * + midiTime::ticksPerTact() / ppt ) ); } for( QVector::iterator it = tcos.begin(); it != tcos.end(); ++it ) { ( *it )->movePosition( ( *it )->startPosition() + - static_cast( dx * - DefaultTicksPerTact / ppt ) - + static_cast( dx * + midiTime::ticksPerTact() / ppt ) - smallest_pos ); } } else if( m_action == Resize ) { - midiTime t = tMax( DefaultTicksPerTact, + midiTime t = tMax( midiTime::ticksPerTact(), static_cast( _me->x() * - DefaultTicksPerTact / ppt ) ); + midiTime::ticksPerTact() / ppt ) ); if( engine::getMainWindow()->isCtrlPressed() == FALSE && _me->button() == Qt::NoButton ) { @@ -523,11 +524,14 @@ void trackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) m_tco->changeLength( t ); s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). arg( m_tco->length().getTact() ). - arg( m_tco->length().getTicks() ). + arg( m_tco->length().getTicks() % + midiTime::ticksPerTact() ). arg( m_tco->startPosition().getTact() + 1 ). - arg( m_tco->startPosition().getTicks() ). + arg( m_tco->startPosition().getTicks() % + midiTime::ticksPerTact() ). arg( m_tco->endPosition().getTact() + 1 ). - arg( m_tco->endPosition().getTicks() ) ); + arg( m_tco->endPosition().getTicks() % + midiTime::ticksPerTact() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, 8 ) ); } else @@ -767,7 +771,7 @@ void trackContentWidget::changePosition( const midiTime & _new_pos ) ( ts <= begin && te >= end ) ) { tcov->move( static_cast( ( ts - begin ) * ppt / - DefaultTicksPerTact ), + midiTime::ticksPerTact() ), tcov->y() ); if( !tcov->isVisible() ) { @@ -841,7 +845,7 @@ void trackContentWidget::mousePressEvent( QMouseEvent * _me ) !m_trackView->getTrackContainerView()->fixedTCOs() ) { const midiTime pos = getPosition( _me->x() ).getTact() * - DefaultTicksPerTact; + midiTime::ticksPerTact(); trackContentObject * tco = getTrack()->addTCO( getTrack()->createTCO( pos ) ); @@ -1012,7 +1016,7 @@ midiTime trackContentWidget::getPosition( int _mouse_x ) { return( midiTime( m_trackView->getTrackContainerView()-> currentPosition() + _mouse_x * - DefaultTicksPerTact / + midiTime::ticksPerTact() / static_cast( m_trackView-> getTrackContainerView()->pixelsPerTact() ) ) ); } @@ -1023,7 +1027,7 @@ midiTime trackContentWidget::endPosition( const midiTime & _pos_start ) { const float ppt = m_trackView->getTrackContainerView()->pixelsPerTact(); const int w = width(); - return( _pos_start + static_cast( w * DefaultTicksPerTact / + return( _pos_start + static_cast( w * midiTime::ticksPerTact() / ppt ) ); } @@ -1551,7 +1555,7 @@ trackContentObject * track::getTCO( int _tco_num ) } printf( "called track::getTCO( %d ), " "but TCO %d doesn't exist\n", _tco_num, _tco_num ); - return( addTCO( createTCO( _tco_num * DefaultTicksPerTact ) ) ); + return( addTCO( createTCO( _tco_num * midiTime::ticksPerTact() ) ) ); } @@ -1644,7 +1648,7 @@ void track::insertTact( const midiTime & _pos ) if( ( *it )->startPosition() >= _pos ) { ( *it )->movePosition( (*it)->startPosition() + - DefaultTicksPerTact ); + midiTime::ticksPerTact() ); } } } @@ -1662,7 +1666,7 @@ void track::removeTact( const midiTime & _pos ) if( ( *it )->startPosition() >= _pos ) { ( *it )->movePosition( tMax( ( *it )->startPosition() - - DefaultTicksPerTact, 0 ) ); + midiTime::ticksPerTact(), 0 ) ); } } } @@ -1673,17 +1677,18 @@ void track::removeTact( const midiTime & _pos ) tact track::length( void ) const { // find last end-position - int last = 0; + tick last = 0; for( tcoVector::const_iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { - const int cur = ( *it )->endPosition(); + const tick cur = ( *it )->endPosition(); if( cur > last ) { last = cur; } } - return( last/DefaultTicksPerTact + 1 ); + + return( last / midiTime::ticksPerTact() ); } diff --git a/src/gui/automation_editor.cpp b/src/gui/automation_editor.cpp index 8f35d5126..798a8807a 100644 --- a/src/gui/automation_editor.cpp +++ b/src/gui/automation_editor.cpp @@ -506,7 +506,6 @@ void automationEditor::keyPressEvent( QKeyEvent * _ke ) { if( ( m_timeLine->pos() -= 16 ) < 0 ) { - m_timeLine->pos().setTact( 0 ); m_timeLine->pos().setTicks( 0 ); } m_timeLine->updatePosition(); @@ -625,7 +624,6 @@ void automationEditor::keyPressEvent( QKeyEvent * _ke ) break; case Qt::Key_Home: - m_timeLine->pos().setTact( 0 ); m_timeLine->pos().setTicks( 0 ); m_timeLine->updatePosition(); break; diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index 813f622cd..a0c982de1 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -124,7 +124,7 @@ pianoRoll::pianoRollKeyTypes pianoRoll::prKeyOrder[] = } ; -const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DEFAULT_STEPS_PER_TACT; +const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DefaultStepsPerTact; pianoRoll::pianoRoll( void ) : @@ -456,6 +456,9 @@ pianoRoll::pianoRoll( void ) : resize( INITIAL_PIANOROLL_WIDTH, INITIAL_PIANOROLL_HEIGHT ); hide(); } + + connect( engine::getSong(), SIGNAL( timeSignatureChanged( int, int ) ), + this, SLOT( update() ) ); } @@ -594,10 +597,10 @@ inline void pianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, -inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, Uint16 _x, - Uint16 _y ) +inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, int _x, + int _y ) { - Uint16 middle_y = _y + KEY_LINE_HEIGHT / 2; + int middle_y = _y + KEY_LINE_HEIGHT / 2; _p.setPen( QColor( 0xFF, 0xDF, 0x20 ) ); timeMap & map = _n->detuning()->getAutomationPattern()->getTimeMap(); @@ -610,11 +613,11 @@ inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, Uint16 _x, { break; } - Uint16 pos_x = _x + pos_ticks * m_ppt / DefaultTicksPerTact; + int pos_x = _x + pos_ticks * m_ppt / midiTime::ticksPerTact(); const int level = it.value(); - Uint16 pos_y = middle_y - level * KEY_LINE_HEIGHT / 10; + int pos_y = middle_y - level * KEY_LINE_HEIGHT / 10; _p.drawLine( pos_x - 1, pos_y, pos_x + 1, pos_y ); _p.drawLine( pos_x, pos_y - 1, pos_x, pos_y + 1 ); @@ -682,7 +685,6 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) { if( ( m_timeLine->pos() -= 16 ) < 0 ) { - m_timeLine->pos().setTact( 0 ); m_timeLine->pos().setTicks( 0 ); } m_timeLine->updatePosition(); @@ -801,7 +803,6 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) break; case Qt::Key_Home: - m_timeLine->pos().setTact( 0 ); m_timeLine->pos().setTicks( 0 ); m_timeLine->updatePosition(); break; @@ -898,7 +899,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) x -= WHITE_KEY_WIDTH; // get tick in which the user clicked - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * midiTime::ticksPerTact() / m_ppt + m_currentPosition; @@ -928,7 +929,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) ( edit_note == TRUE && pos_ticks <= ( *it )->pos() + NE_LINE_WIDTH * - DefaultTicksPerTact / + midiTime::ticksPerTact() / m_ppt ) ) ) @@ -993,10 +994,10 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) m_currentNote = *it; // clicked at the "tail" of the note? - if( pos_ticks*m_ppt/DefaultTicksPerTact > + if( pos_ticks*m_ppt/midiTime::ticksPerTact() > ( m_currentNote->pos() + m_currentNote->length() )*m_ppt/ - DefaultTicksPerTact - + midiTime::ticksPerTact() - RESIZE_AREA_WIDTH && m_currentNote->length() > 0 ) { @@ -1016,7 +1017,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) m_currentNote->pos() - m_currentPosition ) * m_ppt ) / - DefaultTicksPerTact ); + midiTime::ticksPerTact() ); m_moveXOffset = x - aligned_x - 1; // set move-cursor QCursor c( Qt::SizeAllCursor ); @@ -1049,7 +1050,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) else if( _me->button() == Qt::LeftButton && m_editMode == SELECT ) { - // select an area of notes m_selectStartTick = pos_ticks; @@ -1072,7 +1072,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) else if( _me->button() == Qt::LeftButton && m_editMode == MOVE ) { - // move selection (including selected notes) // save position where move-process began @@ -1198,17 +1197,17 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) { // Use nearest-note when changing volume so the bars can // be "scribbled" - int pos_ticks = ( x * DefaultTicksPerTact ) / m_ppt + - m_currentPosition; + int pos_ticks = ( x * midiTime::ticksPerTact() ) / + m_ppt + m_currentPosition; // get note-vector of current pattern const noteVector & notes = m_pattern->notes(); // will be our iterator in the following loop noteVector::const_iterator it = notes.begin(); - + note * shortNote = NULL; - + // Max "snap length" 1/8 note on either side int shortDistance = DefaultTicksPerTact/8; @@ -1269,7 +1268,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) { x -= m_moveXOffset; } - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * midiTime::ticksPerTact() / m_ppt + m_currentPosition; if( m_action == MOVE_NOTE ) { @@ -1312,8 +1311,8 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) // set move- or resize-cursor // get tick in which the cursor is posated - int pos_ticks = ( x * DefaultTicksPerTact ) / m_ppt + - m_currentPosition; + int pos_ticks = ( x * midiTime::ticksPerTact() ) / + m_ppt + m_currentPosition; // get note-vector of current pattern const noteVector & notes = m_pattern->notes(); @@ -1349,10 +1348,11 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) } // cursor at the "tail" of the note? else if( ( *it )->length() > 0 && - pos_ticks*m_ppt/DefaultTicksPerTact > + pos_ticks*m_ppt / + midiTime::ticksPerTact() > ( ( *it )->pos() + ( *it )->length() )*m_ppt/ - DefaultTicksPerTact - + midiTime::ticksPerTact()- RESIZE_AREA_WIDTH ) { if( QApplication::overrideCursor() ) @@ -1441,7 +1441,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) } // get tick in which the cursor is posated - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * midiTime::ticksPerTact() / m_ppt + m_currentPosition; m_selectedTick = pos_ticks - @@ -1465,7 +1465,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) // move selection + selected notes // do horizontal move-stuff - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * midiTime::ticksPerTact() / m_ppt + m_currentPosition; int ticks_diff = pos_ticks - m_moveStartTick; @@ -1490,8 +1490,8 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) } m_selectStartTick += ticks_diff; - int tact_diff = ticks_diff / DefaultTicksPerTact; - ticks_diff = ticks_diff % DefaultTicksPerTact; + int tact_diff = ticks_diff / midiTime::ticksPerTact(); + ticks_diff = ticks_diff % midiTime::ticksPerTact(); // do vertical move-stuff int key_diff = key_num - m_moveStartKey; @@ -1539,10 +1539,10 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) ticks_diff; // ensure note_ticks range - if( note_ticks > DefaultTicksPerTact ) + if( note_ticks > midiTime::ticksPerTact() ) { - note_tact += (note_ticks/DefaultTicksPerTact); - note_ticks %= DefaultTicksPerTact; + note_tact += (note_ticks/midiTime::ticksPerTact() ); + note_ticks %= midiTime::ticksPerTact(); } /* Old 1/64th code if( note_ticks >> 6 ) @@ -1601,7 +1601,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) } // get tick in which the cursor is posated - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * midiTime::ticksPerTact()/ m_ppt + m_currentPosition; m_selectedTick = pos_ticks - @@ -1835,17 +1835,19 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) height() - PR_TOP_MARGIN - PR_BOTTOM_MARGIN ); // draw vertical raster - int tact_16th = m_currentPosition / ( DefaultTicksPerTact / 16 ); - const int offset = ( m_currentPosition % (DefaultTicksPerTact/16) ) * - m_ppt / DefaultTicksPerTact; + int tact_16th = m_currentPosition / DefaultBeatsPerTact; + const int offset = ( m_currentPosition % DefaultBeatsPerTact ) * + m_ppt / midiTime::ticksPerTact(); - for( int x = WHITE_KEY_WIDTH - offset; x < width(); - x += m_ppt / DEFAULT_STEPS_PER_TACT, ++tact_16th ) + // we need float here as odd time signatures might produce rounding + // errors else and thus an unusable grid + for( float x = WHITE_KEY_WIDTH - offset; x < width(); + x += (float) m_ppt / midiTime::stepsPerTact(), ++tact_16th ) { if( x >= WHITE_KEY_WIDTH ) { // every tact-start needs to be a bright line - if( tact_16th % 16 == 0 ) + if( tact_16th % midiTime::stepsPerTact() == 0 ) { p.setPen( QColor( 0x7F, 0x7F, 0x7F ) ); } @@ -1859,7 +1861,7 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) { p.setPen( QColor( 0x3F, 0x3F, 0x3F ) ); } - p.drawLine( x, PR_TOP_MARGIN, x, height() - + p.drawLine( (int)x, PR_TOP_MARGIN, (int)x, height() - PR_BOTTOM_MARGIN ); } } @@ -1915,9 +1917,9 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) Sint32 pos_ticks = ( *it )->pos(); int note_width = len_ticks * m_ppt / - DefaultTicksPerTact; + midiTime::ticksPerTact(); const int x = ( pos_ticks - m_currentPosition ) * - m_ppt / DefaultTicksPerTact; + m_ppt / midiTime::ticksPerTact(); // skip this note if not in visible area at all if( !( x + note_width >= 0 && x <= width() - WHITE_KEY_WIDTH ) ) @@ -2001,9 +2003,9 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) // now draw selection-frame int x = ( ( sel_pos_start - m_currentPosition ) * m_ppt ) / - DefaultTicksPerTact; + midiTime::ticksPerTact(); int w = ( ( ( sel_pos_end - m_currentPosition ) * m_ppt ) / - DefaultTicksPerTact ) - x; + midiTime::ticksPerTact() ) - x; int y = (int) y_base - sel_key_start * KEY_LINE_HEIGHT; int h = (int) y_base - sel_key_end * KEY_LINE_HEIGHT - y; p.setPen( QColor( 0, 64, 192 ) ); @@ -2089,7 +2091,7 @@ void pianoRoll::wheelEvent( QWheelEvent * _we ) if( _we->delta() > 0 ) { m_ppt = tMin( m_ppt * 2, KEY_LINE_HEIGHT * - DEFAULT_STEPS_PER_TACT * 8 ); + DefaultStepsPerTact * 8 ); } else if( m_ppt >= 72 ) { @@ -2576,17 +2578,18 @@ void pianoRoll::updatePosition( const midiTime & _t ) m_scrollBack == TRUE ) { const int w = width() - WHITE_KEY_WIDTH; - if( _t > m_currentPosition + w * DefaultTicksPerTact / m_ppt ) + if( _t > m_currentPosition + w * midiTime::ticksPerTact() / + m_ppt ) { m_leftRightScroll->setValue( _t.getTact() * - DefaultTicksPerTact ); + midiTime::ticksPerTact() ); } else if( _t < m_currentPosition ) { - midiTime t = tMax( _t - w * DefaultTicksPerTact * - DefaultTicksPerTact / m_ppt, 0 ); + midiTime t = tMax( _t - w * midiTime::ticksPerTact() * + midiTime::ticksPerTact() / m_ppt, 0 ); m_leftRightScroll->setValue( t.getTact() * - DefaultTicksPerTact ); + midiTime::ticksPerTact() ); } m_scrollBack = FALSE; } @@ -2626,7 +2629,7 @@ midiTime pianoRoll::newNoteLen( void ) const { return( m_lenOfNewNotes ); } - return( DefaultTicksPerTact / m_noteLenModel->currentText().right( + return( midiTime::ticksPerTact() / m_noteLenModel->currentText().right( m_noteLenModel->currentText().length() - 2 ).toInt() ); } @@ -2666,8 +2669,8 @@ noteVector::const_iterator pianoRoll::noteIteratorUnderMouse( void ) } int key_num = getKey( pos.y() ); - int pos_ticks = ( pos.x() - WHITE_KEY_WIDTH ) * DefaultTicksPerTact / - m_ppt + m_currentPosition; + int pos_ticks = ( pos.x() - WHITE_KEY_WIDTH ) * + midiTime::ticksPerTact() / m_ppt + m_currentPosition; // will be our iterator in the following loop noteVector::const_iterator it = notes.begin(); diff --git a/src/gui/song_editor.cpp b/src/gui/song_editor.cpp index b2beb91ab..427b45f6e 100644 --- a/src/gui/song_editor.cpp +++ b/src/gui/song_editor.cpp @@ -427,20 +427,18 @@ void songEditor::keyPressEvent( QKeyEvent * _ke ) } else if( _ke->key() == Qt::Key_Left ) { - tact interesting_tact = m_s->currentTact(); - if( interesting_tact > 0 ) + tick t = m_s->currentTick() - midiTime::ticksPerTact(); + if( t >= 0 ) { - m_s->setPlayPos( --interesting_tact, m_s->currentTick(), - song::Mode_PlaySong ); + m_s->setPlayPos( t, song::Mode_PlaySong ); } } else if( _ke->key() == Qt::Key_Right ) { - tact interesting_tact = m_s->currentTact(); - if( interesting_tact < MAX_SONG_LENGTH ) + tick t = m_s->currentTick() + midiTime::ticksPerTact(); + if( t < MaxSongLength ) { - m_s->setPlayPos( ++interesting_tact, m_s->currentTick(), - song::Mode_PlaySong ); + m_s->setPlayPos( t, song::Mode_PlaySong ); } } else if( _ke->key() == Qt::Key_Space ) @@ -456,7 +454,7 @@ void songEditor::keyPressEvent( QKeyEvent * _ke ) } else if( _ke->key() == Qt::Key_Home ) { - m_s->setPlayPos( 0, 0, song::Mode_PlaySong ); + m_s->setPlayPos( 0, song::Mode_PlaySong ); } else { @@ -576,7 +574,7 @@ void songEditor::masterPitchChanged( int _new_val ) && m_masterPitchSlider->showStatus() ) { m_mpsStatus->moveGlobal( m_masterPitchSlider, - QPoint( m_masterPitchSlider->width() + 2, -2 ) ); + QPoint( m_masterPitchSlider->width() + 2, -2 ) ); m_mpsStatus->setVisibilityTimeOut( 1000 ); } } @@ -587,7 +585,7 @@ void songEditor::masterPitchChanged( int _new_val ) void songEditor::masterPitchPressed( void ) { m_mpsStatus->moveGlobal( m_masterPitchSlider, - QPoint( m_masterPitchSlider->width() + 2, -2 ) ); + QPoint( m_masterPitchSlider->width() + 2, -2 ) ); m_mpsStatus->show(); masterPitchMoved( m_s->m_masterPitchModel.value() ); } @@ -619,15 +617,15 @@ void songEditor::updatePosition( const midiTime & _t ) { const int w = width() - DEFAULT_SETTINGS_WIDGET_WIDTH - TRACK_OP_WIDTH; - if( _t > m_currentPosition + w * DefaultTicksPerTact / + if( _t > m_currentPosition + w * midiTime::ticksPerTact() / pixelsPerTact() ) { m_leftRightScroll->setValue( _t.getTact() ); } else if( _t < m_currentPosition ) { - midiTime t = tMax( (int)( _t - w * DefaultTicksPerTact * - DefaultTicksPerTact / + midiTime t = tMax( + (int)( _t - w * midiTime::ticksPerTact() / pixelsPerTact() ), 0 ); m_leftRightScroll->setValue( t.getTact() ); @@ -652,21 +650,6 @@ void songEditor::zoomingChanged( void ) -void songEditor::updateTimeLinePosition( void ) -{ - if( m_s->m_playPos[m_s->m_playMode].m_timeLine != NULL && - m_s->m_playPos[m_s->m_playMode].m_timeLineUpdate == TRUE ) - { -/* QTimer::singleShot( 1, m_playPos[m_playMode].m_timeLine, - SLOT( updatePosition() ) );*/ - //m_playPos[m_playMode].m_timeLine->updatePosition(); - } -} - - - - - bool songEditor::allowRubberband( void ) const { return( m_editModeButton->isChecked() ); diff --git a/src/gui/track_container_view.cpp b/src/gui/track_container_view.cpp index 8a558fa71..d565316d6 100644 --- a/src/gui/track_container_view.cpp +++ b/src/gui/track_container_view.cpp @@ -77,6 +77,8 @@ trackContainerView::trackContainerView( trackContainer * _tc ) : setAcceptDrops( TRUE ); + connect( engine::getSong(), SIGNAL( timeSignatureChanged( int, int ) ), + this, SLOT( realignTracks() ) ); connect( m_tc, SIGNAL( trackAdded( track * ) ), this, SLOT( createTrackView( track * ) ), Qt::QueuedConnection ); diff --git a/src/gui/widgets/tempo_sync_knob.cpp b/src/gui/widgets/tempo_sync_knob.cpp index 48134689a..23d2896f0 100644 --- a/src/gui/widgets/tempo_sync_knob.cpp +++ b/src/gui/widgets/tempo_sync_knob.cpp @@ -168,9 +168,7 @@ void tempoSyncKnobModel::setSyncMode( tempoSyncMode _new_mode ) m_tempoSyncMode = _new_mode; if( _new_mode == SyncCustom ) { - connect( &m_custom, SIGNAL( numeratorChanged() ), - this, SLOT( updateCustom() ) ); - connect( &m_custom, SIGNAL( denominatorChanged() ), + connect( &m_custom, SIGNAL( dataChanged() ), this, SLOT( updateCustom() ) ); } } diff --git a/src/tracks/bb_track.cpp b/src/tracks/bb_track.cpp index 013310053..04b0f3538 100644 --- a/src/tracks/bb_track.cpp +++ b/src/tracks/bb_track.cpp @@ -198,7 +198,7 @@ void bbTCOView::paintEvent( QPaintEvent * ) tact t = engine::getBBTrackContainer()->lengthOfBB( bbTrack::numOfBBTrack( m_bbTCO->getTrack() ) ); - if( m_bbTCO->length() > DefaultTicksPerTact && t > 0 ) + if( m_bbTCO->length() > midiTime::ticksPerTact() && t > 0 ) { for( int x = static_cast( t * pixelsPerTact() ); x < width()-2; @@ -361,10 +361,10 @@ bool bbTrack::play( const midiTime & _start, const fpp_t _frames, } QList tcos; - getTCOsInRange( tcos, _start, _start + static_cast( _frames / + getTCOsInRange( tcos, _start, _start + static_cast( _frames / engine::framesPerTick() ) ); - if ( tcos.size() == 0 ) + if( tcos.size() == 0 ) { return( FALSE ); } @@ -381,6 +381,7 @@ bool bbTrack::play( const midiTime & _start, const fpp_t _frames, lastLen = ( *it )->length(); } } + if( _start - lastPosition < lastLen ) { return( engine::getBBTrackContainer()->play( _start - diff --git a/src/tracks/pattern.cpp b/src/tracks/pattern.cpp index 03a14ff1f..974fc7df8 100644 --- a/src/tracks/pattern.cpp +++ b/src/tracks/pattern.cpp @@ -67,7 +67,7 @@ pattern::pattern( instrumentTrack * _instrument_track ) : m_instrumentTrack( _instrument_track ), m_patternType( BeatPattern ), m_name( _instrument_track->name() ), - m_steps( DEFAULT_STEPS_PER_TACT ), + m_steps( midiTime::stepsPerTact() ), m_frozenPattern( NULL ), m_freezing( FALSE ), m_freezeAborted( FALSE ) @@ -120,6 +120,8 @@ pattern::~pattern() void pattern::init( void ) { + connect( engine::getSong(), SIGNAL( timeSignatureChanged( int, int ) ), + this, SLOT( changeTimeSignature() ) ); saveJournallingState( FALSE ); ensureBeatNotes(); @@ -135,29 +137,50 @@ midiTime pattern::length( void ) const { if( m_patternType == BeatPattern ) { - if( m_steps % DEFAULT_STEPS_PER_TACT == 0 ) - { - return( m_steps * BEATS_PER_TACT ); - } - return( ( m_steps / DEFAULT_STEPS_PER_TACT + 1 ) * - DEFAULT_STEPS_PER_TACT * BEATS_PER_TACT ); + return( beatPatternLength() ); } - Sint32 max_length = 0; + tick max_length = midiTime::ticksPerTact(); for( noteVector::const_iterator it = m_notes.begin(); - it != m_notes.end(); - ++it ) + it != m_notes.end(); ++it ) { - max_length = tMax( max_length, ( *it )->endPos() ); + if( ( *it )->length() > 0 ) + { + max_length = tMax( max_length, + ( *it )->endPos() ); + } } - if( max_length % DefaultTicksPerTact == 0 ) + return( midiTime( max_length ).nextFullTact() * + midiTime::ticksPerTact() ); +} + + + + +midiTime pattern::beatPatternLength( void ) const +{ + tick max_length = midiTime::ticksPerTact(); + + for( noteVector::const_iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) { - return( midiTime( tMax( max_length, - DefaultTicksPerTact ) ) ); + if( ( *it )->length() < 0 ) + { + max_length = tMax( max_length, ( *it )->pos() + + midiTime::ticksPerTact() / + midiTime::stepsPerTact() ); + } } - return( midiTime( tMax( midiTime( max_length ).getTact() + 1, 1 ), - 0 ) ); + + if( m_steps != midiTime::stepsPerTact() ) + { + max_length = m_steps * midiTime::ticksPerTact() / + midiTime::stepsPerTact() ; + } + + return( midiTime( max_length ).nextFullTact() * + midiTime::ticksPerTact() ); } @@ -368,7 +391,7 @@ void pattern::loadSettings( const QDomElement & _this ) m_steps = _this.attribute( "steps" ).toInt(); if( m_steps == 0 ) { - m_steps = DEFAULT_STEPS_PER_TACT; + m_steps = midiTime::stepsPerTact(); } ensureBeatNotes(); @@ -463,7 +486,9 @@ void pattern::removeSteps( int _n ) for( noteVector::iterator it = m_notes.begin(); it != m_notes.end(); ++it ) { - if( ( *it )->pos() == i * BEATS_PER_TACT && + if( ( *it )->pos() == + i * midiTime::ticksPerTact() / + midiTime::stepsPerTact() && ( *it )->length() <= 0 ) { removeNote( *it ); @@ -497,7 +522,9 @@ void pattern::ensureBeatNotes( void ) for( noteVector::iterator it = m_notes.begin(); it != m_notes.end(); ++it ) { - if( ( *it )->pos() == i * BEATS_PER_TACT && + if( ( *it )->pos() == + i * midiTime::ticksPerTact() / + midiTime::stepsPerTact() && ( *it )->length() <= 0 ) { found = TRUE; @@ -507,7 +534,8 @@ void pattern::ensureBeatNotes( void ) if( found == FALSE ) { addNote( note( midiTime( 0 ), midiTime( i * - BEATS_PER_TACT ) ) ); + midiTime::ticksPerTact() / + midiTime::stepsPerTact() ) ), FALSE ); } } } @@ -528,8 +556,8 @@ void pattern::updateBBTrack( void ) bool pattern::empty( void ) { - for( noteVector::iterator it = m_notes.begin(); it != m_notes.end(); - ++it ) + for( noteVector::const_iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) { if( ( *it )->length() != 0 ) { @@ -542,6 +570,37 @@ bool pattern::empty( void ) +void pattern::changeTimeSignature( void ) +{ + midiTime last_pos = midiTime::ticksPerTact(); + for( noteVector::const_iterator cit = m_notes.begin(); + cit != m_notes.end(); ++cit ) + { + if( ( *cit )->length() < 0 && ( *cit )->pos() > last_pos ) + { + last_pos = ( *cit )->pos()+midiTime::ticksPerTact() / + midiTime::stepsPerTact(); + } + } + 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; + m_notes.erase( it ); + --m_steps; + } + else + { + ++it; + } + } + m_steps = qMax( qMax( m_steps, midiTime::stepsPerTact() ), + last_pos.getTact() * midiTime::stepsPerTact() ); + ensureBeatNotes(); +} + @@ -671,7 +730,6 @@ void patternFreezeThread::run( void ) engine::getSong()->playPattern( m_pattern, FALSE ); song::playPos & ppp = engine::getSong()->getPlayPos( song::Mode_PlayPattern ); - ppp.setTact( 0 ); ppp.setTicks( 0 ); ppp.setCurrentFrame( 0 ); ppp.m_timeLineUpdate = FALSE; @@ -838,7 +896,7 @@ void patternView::changeName( void ) void patternView::addSteps( QAction * _item ) { - m_pat->addSteps( _item->text().toInt() ); + m_pat->addSteps( _item->text().section( ' ', 0, 0 ).toInt() ); } @@ -846,7 +904,7 @@ void patternView::addSteps( QAction * _item ) void patternView::removeSteps( QAction * _item ) { - m_pat->removeSteps( _item->text().toInt() ); + m_pat->removeSteps( _item->text().section( ' ', 0, 0 ).toInt() ); } @@ -926,7 +984,7 @@ void patternView::mouseDoubleClickEvent( QMouseEvent * _me ) if( m_pat->type() == pattern::MelodyPattern || !( m_pat->type() == pattern::BeatPattern && ( pixelsPerTact() >= 192 || - m_pat->m_steps != DEFAULT_STEPS_PER_TACT ) && + m_pat->m_steps != midiTime::stepsPerTact() ) && _me->y() > height() - s_stepBtnOff->height() ) ) { openInPianoRoll(); @@ -941,11 +999,11 @@ void patternView::mousePressEvent( QMouseEvent * _me ) if( _me->button() == Qt::LeftButton && m_pat->m_patternType == pattern::BeatPattern && ( fixedTCOs() || pixelsPerTact() >= 96 || - m_pat->m_steps != DEFAULT_STEPS_PER_TACT ) && + m_pat->m_steps != midiTime::stepsPerTact() ) && _me->y() > height() - s_stepBtnOff->height() ) { int step = ( _me->x() - TCO_BORDER_WIDTH ) * - m_pat->length() / BEATS_PER_TACT / width(); + m_pat->length() / DefaultBeatsPerTact / width(); if( step >= m_pat->m_steps ) { return; @@ -988,12 +1046,12 @@ void patternView::mousePressEvent( QMouseEvent * _me ) void patternView::wheelEvent( QWheelEvent * _we ) { if( m_pat->m_patternType == pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 192 || - m_pat->m_steps != DEFAULT_STEPS_PER_TACT ) && + ( fixedTCOs() || pixelsPerTact() >= 96 || + m_pat->m_steps != midiTime::stepsPerTact() ) && _we->y() > height() - s_stepBtnOff->height() ) { int step = ( _we->x() - TCO_BORDER_WIDTH ) * - m_pat->length() / BEATS_PER_TACT / width(); + m_pat->length() / DefaultBeatsPerTact / width(); if( step >= m_pat->m_steps ) { return; @@ -1078,14 +1136,28 @@ void patternView::paintEvent( QPaintEvent * ) / (float) m_pat->length().getTact() : pixelsPerTact(); + const int x_base = TCO_BORDER_WIDTH; + p.setPen( QColor( 0, 0, 0 ) ); + for( tact tact_num = 1; tact_num < + m_pat->length().getTact(); ++tact_num ) + { + p.drawLine( + x_base + static_cast( + ppt * tact_num ) - 1, + TCO_BORDER_WIDTH, + x_base + static_cast( + ppt * tact_num ) - 1, + height() - 2 * + TCO_BORDER_WIDTH ); + } if( m_pat->m_patternType == pattern::MelodyPattern ) { - Sint32 central_key = 0; + int central_key = 0; if( m_pat->m_notes.size() > 0 ) { // first determine the central tone so that we can // display the area where most of the m_notes are - Sint32 total_notes = 0; + int total_notes = 0; for( noteVector::iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { @@ -1100,13 +1172,10 @@ void patternView::paintEvent( QPaintEvent * ) { central_key = central_key / total_notes; - Sint16 central_y = height() / 2; - Sint16 y_base = central_y + TCO_BORDER_WIDTH -1; + int central_y = height() / 2; + int y_base = central_y + TCO_BORDER_WIDTH -1; - const Sint16 x_base = TCO_BORDER_WIDTH; - - p.setPen( QColor( 0, 0, 0 ) ); - for( tact tact_num = 1; tact_num < +/* for( tact tact_num = 1; tact_num < m_pat->length().getTact(); ++tact_num ) { p.drawLine( @@ -1117,7 +1186,7 @@ void patternView::paintEvent( QPaintEvent * ) ppt * tact_num ) - 1, height() - 2 * TCO_BORDER_WIDTH ); - } + }*/ if( m_pat->getTrack()->muted() || m_pat->muted() ) { @@ -1143,10 +1212,11 @@ void patternView::paintEvent( QPaintEvent * ) y_pos > -central_y && y_pos < central_y ) { - Sint16 x1 = 2 * x_base + - static_cast( ( *it )->pos() * ppt / DefaultTicksPerTact ); - Sint16 x2 = - static_cast( ( ( *it )->pos() + ( *it )->length() ) * ppt / DefaultTicksPerTact ); + int x1 = 2 * x_base + + static_cast( ( *it )->pos() * ppt / + midiTime::ticksPerTact() ); + int x2 = + static_cast( ( ( *it )->pos() + ( *it )->length() ) * ppt / midiTime::ticksPerTact() ); p.drawLine( x1, y_base + y_pos, x2, y_base + y_pos ); @@ -1156,14 +1226,14 @@ void patternView::paintEvent( QPaintEvent * ) } } else if( m_pat->m_patternType == pattern::BeatPattern && - ( fixedTCOs() || ppt >= 96 - || m_pat->m_steps != DEFAULT_STEPS_PER_TACT ) ) + ( fixedTCOs() || ppt >= 96 + || m_pat->m_steps != midiTime::stepsPerTact() ) ) { QPixmap stepon; QPixmap stepoverlay; QPixmap stepoff; QPixmap stepoffl; - const int steps = m_pat->length() / BEATS_PER_TACT; + const int steps = m_pat->length() / DefaultBeatsPerTact; const int w = width() - 2 * TCO_BORDER_WIDTH; stepon = s_stepBtnOn->scaled( w / steps, s_stepBtnOn->height(), @@ -1184,10 +1254,10 @@ void patternView::paintEvent( QPaintEvent * ) for( noteVector::iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { - Sint16 no = ( *it )->pos() / BEATS_PER_TACT; - Sint16 x = TCO_BORDER_WIDTH + static_cast( no * + int no = ( *it )->pos() / DefaultBeatsPerTact; + int x = TCO_BORDER_WIDTH + static_cast( no * w / steps ); - Sint16 y = height() - s_stepBtnOff->height() - 1; + int y = height() - s_stepBtnOff->height() - 1; Uint8 vol = ( *it )->getVolume();