/// Take beat-bar-tick info from the Jack system, and translate it to a new internal frame position and ticksize. void JackOutput::relocateBBT() { Preferences* pPref = Preferences::get_instance(); //wolke if hydrogen is jack time master this is not relevant if ( m_transport.m_status != TransportInfo::ROLLING || pPref->m_bJackMasterMode == Preferences::USE_JACK_TIME_MASTER || ! ( m_JackTransportPos.valid & JackPositionBBT ) ) { WARNINGLOG( "Relocate: Call it off" ); return; } //WARNINGLOG( "Resyncing!" ); INFOLOG( "..." ); Hydrogen * H = Hydrogen::get_instance(); Song * S = H->getSong(); float hydrogen_TPB = ( float )( S->__resolution / m_JackTransportPos.beat_type * 4 ); long bar_ticks = 0; //long beat_ticks = 0; if ( S->get_mode() == Song::SONG_MODE ) { // (Reasonable?) assumption that one pattern is _always_ 1 bar long! bar_ticks = H->getTickForPosition( m_JackTransportPos.bar-1 ); // ignore error NOTE This is wrong -- if loop state is off, transport should just stop ?? if ( bar_ticks < 0 ) bar_ticks = 0; } float hydrogen_ticks_to_locate = bar_ticks + ( m_JackTransportPos.beat-1 ) * hydrogen_TPB + m_JackTransportPos.tick * ( hydrogen_TPB / m_JackTransportPos.ticks_per_beat ); // INFOLOG( QString( "Position from Time Master: BBT [%1,%2,%3]" ) . arg( m_JackTransportPos.bar ) . arg( m_JackTransportPos.beat ) . arg( m_JackTransportPos.tick ) ); // WARNINGLOG( QString(bbt) + " -- Tx/Beat = "+to_string(m_JackTransportPos.ticks_per_beat)+", Meter "+to_string(m_JackTransportPos.beats_per_bar)+"/"+to_string(m_JackTransportPos.beat_type)+" =>tick " + to_string( hydrogen_ticks_to_locate ) ); float fNewTickSize = getSampleRate() * 60.0 / m_transport.m_nBPM / S->__resolution; // not S->m_fBPM !?? if ( fNewTickSize == 0 ) return; // ??!? // NOTE this _should_ prevent audioEngine_process_checkBPMChanged in Hydrogen.cpp from recalculating things. m_transport.m_nTickSize = fNewTickSize; long long nNewFrames = ( long long )( hydrogen_ticks_to_locate * fNewTickSize ); #ifndef JACK_NO_BBT_OFFSET if ( m_JackTransportPos.valid & JackBBTFrameOffset ) nNewFrames += m_JackTransportPos.bbt_offset; #endif m_transport.m_nFrames = nNewFrames; }
void JackAudioDriver::relocateBBT() { Preferences* pPref = Preferences::get_instance(); // If Hydrogen itself is the JACK timebase master, this // function is not relevant. if ( m_transport.m_status != TransportInfo::ROLLING || pPref->m_bJackMasterMode == Preferences::USE_JACK_TIME_MASTER || ! ( m_JackTransportPos.valid & JackPositionBBT ) ) { // WARNINGLOG( "Relocate: Call it off" ); return; } // WARNINGLOG( "Relocate..." ); Hydrogen * H = Hydrogen::get_instance(); Song * S = H->getSong(); // m_JackTransportPos.beat_type contains the denominator of // the time signature and is given in number of ticks per // quarter. Thus, hydrogen_TPB contains the number of beats // per denominator of the JACK time signature. (Ticks per bar) float hydrogen_TPB = ( float )( S->__resolution / m_JackTransportPos.beat_type * 4 ); long bar_ticks = 0; //long beat_ticks = 0; if ( S->get_mode() == Song::SONG_MODE ) { // m_JackTransportPos.bar accesses the current bar at // the transport position. (Reasonable?) assumption // that one pattern is _always_ 1 bar long! bar_ticks = H->getTickForPosition( m_JackTransportPos.bar-1 ); // If a tick corresponding to the position of the // current bar-1 could not be found, we will use the // tick at the very beginning of the song instead. if ( bar_ticks < 0 ) bar_ticks = 0; } // m_JackTransportPos.beat refers to the current beat within a // bar, m_JackTransportPos.tick to the current tick within a // beat, and m_JackTransportPos.ticks_per_beat to the number // of ticks per beat. // Using hydrogen_TPB as conversion factor, the relocation // position in ticks will be calculated by combining the // current bar, beat, and tick. float hydrogen_ticks_to_locate = bar_ticks + ( m_JackTransportPos.beat-1 ) * hydrogen_TPB + m_JackTransportPos.tick * ( hydrogen_TPB / m_JackTransportPos.ticks_per_beat ); INFOLOG( QString( "Position from Timebase Master: BBT [%1,%2,%3]" ).arg( m_JackTransportPos.bar ).arg( m_JackTransportPos.beat ).arg( m_JackTransportPos.tick ) ); // WARNINGLOG( "Tx/Beat = "+to_string(m_JackTransportPos.ticks_per_beat)+", Meter "+to_string(m_JackTransportPos.beats_per_bar)+"/"+to_string(m_JackTransportPos.beat_type)+" =>tick " + to_string( hydrogen_ticks_to_locate ) ); // Before calling this function in updateTransportInfo() the // speed obtained by the JACK server query was already written // to m_transport.m_nBPM. This value can thus be considered // clean. float fNewTickSize = getSampleRate() * 60.0 / m_transport.m_nBPM / S->__resolution; if ( fNewTickSize == 0 ) return; // Note that this will prevent // audioEngine_process_checkBPMChanged() in Hydrogen.cpp from // recalculating things unless m_transport.m_nBpm and S->__bpm // aren't equal. m_transport.m_nTickSize = fNewTickSize; // New transport position in frames long long nNewFrames = ( long long )( hydrogen_ticks_to_locate * fNewTickSize ); #ifndef JACK_NO_BBT_OFFSET // m_JackTransportPos.bbt_offset is a frame offset for the BBT // fields (the given bar, beat, and tick values actually refer // to a time frame_offset frames before the start of the // cycle), should be assumed to be 0 if JackBBTFrameOffset is // not set. If JackBBTFrameOffset is set and this value is // zero, the BBT time refers to the first frame of this // cycle. If the value is positive, the BBT time refers to a // frame that many frames before the start of the cycle. // // Due to the if clause in the beginning of the function, the // following if clause is true at all times. if ( m_JackTransportPos.valid & JackBBTFrameOffset ) nNewFrames += m_JackTransportPos.bbt_offset; #endif m_transport.m_nFrames = nNewFrames; }