Changeset 527

Show
Ignore:
Timestamp:
09/27/08 17:46:55 (5 years ago)
Author:
gabriel
Message:

Redefine getTickPosition() to return the actual tick position (without any lookahead).

A forum user reported [1] that MIDI notes are *sounding* at the right time,
but being *recorded* about 1/16th late. Sebastian Moors (smoors) said [2]
that he isolated to SVN rev 210, where lead-lag was introduced. In
that commit, the value of m_nPatternTickPosition was adjusted to
include a lookahead factor. This allowed notes with positive lead and
positive humanize (i.e. before the beat) to be correctly scheduled.
However, realtime notes were then recorded *with* the leadlag, putting
notes 5 ticks + 2000 frames late (typ. 8-11 ticks). It was typically
not noticeable with quantize on -- but with quantize off, it was
always present. To correct this, I rewrote getTickPosition() to
recalculate the tick... rather than use the global
m_nPatternTickPosition (which is integral to updateNoteQueue's
scheduling).

This commit has one (minor) issue: If you turn on quantize and you
give a note that is way out in front of the beat (at the edge of the
quantize window), you will probably hear the note twice: Once for the
realtime event, and once for the note that was recorded in the
pattern. I believe that this only happens when the realtime note and
the scheduled (quantized) note differ by the amount of lookahead.

[1]  http://www.hydrogen-music.org/forum/?action=show_thread&thread=882&fid=5&page=1
[2] e-mail to hydrogen-devel@…, 08SEP2008.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/libs/hydrogen/src/hydrogen.cpp

    r503 r527  
    14151415 
    14161416 
    1417 // unsigned long audioEngine_getTickPosition() 
    1418 // { 
    1419 //      return m_nPatternTickPosition; 
    1420 // } 
    1421  
    1422  
    14231417AudioOutput* createDriver( const QString& sDriver ) 
    14241418{ 
     
    18891883 
    18901884                        // hear note if its not in the future 
    1891                         if ( pref->getHearNewNotes() 
    1892                              && position <= getTickPosition() ) { 
     1885                        // Let the scheduler worry if it's in the future or not. 
     1886                        if ( pref->getHearNewNotes() ) { 
    18931887                                hearnote = true; 
    18941888                        } 
     
    19311925 
    19321926 
    1933  
     1927// Returns the current (real-time) tick, relative to the current 
     1928// (or first) pattern being played. 
    19341929unsigned long Hydrogen::getTickPosition() 
    19351930{ 
    1936         return m_nPatternTickPosition; 
     1931        if( m_pSong == 0 ) { 
     1932                return 0; 
     1933        } 
     1934        TransportInfo& xsp = m_pAudioDriver->m_transport; 
     1935        int tick, starttick, patsize, rv; 
     1936        tick = xsp.m_nFrames / xsp.m_nTickSize; 
     1937        starttick = 0; 
     1938        patsize = 1; 
     1939        if( m_pSong->get_mode() == Song::SONG_MODE ) { 
     1940                rv = findPatternInTick( tick, m_pSong->is_loop_enabled(), &starttick); 
     1941                if(m_nSongSizeInTicks > 0) patsize = m_nSongSizeInTicks; 
     1942        } else if( (m_pSong->get_mode() == Song::PATTERN_MODE) 
     1943                   && (m_pPlayingPatterns->get_size() != 0)) { 
     1944                starttick = m_nPatternStartTick; 
     1945                patsize = m_pPlayingPatterns->get(0)->get_lenght(); 
     1946        } // else make do with the absolute tick. 
     1947        tick = ( tick - starttick ); 
     1948        if(patsize > 1) tick %= patsize; 
     1949        if(tick < 0) tick += patsize; 
     1950        assert(tick >= 0); 
     1951        return (unsigned)tick; 
    19371952} 
    19381953