From 394c6c35aa4e8ac323d93b5e659bb0738e630d6c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 27 Oct 2025 19:34:21 -0500 Subject: [PATCH] earliest implementation of sync does not loop correctly --- src/engine/engine.cpp | 29 +++++++++++++++++++++++++++++ src/engine/engine.h | 9 +++++++++ src/engine/filePlayer.cpp | 11 +++++++++++ src/engine/filePlayer.h | 1 + src/engine/playback.cpp | 2 +- src/gui/refPlayer.cpp | 22 +++++++++++++++++++--- 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 190d9918d..2ef21be66 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1658,6 +1658,14 @@ DivFilePlayer* DivEngine::getFilePlayer() { return curFilePlayer; } +bool DivEngine::getFilePlayerSync() { + return filePlayerSync; +} + +void DivEngine::setFilePlayerSync(bool doSync) { + filePlayerSync=doSync; +} + void DivEngine::playSub(bool preserveDrift, int goalRow) { logV("playSub() called"); std::chrono::high_resolution_clock::time_point timeStart=std::chrono::high_resolution_clock::now(); @@ -2008,6 +2016,12 @@ bool DivEngine::play() { output->midiOut->send(TAMidiMessage(TA_MIDI_MACHINE_PLAY,0,0)); } bool didItPlay=playing; + if (didItPlay) { + if (curFilePlayer && filePlayerSync) { + curFilePlayer->setPosSeconds(totalSeconds,totalTicks); + curFilePlayer->play(); + } + } BUSY_END; return didItPlay; } @@ -2024,6 +2038,12 @@ bool DivEngine::playToRow(int row) { keyHit[i]=false; } bool didItPlay=playing; + if (didItPlay) { + if (curFilePlayer && filePlayerSync) { + curFilePlayer->setPosSeconds(totalSeconds,totalTicks); + curFilePlayer->play(); + } + } BUSY_END; return didItPlay; } @@ -2079,6 +2099,10 @@ void DivEngine::stop() { } } + if (curFilePlayer && filePlayerSync) { + curFilePlayer->stop(); + } + // reset all chan oscs for (int i=0; igetOscBuffer(dispatchChanOfChan[i]); @@ -3646,6 +3670,11 @@ void DivEngine::setOrder(unsigned char order) { prevOrder=curOrder; if (playing && !freelance) { playSub(false); + + if (curFilePlayer && filePlayerSync) { + curFilePlayer->setPosSeconds(totalSeconds,totalTicks); + curFilePlayer->play(); + } } BUSY_END; } diff --git a/src/engine/engine.h b/src/engine/engine.h index 18dd4f822..07f07f10e 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -601,6 +601,9 @@ class DivEngine { float* filePlayerBuf[DIV_MAX_OUTPUTS]; size_t filePlayerBufLen; DivFilePlayer* curFilePlayer; + bool filePlayerSync; + ssize_t filePlayerCueSeconds; + unsigned int filePlayerCueMillis; size_t totalProcessed; @@ -754,6 +757,9 @@ class DivEngine { // get the audio file player. DivFilePlayer* getFilePlayer(); + // get whether the player is synchronized with song playback. + bool getFilePlayerSync(); + void setFilePlayerSync(bool doSync); // save as .dmf. SafeWriter* saveDMF(unsigned char version); @@ -1565,6 +1571,9 @@ class DivEngine { previewVol(1.0f), filePlayerBufLen(0), curFilePlayer(NULL), + filePlayerSync(true), + filePlayerCueSeconds(0), + filePlayerCueMillis(0), totalProcessed(0), renderPoolThreads(0), renderPool(NULL), diff --git a/src/engine/filePlayer.cpp b/src/engine/filePlayer.cpp index f27ba5705..c101908db 100644 --- a/src/engine/filePlayer.cpp +++ b/src/engine/filePlayer.cpp @@ -283,6 +283,17 @@ ssize_t DivFilePlayer::getPos() { ssize_t DivFilePlayer::setPos(ssize_t newPos, unsigned int offset) { playPos=newPos; + rateAccum=0; + wantBlock=playPos; + return playPos; +} + +ssize_t DivFilePlayer::setPosSeconds(ssize_t seconds, unsigned int micros, unsigned int offset) { + if (sf==NULL) return 0; + double microsD=(double)si.samplerate*((double)micros/1000000.0); + playPos=seconds*si.samplerate+(int)microsD; + rateAccum=0; + wantBlock=playPos; return playPos; } diff --git a/src/engine/filePlayer.h b/src/engine/filePlayer.h index d0d57be74..61648264f 100644 --- a/src/engine/filePlayer.h +++ b/src/engine/filePlayer.h @@ -73,6 +73,7 @@ class DivFilePlayer { void mix(float** buf, int chans, unsigned int size); ssize_t getPos(); ssize_t setPos(ssize_t newPos, unsigned int offset=0); + ssize_t setPosSeconds(ssize_t seconds, unsigned int micros, unsigned int offset=0); bool isBlockPresent(ssize_t pos); bool setBlockPriority(ssize_t pos, bool priority); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index a3887b01a..c8bb9df27 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -3246,7 +3246,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi } filePlayerBufLen=size; } - if (curFilePlayer!=NULL) { + if (curFilePlayer!=NULL && !exporting) { curFilePlayer->mix(filePlayerBuf,outChans,size); } else { for (int i=0; igetFilePlayer(); - size_t playPos=fp->getPos(); + bool playPosNegative=false; + ssize_t playPos=fp->getPos(); + if (playPos<0) { + playPos=-playPos; + playPosNegative=true; + } size_t minPos=0; size_t maxPos=fp->getFileInfo().frames; int fileRate=fp->getFileInfo().samplerate; @@ -41,7 +46,11 @@ void FurnaceGUI::drawRefPlayer() { int posMinutes=((playPos/fileRate)/60)%60; int posSeconds=(playPos/fileRate)%60; int posMillis=(1000*(playPos%fileRate))/fileRate; - ImGui::Text("%d:%02d:%02d.%03d",posHours,posMinutes,posSeconds,posMillis); + if (playPosNegative) { + ImGui::Text("-%d:%02d:%02d.%03d",posHours,posMinutes,posSeconds,posMillis); + } else { + ImGui::Text("%d:%02d:%02d.%03d",posHours,posMinutes,posSeconds,posMillis); + } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::SliderScalar("##Position",ImGuiDataType_U64,&playPos,&minPos,&maxPos,"")) { @@ -69,9 +78,16 @@ void FurnaceGUI::drawRefPlayer() { } } ImGui::SameLine(); + + pushToggleColors(e->getFilePlayerSync()); + if (ImGui::Button(_("Sync"))) { + e->setFilePlayerSync(!e->getFilePlayerSync()); + } + popToggleColors(); float vol=fp->getVolume(); - if (ImGui::SliderFloat("Volume",&vol,0.0f,1.0f)) { + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::SliderFloat("##Volume",&vol,0.0f,1.0f)) { if (vol<0.0f) vol=0.0f; if (vol>1.0f) vol=1.0f; fp->setVolume(vol);