file player cue point and loop tracking
no loop trail yet
This commit is contained in:
parent
3c106f7861
commit
319da2d391
7 changed files with 213 additions and 30 deletions
|
|
@ -1662,6 +1662,16 @@ void DivEngine::setFilePlayerSync(bool doSync) {
|
|||
filePlayerSync=doSync;
|
||||
}
|
||||
|
||||
void DivEngine::getFilePlayerCue(int& seconds, int& micros) {
|
||||
seconds=filePlayerCueSeconds;
|
||||
micros=filePlayerCueMicros;
|
||||
}
|
||||
|
||||
void DivEngine::setFilePlayerCue(int seconds, int micros) {
|
||||
filePlayerCueSeconds=seconds;
|
||||
filePlayerCueMicros=micros;
|
||||
}
|
||||
|
||||
void DivEngine::syncFilePlayer() {
|
||||
if (curFilePlayer==NULL) return;
|
||||
int finalSeconds=totalSeconds+filePlayerCueSeconds;
|
||||
|
|
|
|||
|
|
@ -604,6 +604,8 @@ class DivEngine {
|
|||
bool filePlayerSync;
|
||||
ssize_t filePlayerCueSeconds;
|
||||
unsigned int filePlayerCueMicros;
|
||||
int filePlayerLoopTrail;
|
||||
int curFilePlayerTrail;
|
||||
|
||||
size_t totalProcessed;
|
||||
|
||||
|
|
@ -630,8 +632,6 @@ class DivEngine {
|
|||
void runMidiTime(int totalCycles=1);
|
||||
bool shallSwitchCores();
|
||||
|
||||
void syncFilePlayer();
|
||||
|
||||
void testFunction();
|
||||
|
||||
bool loadDMF(unsigned char* file, size_t len);
|
||||
|
|
@ -762,6 +762,11 @@ class DivEngine {
|
|||
// get whether the player is synchronized with song playback.
|
||||
bool getFilePlayerSync();
|
||||
void setFilePlayerSync(bool doSync);
|
||||
// get/set file player cue position.
|
||||
void getFilePlayerCue(int& seconds, int& micros);
|
||||
void setFilePlayerCue(int seconds, int micros);
|
||||
// UNSAFE - sync file player to current playback position.
|
||||
void syncFilePlayer();
|
||||
|
||||
// save as .dmf.
|
||||
SafeWriter* saveDMF(unsigned char version);
|
||||
|
|
@ -1573,6 +1578,8 @@ class DivEngine {
|
|||
filePlayerSync(false),
|
||||
filePlayerCueSeconds(0),
|
||||
filePlayerCueMicros(0),
|
||||
filePlayerLoopTrail(0),
|
||||
curFilePlayerTrail(0),
|
||||
totalProcessed(0),
|
||||
renderPoolThreads(0),
|
||||
renderPool(NULL),
|
||||
|
|
|
|||
|
|
@ -208,6 +208,19 @@ void DivFilePlayer::mix(float** buf, int chans, unsigned int size) {
|
|||
}
|
||||
|
||||
for (unsigned int i=0; i<size; i++) {
|
||||
// acknowledge pending events
|
||||
if (pendingPosOffset==i) {
|
||||
pendingPosOffset=UINT_MAX;
|
||||
playPos=pendingPos;
|
||||
rateAccum=0;
|
||||
}
|
||||
if (pendingPlayOffset==i) {
|
||||
playing=true;
|
||||
}
|
||||
if (pendingStopOffset==i) {
|
||||
playing=false;
|
||||
}
|
||||
|
||||
ssize_t blockIndex=playPos>>DIV_FPCACHE_BLOCK_SHIFT;
|
||||
if (blockIndex!=lastWantBlock) {
|
||||
wantBlock=playPos;
|
||||
|
|
@ -285,22 +298,49 @@ ssize_t DivFilePlayer::getPos() {
|
|||
return playPos;
|
||||
}
|
||||
|
||||
void DivFilePlayer::getPosSeconds(ssize_t& seconds, unsigned int& micros) {
|
||||
if (sf==NULL) {
|
||||
seconds=0;
|
||||
micros=0;
|
||||
return;
|
||||
}
|
||||
double microsD=playPos%si.samplerate;
|
||||
seconds=playPos/si.samplerate;
|
||||
micros=(int)((1000000.0*microsD)/(double)si.samplerate);
|
||||
}
|
||||
|
||||
ssize_t DivFilePlayer::setPos(ssize_t newPos, unsigned int offset) {
|
||||
playPos=newPos;
|
||||
rateAccum=0;
|
||||
wantBlock=playPos;
|
||||
logD("DivFilePlayer: setPos(%" PRIi64 ")",newPos);
|
||||
return playPos;
|
||||
if (offset==UINT_MAX) {
|
||||
playPos=newPos;
|
||||
rateAccum=0;
|
||||
wantBlock=playPos;
|
||||
logD("DivFilePlayer: setPos(%" PRIi64 ")",newPos);
|
||||
return playPos;
|
||||
} else {
|
||||
pendingPosOffset=offset;
|
||||
pendingPos=newPos;
|
||||
wantBlock=playPos;
|
||||
logD("DivFilePlayer: offset %u setPos(%" PRIi64 ")",offset,newPos);
|
||||
return newPos;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
logD("DivFilePlayer: setPosSeconds(%" PRIi64 ".%06d)",seconds,micros);
|
||||
return playPos;
|
||||
if (offset==UINT_MAX) {
|
||||
playPos=seconds*si.samplerate+(int)microsD;
|
||||
rateAccum=0;
|
||||
wantBlock=playPos;
|
||||
logD("DivFilePlayer: setPosSeconds(%" PRIi64 ".%06d)",seconds,micros);
|
||||
return playPos;
|
||||
} else {
|
||||
pendingPosOffset=offset;
|
||||
pendingPos=seconds*si.samplerate+(int)microsD;
|
||||
wantBlock=pendingPos;
|
||||
logD("DivFilePlayer: offset %u setPosSeconds(%" PRIi64 ".%06d)",offset,seconds,micros);
|
||||
return pendingPos;
|
||||
}
|
||||
}
|
||||
|
||||
size_t DivFilePlayer::getMemUsage() {
|
||||
|
|
@ -336,13 +376,23 @@ bool DivFilePlayer::isPlaying() {
|
|||
}
|
||||
|
||||
void DivFilePlayer::play(unsigned int offset) {
|
||||
logV("DivFilePlayer: playing");
|
||||
playing=true;
|
||||
if (offset!=UINT_MAX) {
|
||||
pendingPlayOffset=offset;
|
||||
logV("DivFilePlayer: playing (offset: %u)",offset);
|
||||
} else {
|
||||
playing=true;
|
||||
logV("DivFilePlayer: playing");
|
||||
}
|
||||
}
|
||||
|
||||
void DivFilePlayer::stop(unsigned int offset) {
|
||||
logV("DivFilePlayer: stopping");
|
||||
playing=false;
|
||||
if (offset!=UINT_MAX) {
|
||||
pendingStopOffset=offset;
|
||||
logV("DivFilePlayer: stopping (offset: %u)",offset);
|
||||
} else {
|
||||
playing=false;
|
||||
logV("DivFilePlayer: stopping");
|
||||
}
|
||||
}
|
||||
|
||||
bool DivFilePlayer::closeFile() {
|
||||
|
|
@ -492,6 +542,10 @@ DivFilePlayer::DivFilePlayer():
|
|||
quitThread(false),
|
||||
threadHasQuit(false),
|
||||
isActive(false),
|
||||
pendingPos(0),
|
||||
pendingPosOffset(UINT_MAX),
|
||||
pendingPlayOffset(UINT_MAX),
|
||||
pendingStopOffset(UINT_MAX),
|
||||
cacheThread(NULL) {
|
||||
memset(&si,0,sizeof(SF_INFO));
|
||||
sincTable=DivFilterTables::getSincTable8();
|
||||
|
|
|
|||
|
|
@ -57,6 +57,11 @@ class DivFilePlayer {
|
|||
bool threadHasQuit;
|
||||
bool isActive;
|
||||
|
||||
ssize_t pendingPos;
|
||||
unsigned int pendingPosOffset;
|
||||
unsigned int pendingPlayOffset;
|
||||
unsigned int pendingStopOffset;
|
||||
|
||||
std::thread* cacheThread;
|
||||
std::mutex cacheMutex;
|
||||
std::mutex cacheThreadLock;
|
||||
|
|
@ -73,15 +78,16 @@ 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);
|
||||
void getPosSeconds(ssize_t& seconds, unsigned int& micros);
|
||||
ssize_t setPos(ssize_t newPos, unsigned int offset=UINT_MAX);
|
||||
ssize_t setPosSeconds(ssize_t seconds, unsigned int micros, unsigned int offset=UINT_MAX);
|
||||
|
||||
bool isBlockPresent(ssize_t pos);
|
||||
bool setBlockPriority(ssize_t pos, bool priority);
|
||||
bool isLoaded();
|
||||
bool isPlaying();
|
||||
void play(unsigned int offset=0);
|
||||
void stop(unsigned int offset=0);
|
||||
void play(unsigned int offset=UINT_MAX);
|
||||
void stop(unsigned int offset=UINT_MAX);
|
||||
bool closeFile();
|
||||
bool loadFile(const char* path);
|
||||
|
||||
|
|
|
|||
|
|
@ -3106,6 +3106,22 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
// used by audio export to determine how many samples to write (otherwise it'll add silence at the end)
|
||||
lastLoopPos=size-runLeftG;
|
||||
logD("last loop pos: %d for a size of %d and runLeftG of %d",lastLoopPos,size,runLeftG);
|
||||
// if file player is synchronized then set its position to that of the loop row
|
||||
if (curFilePlayer && filePlayerSync) {
|
||||
if (curFilePlayer->isPlaying()) {
|
||||
DivSongTimestamps::Timestamp rowTS=curSubSong->ts.loopStartTime;
|
||||
int finalSeconds=rowTS.seconds+filePlayerCueSeconds;
|
||||
int finalMicros=rowTS.micros+filePlayerCueMicros;
|
||||
|
||||
while (finalMicros>=1000000) {
|
||||
finalMicros-=1000000;
|
||||
finalSeconds++;
|
||||
}
|
||||
|
||||
curFilePlayer->setPosSeconds(finalSeconds,finalMicros,lastLoopPos);
|
||||
}
|
||||
}
|
||||
// increase total loop count
|
||||
totalLoops++;
|
||||
// stop playing once we hit a specific number of loops (set during audio export)
|
||||
if (remainingLoops>0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue