ref: 8d634e5bebdcb565e7e253b7897c960e81ef5470
parent: 7d3ab1309bc5e65b76ea937dad18a76337d72e7b
author: Olav Sørensen <olav.sorensen@live.no>
date: Thu Apr 29 19:00:36 EDT 2021
Code cleanup and render length fix for MOD2WAV
--- a/src/pt2_replayer.c
+++ b/src/pt2_replayer.c
@@ -22,7 +22,7 @@
#include "pt2_scopes.h"
#include "pt2_sync.h"
-static bool posJumpAssert, pBreakFlag, updateUIPositions, modHasBeenPlayed;
+static bool posJumpAssert, pBreakFlag, modRenderDone;
static int8_t pBreakPosition, oldRow, modPattern;
static uint8_t pattDelTime, lowMask = 0xFF, pattDelTime2;
static int16_t modOrder, oldPattern, oldOrder;
@@ -909,8 +909,38 @@
}
}
+static bool firstNextPos = true;
+
+static void updateUIPositions(void)
+{
+ // don't update UI under MOD2WAV/PAT2SMP rendering
+ if (editor.isWAVRendering || editor.isSMPRendering)
+ return;
+
+ song->currRow = song->row;
+ song->currOrder = modOrder;
+ song->currPattern = modPattern;
+
+ uint16_t *currPatPtr = &song->header.order[modOrder];
+ editor.currPatternDisp = currPatPtr;
+ editor.currPosEdPattDisp = currPatPtr;
+ editor.currPatternDisp = currPatPtr;
+ editor.currPosEdPattDisp = currPatPtr;
+
+ ui.updateSongPos = true;
+ ui.updateSongPattern = true;
+ ui.updateCurrPattText = true;
+ ui.updatePatternData = true;
+
+ if (ui.posEdScreenShown)
+ ui.updatePosEd = true;
+}
+
static void nextPosition(void)
{
+ if (editor.isSMPRendering)
+ modRenderDone = true;
+
song->row = pBreakPosition;
pBreakPosition = 0;
posJumpAssert = false;
@@ -925,9 +955,7 @@
editor.stepPlayEnabled = false;
editor.stepPlayBackwards = false;
- if (!editor.isWAVRendering && !editor.isSMPRendering)
- song->currRow = song->row;
-
+ song->currRow = song->row;
return;
}
@@ -935,7 +963,6 @@
if (modOrder >= song->header.numOrders)
{
modOrder = 0;
- modHasBeenPlayed = true;
if (config.compoMode) // stop song for music competitions playing
{
@@ -942,89 +969,95 @@
doStopIt(true);
turnOffVoices();
- song->currOrder = 0;
- song->currRow = song->row = 0;
- song->currPattern = modPattern = (int8_t)song->header.order[0];
+ modOrder = 0;
+ modPattern = (int8_t)song->header.order[modOrder];
+ song->row = 0;
- editor.currPatternDisp = &song->currPattern;
- editor.currPosEdPattDisp = &song->currPattern;
- editor.currPatternDisp = &song->currPattern;
- editor.currPosEdPattDisp = &song->currPattern;
-
- if (ui.posEdScreenShown)
- ui.updatePosEd = true;
-
- ui.updateSongPos = true;
- ui.updateSongPattern = true;
- ui.updateCurrPattText = true;
+ updateUIPositions();
}
+
+ if (editor.isWAVRendering)
+ modRenderDone = true;
}
modPattern = (int8_t)song->header.order[modOrder];
if (modPattern > MAX_PATTERNS-1)
modPattern = MAX_PATTERNS-1;
-
- updateUIPositions = true;
}
+
+ firstNextPos = false;
}
-bool intMusic(void)
+static void increasePlaybackTimer(void)
{
- uint8_t i;
- uint16_t *patt;
- moduleChannel_t *c;
+ // the timer is not counting in "play pattern" mode
+ if (editor.playMode != PLAY_MODE_PATTERN && modBPM >= 32 && modBPM <= 255)
+ editor.musicTime64 += musicTimeTab64[modBPM-32];
+}
- // Quirk: CIA uses newly set timer values on the next interrupt, so handle BPM change now (ciaSetBPM was set on previous interrupt)
- if (ciaSetBPM != -1)
- {
- modSetTempo(ciaSetBPM, false);
- ciaSetBPM = -1;
- }
+static void setCurrRowToVisited(void) // for MOD2WAV
+{
+ if (editor.isWAVRendering)
+ editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row] = true;
+}
- if (editor.playMode != PLAY_MODE_PATTERN && modBPM >= 32 && modBPM <= 255)
- editor.musicTime64 += musicTimeTab64[modBPM-32]; // for playback counter (don't increase in "play/rec pattern" mode)
+static bool renderEndCheck(void) // for MOD2WAV/PAT2SMP
+{
+ if (!editor.isWAVRendering && !editor.isSMPRendering)
+ return true; // we're not doing MOD2WAV/PAT2SMP
- if (updateUIPositions)
+ bool noPatternDelay = pattDelTime2 == 0;
+ if (noPatternDelay && song->tick == song->speed-1)
{
- updateUIPositions = false;
-
- if (!editor.isWAVRendering && !editor.isSMPRendering)
+ if (editor.isSMPRendering)
{
- if (editor.playMode != PLAY_MODE_PATTERN)
- {
- song->currOrder = modOrder;
- song->currPattern = modPattern;
+ if (modRenderDone)
+ return false; // we're done rendering
+ }
+
+ if (editor.isWAVRendering)
+ {
+ bool rowVisited = editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row];
+ if (rowVisited || modRenderDone)
+ return false; // we're done rendering
+ }
+ }
- patt = &song->header.order[modOrder];
- editor.currPatternDisp = patt;
- editor.currPosEdPattDisp = patt;
- editor.currPatternDisp = patt;
- editor.currPosEdPattDisp = patt;
+ return true;
+}
- if (ui.posEdScreenShown)
- ui.updatePosEd = true;
-
- ui.updateSongPos = true;
- ui.updateSongPattern = true;
- ui.updateCurrPattText = true;
- }
- }
+bool intMusic(void) // replayer ticker
+{
+ // quirk: CIA BPM changes are delayed by one tick in PT, so handle previous tick's BPM change now
+ if (ciaSetBPM != -1)
+ {
+ const int32_t newBPM = ciaSetBPM;
+ modSetTempo(newBPM, false);
+ ciaSetBPM = -1;
}
- if (editor.isWAVRendering && song->tick == 0)
- editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row] = true;
+ increasePlaybackTimer();
if (!editor.stepPlayEnabled)
song->tick++;
- if ((uint32_t)song->tick >= (uint32_t)song->speed || editor.stepPlayEnabled)
+ bool readNewNote = false;
+ if ((unsigned)song->tick >= (unsigned)song->speed)
{
song->tick = 0;
+ readNewNote = true;
+ }
- if (pattDelTime2 == 0)
+ if (readNewNote || editor.stepPlayEnabled) // tick 0
+ {
+ if (pattDelTime2 == 0) // no pattern delay, time to read note data
{
- c = song->channels;
- for (i = 0; i < AMIGA_VOICES; i++, c++)
+ setCurrRowToVisited(); // for MOD2WAV/PAT2SMP
+ updateUIPositions(); // update current song positions in UI
+
+ // read note data and trigger voices
+ moduleChannel_t *c = song->channels;
+ for (int32_t i = 0; i < AMIGA_VOICES; i++, c++)
{
playVoice(c);
paulaSetVolume(i, c->n_volume);
@@ -1034,23 +1067,18 @@
paulaSetLength(i, c->n_replen);
}
}
- else
+ else // pattern delay is on-going
{
- c = song->channels;
- for (i = 0; i < AMIGA_VOICES; i++, c++)
+ moduleChannel_t *c = song->channels;
+ for (int32_t i = 0; i < AMIGA_VOICES; i++, c++)
checkEffects(c);
}
- if (!editor.isWAVRendering && !editor.isSMPRendering)
- {
- song->currRow = song->row;
- ui.updatePatternData = true;
- }
-
+ // increase row
if (!editor.stepPlayBackwards)
{
song->row++;
- song->rowsCounter++;
+ song->rowsCounter++; // for MOD2WAV's progress bar
}
if (pattDelTime > 0)
@@ -1059,10 +1087,15 @@
pattDelTime = 0;
}
+ // undo row increase if pattern delay is on-going
if (pattDelTime2 > 0)
{
- if (--pattDelTime2 > 0)
+ pattDelTime2--;
+ if (pattDelTime2 > 0)
+ {
song->row--;
+ song->rowsCounter--; // for MOD2WAV's progress bar
+ }
}
if (pBreakFlag)
@@ -1072,38 +1105,30 @@
pBreakFlag = false;
}
- if (editor.blockMarkFlag)
- ui.updateStatusText = true;
-
+ // step-play handling
if (editor.stepPlayEnabled)
{
doStopIt(true);
song->currRow = song->row & 0x3F;
- ui.updatePatternData = true;
-
editor.stepPlayEnabled = false;
editor.stepPlayBackwards = false;
- ui.updatePatternData = true;
+ ui.updatePatternData = true;
return true;
}
if (song->row >= MOD_ROWS || posJumpAssert)
- {
- if (editor.isSMPRendering)
- modHasBeenPlayed = true;
-
nextPosition();
- }
- if (editor.isWAVRendering && !pattDelTime2 && editor.rowVisitTable[(modOrder * MOD_ROWS) + song->row])
- modHasBeenPlayed = true;
+ // for pattern block mark feature
+ if (editor.blockMarkFlag)
+ ui.updateStatusText = true;
}
- else
+ else // tick > 0 (handle effects)
{
- c = song->channels;
- for (i = 0; i < AMIGA_VOICES; i++, c++)
+ moduleChannel_t *c = song->channels;
+ for (int32_t i = 0; i < AMIGA_VOICES; i++, c++)
checkEffects(c);
if (posJumpAssert)
@@ -1110,13 +1135,7 @@
nextPosition();
}
- if ((editor.isSMPRendering || editor.isWAVRendering) && modHasBeenPlayed && song->tick == song->speed-1)
- {
- modHasBeenPlayed = false;
- return false;
- }
-
- return true;
+ return renderEndCheck(); // MOD2WAV/PAT2SMP listens to the return value (true = not done yet)
}
void modSetPattern(uint8_t pattern)
@@ -1179,7 +1198,7 @@
void modSetTempo(int32_t bpm, bool doLockAudio)
{
- if (bpm < 32)
+ if (bpm < 32 || bpm > 255)
return;
const bool audioWasntLocked = !audio.locked;
@@ -1195,20 +1214,20 @@
bpm -= 32; // 32..255 -> 0..223
- double dSamplesPerTick;
+ int64_t samplesPerTick64;
if (editor.isSMPRendering)
- dSamplesPerTick = editor.pat2SmpHQ ? audio.bpmTable28kHz[bpm] : audio.bpmTable22kHz[bpm];
+ samplesPerTick64 = editor.pat2SmpHQ ? audio.bpmTable28kHz[bpm] : audio.bpmTable22kHz[bpm];
else if (editor.isWAVRendering)
- dSamplesPerTick = audio.bpmTableMod2Wav[bpm];
+ samplesPerTick64 = audio.bpmTableMod2Wav[bpm];
else
- dSamplesPerTick = audio.bpmTable[bpm];
+ samplesPerTick64 = audio.bpmTable[bpm];
- audio.dSamplesPerTick = dSamplesPerTick;
+ audio.samplesPerTick64 = samplesPerTick64;
// calculate tick time length for audio/video sync timestamp
const uint64_t tickTimeLen64 = audio.tickLengthTable[bpm];
const uint32_t tickTimeLen = tickTimeLen64 >> 32;
- const uint32_t tickTimeLenFrac = tickTimeLen64 & 0xFFFFFFFF;
+ const uint32_t tickTimeLenFrac = (uint32_t)tickTimeLen64;
setSyncTickTimeLen(tickTimeLen, tickTimeLenFrac);
@@ -1238,7 +1257,7 @@
pattDelTime2 = 0;
pBreakPosition = 0;
posJumpAssert = false;
- modHasBeenPlayed = true;
+ modRenderDone = true;
}
void playPattern(int8_t startRow)
@@ -1246,7 +1265,7 @@
if (!editor.stepPlayEnabled)
pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
- audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
+ audio.tickSampleCounter64 = 0; // zero tick sample counter so that it will instantly initiate a tick
song->currRow = song->row = startRow & 0x3F;
song->tick = song->speed;
ciaSetBPM = -1;
@@ -1291,7 +1310,7 @@
doStopIt(false);
turnOffVoices();
- audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
+ audio.tickSampleCounter64 = 0; // zero tick sample counter so that it will instantly initiate a tick
ciaSetBPM = -1;
if (row != -1)
@@ -1343,8 +1362,8 @@
editor.playMode = oldPlayMode;
editor.currMode = oldMode;
- song->tick = song->speed;
- modHasBeenPlayed = false;
+ song->tick = song->speed-1;
+ modRenderDone = false;
editor.songPlaying = true;
editor.didQuantize = false;
@@ -1569,6 +1588,6 @@
doStopIt(true);
song->tick = 0;
- modHasBeenPlayed = false;
+ modRenderDone = false;
audio.forceMixerOff = false;
}