ZSM: include song tuning in export

This commit is contained in:
MooingLemur 2023-08-11 01:02:18 -07:00
parent a59b5753bb
commit 8006e40e26
4 changed files with 30 additions and 11 deletions

View file

@ -116,6 +116,10 @@ void DivZSM::writeYM(unsigned char a, unsigned char v) {
}
}
void DivZSM::writeSync(unsigned char a, unsigned char v) {
return syncCache.push_back(DivRegWrite(a,v));
}
void DivZSM::writePSG(unsigned char a, unsigned char v) {
// TODO: suppress writes to PSG voice that is not audible (volume=0)
// ^ Let's leave these alone, ZSMKit has a feature that can benefit
@ -126,7 +130,7 @@ void DivZSM::writePSG(unsigned char a, unsigned char v) {
} else if (a==68) {
// Sync event
numWrites++;
return syncCache.push_back(v);
return writeSync(0x00,v);
} else if (a>=64) {
return writePCM(a-64,v);
}
@ -390,15 +394,18 @@ void DivZSM::flushWrites() {
}
}
n=0;
while (n<(long)syncCache.size()) { // we have one or more sync events to write
int writes=syncCache.size()-n;
w->writeC(ZSM_EXT);
if (writes>ZSM_SYNC_MAX_WRITES) writes=ZSM_SYNC_MAX_WRITES;
w->writeC(ZSM_EXT_SYNC|(writes<<1));
for (; writes>0; writes--) {
w->writeC(0x00); // 0x00 = Arbitrary sync message
w->writeC(syncCache[n++]);
for (DivRegWrite& write: syncCache) {
if (n%ZSM_SYNC_MAX_WRITES==0) {
w->writeC(ZSM_EXT);
if (syncCache.size()-n>ZSM_SYNC_MAX_WRITES) {
w->writeC((unsigned char)ZSM_EXT_SYNC|(ZSM_SYNC_MAX_WRITES<<1));
} else {
w->writeC((unsigned char)ZSM_EXT_SYNC|((syncCache.size()-n)<<1));
}
}
n++;
w->writeC(write.addr);
w->writeC(write.val);
}
syncCache.clear();
numWrites=0;

View file

@ -63,7 +63,7 @@ class DivZSM {
std::vector<unsigned char> pcmData;
std::vector<unsigned char> pcmCache;
std::vector<S_pcmInst> pcmInsts;
std::vector<unsigned char> syncCache;
std::vector<DivRegWrite> syncCache;
int loopOffset;
int numWrites;
int ticks;
@ -78,6 +78,7 @@ class DivZSM {
void writeYM(unsigned char a, unsigned char v);
void writePSG(unsigned char a, unsigned char v);
void writePCM(unsigned char a, unsigned char v);
void writeSync(unsigned char a, unsigned char v);
void tick(int numticks = 1);
void setLoopPoint();
SafeWriter* finish();

View file

@ -107,6 +107,16 @@ SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop) {
// TODO: incorporate the Furnace meta-command for init data and filter
// out writes to otherwise-unused channels.
}
// Indicate the song's tuning as a sync meta-event
// specified in terms of how many 1/256th semitones
// the song is offset from standard A-440 tuning.
// This is mainly to benefit visualizations in players
// for non-standard tunings so that they can avoid
// displaying the entire song held in pitch bend.
// Tunings offsets that exceed a half semitone
// will simply be represented in a different key
signed char tuningoffset=(signed char)round(3072*(log(song.tuning/440.0)/log(2)));
zsm.writeSync(0x01,tuningoffset);
while (!done) {
if (loopPos==-1) {