earliest implementation of sync

does not loop correctly
This commit is contained in:
tildearrow 2025-10-27 19:34:21 -05:00
parent 7a7a871198
commit 394c6c35aa
6 changed files with 70 additions and 4 deletions

View file

@ -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; i<chans; i++) {
DivDispatchOscBuffer* buf=disCont[dispatchOfChan[i]].dispatch->getOscBuffer(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;
}

View file

@ -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),

View file

@ -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;
}

View file

@ -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);

View file

@ -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; i<DIV_MAX_OUTPUTS; i++) {

View file

@ -32,7 +32,12 @@ void FurnaceGUI::drawRefPlayer() {
if (ImGui::Begin("Music Player",&refPlayerOpen,globalWinFlags,_("Music Player"))) {
DivFilePlayer* fp=e->getFilePlayer();
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);