65 for (
const auto ppattern : *pOther->m_pPlayingPatterns ) {
66 if ( ppattern !=
nullptr ) {
72 for (
const auto ppattern : *pOther->m_pNextPatterns ) {
73 if ( ppattern !=
nullptr ) {
216 const auto pSong = pHydrogen->getSong();
217 const auto pTimeline = pHydrogen->getTimeline();
218 const auto pAudioEngine = pHydrogen->getAudioEngine();
219 const auto pAudioDriver = pHydrogen->getAudioOutput();
221 if ( pSong ==
nullptr || pTimeline ==
nullptr ) {
226 if ( pAudioDriver ==
nullptr ) {
227 ERRORLOG(
"AudioDriver is not ready!" );
232 if ( nSampleRate == 0 ) {
233 nSampleRate = pAudioDriver->getSampleRate();
235 const int nResolution = pSong->getResolution();
236 const double fSongSizeInTicks = pAudioEngine->getSongSizeInTicks();
238 if ( nSampleRate == 0 || nResolution == 0 ) {
239 ERRORLOG(
"Not properly initialized yet" );
249 const auto tempoMarkers = pTimeline->getAllTempoMarkers();
253 long long nNewFrame = 0;
254 if ( pHydrogen->isTimelineEnabled() &&
255 ! ( tempoMarkers.size() == 1 &&
256 pTimeline->isFirstTempoMarkerSpecial() ) &&
258 pSong->getPatternGroupVector()->size() > 0 ) {
260 double fNewTick = fTick;
261 double fRemainingTicks = fTick;
262 double fNextTick, fPassedTicks = 0;
263 double fNextTickSize;
264 double fNewFrame = 0;
267 const int nColumns = pSong->getPatternGroupVector()->size();
269 auto handleEnd = [&]() {
271 fNewFrame += fRemainingTicks * fNextTickSize;
273 nNewFrame =
static_cast<long long>( std::round( fNewFrame ) );
280 const double fRoundingErrorInTicks =
281 ( fNewFrame -
static_cast<double>( nNewFrame ) ) /
289 if ( fRoundingErrorInTicks >
290 fPassedTicks + fRemainingTicks - fNextTick ) {
293 *fTickMismatch = fRoundingErrorInTicks;
298 *fTickMismatch = fPassedTicks + fRemainingTicks - fNextTick;
300 const double fFinalFrame = fNewFrame +
301 ( fNextTick - fPassedTicks - fRemainingTicks ) * fNextTickSize;
304 double fFinalTickSize;
305 if ( ii < tempoMarkers.size() ) {
307 nSampleRate, tempoMarkers[ ii ]->fBpm, nResolution );
311 nSampleRate, tempoMarkers[ 0 ]->fBpm, nResolution );
325 *fTickMismatch += ( fFinalFrame -
static_cast<double>(nNewFrame) ) /
344 fRemainingTicks -= fNewTick - fPassedTicks;
347 while ( fRemainingTicks > 0 ) {
349 for ( ii = 1; ii <= tempoMarkers.size(); ++ii ) {
350 if ( ii == tempoMarkers.size() ||
351 tempoMarkers[ ii ]->nColumn >= nColumns ) {
352 fNextTick = fSongSizeInTicks;
355 static_cast<double>(pHydrogen->getTickForColumn( tempoMarkers[ ii ]->nColumn ) );
360 tempoMarkers[ ii - 1 ]->fBpm,
363 if ( fRemainingTicks > ( fNextTick - fPassedTicks ) ) {
366 fNewFrame += ( fNextTick - fPassedTicks ) * fNextTickSize;
381 fRemainingTicks -= fNextTick - fPassedTicks;
383 fPassedTicks = fNextTick;
392 if ( fRemainingTicks > 0 ) {
396 const int nRepetitions = std::floor(fTick / fSongSizeInTicks);
397 const double fSongSizeInFrames = fNewFrame;
399 fNewFrame *=
static_cast<double>(nRepetitions);
400 fNewTick = std::fmod( fTick, fSongSizeInTicks );
401 fRemainingTicks = fNewTick;
414 if ( std::isinf( fNewFrame ) ||
415 static_cast<long long>(fNewFrame) >
416 std::numeric_limits<long long>::max() ) {
417 ERRORLOG( QString(
"Provided ticks [%1] are too large." ).arg( fTick ) );
425 if ( fRemainingTicks == 0 ) {
426 ii = tempoMarkers.size();
427 fNextTick =
static_cast<double>(pHydrogen->getTickForColumn(
428 tempoMarkers[ 0 ]->nColumn ) );
430 nSampleRate, tempoMarkers[ ii - 1 ]->fBpm, nResolution );
444 const double fTickSize =
449 const double fNewFrame =
static_cast<double>(fTick) *
451 nNewFrame =
static_cast<long long>( std::round( fNewFrame ) );
452 *fTickMismatch = ( fNewFrame -
static_cast<double>(nNewFrame ) ) /
470 ERRORLOG( QString(
"Provided frame [%1] must be non-negative" ).arg( nFrame ) );
473 const auto pSong = pHydrogen->getSong();
474 const auto pTimeline = pHydrogen->getTimeline();
475 const auto pAudioEngine = pHydrogen->getAudioEngine();
476 const auto pAudioDriver = pHydrogen->getAudioOutput();
478 if ( pSong ==
nullptr || pTimeline ==
nullptr ) {
482 if ( pAudioDriver ==
nullptr ) {
483 ERRORLOG(
"AudioDriver is not ready!" );
487 if ( nSampleRate == 0 ) {
488 nSampleRate = pAudioDriver->getSampleRate();
490 const int nResolution = pSong->getResolution();
493 const double fSongSizeInTicks = pAudioEngine->getSongSizeInTicks();
495 if ( nSampleRate == 0 || nResolution == 0 ) {
496 ERRORLOG(
"Not properly initialized yet" );
504 const auto tempoMarkers = pTimeline->getAllTempoMarkers();
508 if ( pHydrogen->isTimelineEnabled() &&
509 ! ( tempoMarkers.size() == 1 &&
510 pTimeline->isFirstTempoMarkerSpecial() ) &&
512 pSong->getPatternGroupVector()->size() ) {
516 const double fTargetFrame =
static_cast<double>(nFrame);
517 double fPassedFrames = 0;
518 double fNextFrame = 0;
519 double fNextTicks, fPassedTicks = 0;
520 double fNextTickSize;
521 long long nRemainingFrames;
523 const int nColumns = pSong->getPatternGroupVector()->size();
525 while ( fPassedFrames < fTargetFrame ) {
527 for (
int ii = 1; ii <= tempoMarkers.size(); ++ii ) {
531 tempoMarkers[ ii - 1 ]->fBpm,
534 if ( ii == tempoMarkers.size() ||
535 tempoMarkers[ ii ]->nColumn >= nColumns ) {
536 fNextTicks = fSongSizeInTicks;
539 static_cast<double>(pHydrogen->getTickForColumn( tempoMarkers[ ii ]->nColumn ));
541 fNextFrame = (fNextTicks - fPassedTicks) * fNextTickSize;
543 if ( fNextFrame < ( fTargetFrame -
563 fTick += fNextTicks - fPassedTicks;
565 fPassedFrames += fNextFrame;
566 fPassedTicks = fNextTicks;
570 const double fNewTick = (fTargetFrame - fPassedFrames ) /
590 fPassedFrames = fTargetFrame;
596 if ( fPassedFrames != fTargetFrame ) {
600 const double fSongSizeInFrames = fPassedFrames;
601 const int nRepetitions = std::floor(fTargetFrame / fSongSizeInFrames);
602 if ( fSongSizeInTicks * nRepetitions >
603 std::numeric_limits<double>::max() ) {
604 ERRORLOG( QString(
"Provided frames [%1] are too large." ).arg( nFrame ) );
607 fTick = fSongSizeInTicks * nRepetitions;
609 fPassedFrames =
static_cast<double>(nRepetitions) *
631 const double fTickSize =
636 fTick =
static_cast<double>(nFrame) / fTickSize;
658 sOutput = QString(
"%1[TransportPosition]\n" ).arg( sPrefix )
659 .append( QString(
"%1%2m_sLabel: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_sLabel ) )
660 .append( QString(
"%1%2m_nFrame: %3\n" ).arg( sPrefix ).arg( s ).arg(
getFrame() ) )
661 .append( QString(
"%1%2m_fTick: %3\n" ).arg( sPrefix ).arg( s ).arg(
getDoubleTick(), 0,
'f' ) )
662 .append( QString(
"%1%2m_fTick (rounded): %3\n" ).arg( sPrefix ).arg( s ).arg(
getTick() ) )
663 .append( QString(
"%1%2m_fTickSize: %3\n" ).arg( sPrefix ).arg( s ).arg(
getTickSize(), 0,
'f' ) )
664 .append( QString(
"%1%2m_fBpm: %3\n" ).arg( sPrefix ).arg( s ).arg(
getBpm(), 0,
'f' ) )
665 .append( QString(
"%1%2m_nPatternStartTick: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nPatternStartTick ) )
666 .append( QString(
"%1%2m_nPatternTickPosition: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nPatternTickPosition ) )
667 .append( QString(
"%1%2m_nColumn: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nColumn ) )
668 .append( QString(
"%1%2m_fTickMismatch: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_fTickMismatch, 0,
'f' ) )
669 .append( QString(
"%1%2m_nFrameOffsetTempo: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nFrameOffsetTempo ) )
670 .append( QString(
"%1%2m_fTickOffsetQueuing: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_fTickOffsetQueuing, 0,
'f' ) )
671 .append( QString(
"%1%2m_fTickOffsetSongSize: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_fTickOffsetSongSize, 0,
'f' ) );
673 sOutput.append( QString(
"%1%2m_pPlayingPatterns: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_pPlayingPatterns->toQString( sPrefix + s ), bShort ) );
676 sOutput.append( QString(
"%1%2m_pNextPatterns: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_pNextPatterns->toQString( sPrefix + s ), bShort ) );
678 sOutput.append( QString(
"%1%2m_nPatternSize: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nPatternSize ) )
679 .append( QString(
"%1%2m_nLastLeadLagFactor: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nLastLeadLagFactor ) )
680 .append( QString(
"%1%2m_nBar: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nBar ) )
681 .append( QString(
"%1%2m_nBeat: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nBeat ) );
684 sOutput = QString(
"%1[TransportPosition]" ).arg( sPrefix )
685 .append( QString(
" m_sLabel: %1" ).arg(
m_sLabel ) )
686 .append( QString(
", m_nFrame: %1" ).arg(
getFrame() ) )
687 .append( QString(
", m_fTick: %1" ).arg(
getDoubleTick(), 0,
'f' ) )
688 .append( QString(
", m_fTick (rounded): %1" ).arg(
getTick() ) )
689 .append( QString(
", m_fTickSize: %1" ).arg(
getTickSize(), 0,
'f' ) )
690 .append( QString(
", m_fBpm: %1" ).arg(
getBpm(), 0,
'f' ) )
693 .append( QString(
", m_nColumn: %1" ).arg(
m_nColumn ) )
694 .append( QString(
", m_fTickMismatch: %1" ).arg(
m_fTickMismatch, 0,
'f' ) )
699 sOutput.append( QString(
", m_pPlayingPatterns: %1" ).arg(
m_pPlayingPatterns->toQString( sPrefix + s ), bShort ) );
702 sOutput.append( QString(
", m_pNextPatterns: %1" ).arg(
m_pNextPatterns->toQString( sPrefix + s ), bShort ) );
704 sOutput.append( QString(
", m_nPatternSize: %1" ).arg(
m_nPatternSize ) )
706 .append( QString(
", m_nBar: %1" ).arg(
m_nBar ) )
707 .append( QString(
", m_nBeat: %1" ).arg(
m_nBeat ) );