ref: 5d1114967dc5dee345cc8823e3e53df2ff15a1c5
parent: 2b8c2daab5c67ce90aff2a65f330bd4511256428
author: Olav Sørensen <olav.sorensen@live.no>
date: Tue Jun 23 15:46:25 EDT 2020
Pushed v1.20 code - Song BPM is now more accurate (it used to be slightly off for some BPMs). Please note that every Amiga's system clock is off by a very small fraction. This means that the true PT BPM (based on CIA) differs very slightly from machine to machine, so the PT2 clone's BPM will not precisely match a real Amiga. - Added a delay when using left/right/delete/backspace keys in text edit mode. This makes it harder to do accidents! - Bugfix: MOD2WAV didn't stop rendering even if a F00 pattern command was triggered. - Bugfix: PAT2SMP would sometimes not render the very last song tick
--- a/src/pt2_audio.c
+++ b/src/pt2_audio.c
@@ -48,7 +48,7 @@
static bool amigaPanFlag;
static uint16_t ch1Pan, ch2Pan, ch3Pan, ch4Pan;
static int32_t oldPeriod = -1, randSeed = INITIAL_DITHER_SEED;
-static uint32_t sampleCounter, audLatencyPerfValInt, audLatencyPerfValFrac;
+static uint32_t audLatencyPerfValInt, audLatencyPerfValFrac;
static uint64_t tickTime64, tickTime64Frac;
static double *dMixBufferL, *dMixBufferR, *dMixBufferLUnaligned, *dMixBufferRUnaligned, dOldVoiceDelta, dOldVoiceDeltaMul;
static double dPrngStateL, dPrngStateR;
@@ -62,7 +62,6 @@
// globalized
audio_t audio;
-uint32_t samplesPerTick;
paulaVoice_t paula[AMIGA_VOICES];
bool intMusic(void); // defined in pt_modplayer.c
@@ -95,26 +94,16 @@
tickTimeLenFrac = timeLenFrac;
}
-static uint16_t bpm2SmpsPerTick(int32_t bpm, double dAudioFreq)
-{
- if (bpm == 0)
- return 0;
-
- const int32_t ciaVal = (int32_t)(1773447 / bpm); // yes, PT truncates here
- const double dCiaHz = (double)CIA_PAL_CLK / ciaVal;
-
- int32_t smpsPerTick = (int32_t)((dAudioFreq / dCiaHz) + 0.5); // rounded
- return (uint16_t)smpsPerTick;
-}
-
static void generateBpmTables(void)
{
for (int32_t i = 32; i <= 255; i++)
{
- audio.bpmTab[i-32] = bpm2SmpsPerTick(i, audio.outputRate);
- audio.bpmTab28kHz[i-32] = bpm2SmpsPerTick(i, PAT2SMP_HI_FREQ); // PAT2SMP hi quality
- audio.bpmTab22kHz[i-32] = bpm2SmpsPerTick(i, PAT2SMP_LO_FREQ); // PAT2SMP low quality
- audio.bpmTabMod2Wav[i-32] = bpm2SmpsPerTick(i, MOD2WAV_FREQ); // MOD2WAV
+ const double dBpmHz = i / 2.5;
+
+ audio.bpmTab[i-32] = audio.outputRate / dBpmHz;
+ audio.bpmTab28kHz[i-32] = PAT2SMP_HI_FREQ / dBpmHz; // PAT2SMP hi quality
+ audio.bpmTab22kHz[i-32] = PAT2SMP_LO_FREQ / dBpmHz; // PAT2SMP low quality
+ audio.bpmTabMod2Wav[i-32] = MOD2WAV_FREQ / dBpmHz; // MOD2WAV
}
}
@@ -1065,9 +1054,6 @@
static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len)
{
- int16_t *streamOut;
- uint32_t samplesLeft;
-
if (audio.forceMixerOff) // during MOD2WAV
{
memset(stream, 0, len);
@@ -1074,12 +1060,12 @@
return;
}
- streamOut = (int16_t *)stream;
+ int16_t *streamOut = (int16_t *)stream;
- samplesLeft = len >> 2;
+ int32_t samplesLeft = len >> 2;
while (samplesLeft > 0)
{
- if (sampleCounter == 0)
+ if (audio.dTickSampleCounter <= 0.0)
{
// new replayer tick
@@ -1089,18 +1075,20 @@
fillVisualsSyncBuffer();
}
- sampleCounter = samplesPerTick;
+ audio.dTickSampleCounter += audio.dSamplesPerTick;
}
- uint32_t samplesTodo = sampleCounter;
- if (samplesTodo > samplesLeft)
- samplesTodo = samplesLeft;
+ const int32_t remainingTick = (int32_t)ceil(audio.dTickSampleCounter);
- outputAudio(streamOut, samplesTodo);
- streamOut += samplesTodo << 1;
+ int32_t samplesToMix = samplesLeft;
+ if (samplesToMix > remainingTick)
+ samplesToMix = remainingTick;
- samplesLeft -= samplesTodo;
- sampleCounter -= samplesTodo;
+ outputAudio(streamOut, samplesToMix);
+ streamOut += samplesToMix << 1;
+
+ samplesLeft -= samplesToMix;
+ audio.dTickSampleCounter -= samplesToMix;
}
(void)userdata;
@@ -1254,11 +1242,11 @@
** won't overflow.
*/
- uint32_t maxSamplesToMix;
+ int32_t maxSamplesToMix;
if (MOD2WAV_FREQ > audio.outputRate)
- maxSamplesToMix = audio.bpmTabMod2Wav[32-32]; // BPM 32
+ maxSamplesToMix = (int32_t)ceil(audio.bpmTabMod2Wav[32-32]); // BPM 32
else
- maxSamplesToMix = audio.bpmTab[32-32]; // BPM 32
+ maxSamplesToMix = (int32_t)ceil(audio.bpmTab[32-32]); // BPM 32
dMixBufferLUnaligned = (double *)MALLOC_PAD(maxSamplesToMix * sizeof (double), 256);
dMixBufferRUnaligned = (double *)MALLOC_PAD(maxSamplesToMix * sizeof (double), 256);
@@ -1278,15 +1266,17 @@
filterFlags = config.a500LowPassFilter ? FILTER_A500 : 0;
calculateFilterCoeffs();
- samplesPerTick = audio.bpmTab[125-32]; // BPM 125
- sampleCounter = 0;
+ audio.dSamplesPerTick = audio.bpmTab[125-32]; // BPM 125
+ audio.dTickSampleCounter = 0;
calcAudioLatencyVars(audio.audioBufferSize, audio.outputRate);
- for (int32_t i = 0; i < 256-32; i++)
+
+ audio.tickTimeLengthTab[0] = UINT64_MAX;
+ const double dMul = (editor.dPerfFreq / audio.outputRate) * (UINT32_MAX + 1.0);
+ for (int32_t i = 1; i < 256-32; i++)
{
// number of samples per tick -> tick length for performance counter (syncing visuals to audio)
- const double dTickTimeLenMul = (editor.dPerfFreq / audio.outputRate) * (UINT32_MAX + 1.0);
- audio.tickTimeLengthTab[i] = (uint64_t)(audio.bpmTab[i] * dTickTimeLenMul);
+ audio.tickTimeLengthTab[i] = (uint64_t)(audio.bpmTab[i] * dMul);
}
audio.resetSyncTickTimeFlag = true;
@@ -1314,16 +1304,6 @@
free(dMixBufferRUnaligned);
dMixBufferRUnaligned = NULL;
}
-}
-
-void mixerSetSamplesPerTick(uint32_t val)
-{
- samplesPerTick = val;
-}
-
-void mixerClearSampleCounter(void)
-{
- sampleCounter = 0;
}
void toggleAmigaPanMode(void)
--- a/src/pt2_audio.h
+++ b/src/pt2_audio.h
@@ -18,10 +18,12 @@
volatile bool locked, isSampling;
bool forceMixerOff;
- uint16_t bpmTab[256-32], bpmTab28kHz[256-32], bpmTab22kHz[256-32], bpmTabMod2Wav[256-32];
+ double bpmTab[256-32], bpmTab28kHz[256-32], bpmTab22kHz[256-32], bpmTabMod2Wav[256-32];
uint32_t outputRate, audioBufferSize;
double dPeriodToDeltaDiv;
+ double dSamplesPerTick, dTickSampleCounter;
+
// for audio sampling
bool rescanAudioDevicesSupported;
@@ -75,8 +77,6 @@
void mixerKillVoice(int32_t ch);
void turnOffVoices(void);
void mixerCalcVoicePans(uint8_t stereoSeparation);
-void mixerSetSamplesPerTick(uint32_t val);
-void mixerClearSampleCounter(void);
void outputAudio(int16_t *target, int32_t numSamples);
extern audio_t audio; // pt2_audio.c
--- a/src/pt2_header.h
+++ b/src/pt2_header.h
@@ -14,7 +14,7 @@
#include "pt2_unicode.h"
#include "pt2_palette.h"
-#define PROG_VER_STR "1.19"
+#define PROG_VER_STR "1.20"
#ifdef _WIN32
#define DIR_DELIMITER '\\'
--- a/src/pt2_keyboard.c
+++ b/src/pt2_keyboard.c
@@ -30,6 +30,7 @@
#include "pt2_config.h"
#include "pt2_sampling.h"
+
#if defined _WIN32 && !defined _DEBUG
extern bool windowsKeyIsDown;
extern HHOOK g_hKeyboardHook;
@@ -3198,11 +3199,18 @@
{
if (ui.editTextFlag)
{
- if (keyb.repeatCounter >= 4)
+ if (keyb.delayCounter >= KEYB_REPEAT_DELAY)
{
- keyb.repeatCounter = 0;
- textCharPrevious();
+ if (keyb.repeatCounter >= 3)
+ {
+ keyb.repeatCounter = 0;
+ textCharPrevious();
+ }
}
+ else
+ {
+ keyb.delayCounter++;
+ }
}
else
{
@@ -3248,11 +3256,18 @@
{
if (ui.editTextFlag)
{
- if (keyb.repeatCounter >= 4)
+ if (keyb.delayCounter >= KEYB_REPEAT_DELAY)
{
- keyb.repeatCounter = 0;
- textCharNext();
+ if (keyb.repeatCounter >= 3)
+ {
+ keyb.repeatCounter = 0;
+ textCharNext();
+ }
}
+ else
+ {
+ keyb.delayCounter++;
+ }
}
else
{
@@ -3406,11 +3421,19 @@
if (ui.editTextFlag)
{
// only repeat backspace while editing texts
- if (keyb.repeatCounter >= 3)
+
+ if (keyb.delayCounter >= KEYB_REPEAT_DELAY)
{
- keyb.repeatCounter = 0;
- keyDownHandler(scancode, 0);
+ if (keyb.repeatCounter >= 3)
+ {
+ keyb.repeatCounter = 0;
+ keyDownHandler(scancode, 0);
+ }
}
+ else
+ {
+ keyb.delayCounter++;
+ }
}
}
break;
@@ -4202,7 +4225,7 @@
keyb.delayCounter = 0;
keyb.repeatKey = true;
- keyb.delayKey = false;
+ keyb.delayKey = true;
updateTextObject(ui.editObject);
}
--- a/src/pt2_mod2wav.c
+++ b/src/pt2_mod2wav.c
@@ -19,7 +19,6 @@
void storeTempVariables(void); // pt_modplayer.c
bool intMusic(void); // pt_modplayer.c
-extern uint32_t samplesPerTick; // pt_audio.c
static volatile bool wavRenderingDone;
static int16_t *mod2WavBuffer;
@@ -26,13 +25,12 @@
static void calcMod2WavTotalRows(void);
-static uint32_t getAudioFrame(int16_t *outStream)
+static void renderSamples(int32_t samplesPerTick, int16_t *outStream)
{
if (!intMusic())
wavRenderingDone = true;
outputAudio(outStream, samplesPerTick);
- return samplesPerTick;
}
static int32_t SDLCALL mod2WavThreadFunc(void *ptr)
@@ -50,6 +48,8 @@
uint8_t loopCounter = 8;
uint32_t totalSampleCounter = 0;
+ double dTickSamples = audio.dSamplesPerTick;
+
bool renderDone = false;
while (!renderDone)
{
@@ -59,18 +59,21 @@
int16_t *ptr16 = mod2WavBuffer;
for (uint32_t i = 0; i < TICKS_PER_RENDER_CHUNK; i++)
{
- if (!editor.isWAVRendering || wavRenderingDone || editor.abortMod2Wav)
+ if (!editor.isWAVRendering || wavRenderingDone || editor.abortMod2Wav || !editor.songPlaying)
{
renderDone = true;
break;
}
- uint32_t tickSamples = getAudioFrame(ptr16) << 1; // *2 for stereo
+ int32_t tickSamples = (int32_t)dTickSamples;
+ renderSamples(tickSamples, ptr16);
+
+ dTickSamples -= tickSamples; // keep fractional part
+ dTickSamples += audio.dSamplesPerTick;
+ tickSamples *= 2; // stereo
samplesInChunk += tickSamples;
totalSampleCounter += tickSamples;
-
- // increase buffer pointer
ptr16 += tickSamples;
if (++loopCounter >= 8)
@@ -154,7 +157,7 @@
return false;
}
- const uint32_t maxSamplesToMix = TICKS_PER_RENDER_CHUNK * audio.bpmTabMod2Wav[32-32]; // BPM 32, stereo
+ const int32_t maxSamplesToMix = (int32_t)ceil(TICKS_PER_RENDER_CHUNK * audio.bpmTabMod2Wav[32-32]); // BPM 32, stereo
mod2WavBuffer = (int16_t *)malloc(maxSamplesToMix * (2 * sizeof (int16_t)));
if (mod2WavBuffer == NULL)
--- a/src/pt2_module_loader.c
+++ b/src/pt2_module_loader.c
@@ -938,7 +938,7 @@
editor.editMoveAdd = 1;
editor.currSample = 0;
- editor.musicTime = 0;
+ editor.musicTime64 = 0;
editor.modLoaded = true;
editor.blockMarkFlag = false;
editor.sampleZero = false;
--- a/src/pt2_pat2smp.c
+++ b/src/pt2_pat2smp.c
@@ -14,7 +14,6 @@
#include "pt2_textout.h"
bool intMusic(void); // pt_modplayer.c
-extern uint32_t samplesPerTick; // pt_audio.c
void storeTempVariables(void); // pt_modplayer.c
void doPat2Smp(void)
@@ -36,8 +35,7 @@
return;
}
- int8_t oldRow = editor.songPlaying ? 0 : song->currRow;
- uint32_t oldSamplesPerTick = samplesPerTick;
+ const int8_t oldRow = editor.songPlaying ? 0 : song->currRow;
editor.isSMPRendering = true; // this must be set before restartSong()
storeTempVariables();
@@ -51,21 +49,28 @@
modSetTempo(song->currBPM, true);
editor.pat2SmpPos = 0;
+ double dTickSamples = audio.dSamplesPerTick;
+
editor.smpRenderingDone = false;
while (!editor.smpRenderingDone)
{
- if (!intMusic())
+ const int32_t tickSamples = (int32_t)dTickSamples;
+
+ const bool ended = !intMusic() || !editor.songPlaying;
+ outputAudio(NULL, tickSamples);
+
+ dTickSamples -= tickSamples; // keep fractional part
+ dTickSamples += audio.dSamplesPerTick;
+
+ if (ended)
editor.smpRenderingDone = true;
- outputAudio(NULL, samplesPerTick);
}
editor.isSMPRendering = false;
resetSong();
- // set back old row and samplesPerTick
- song->row = oldRow;
- song->currRow = song->row;
- mixerSetSamplesPerTick(oldSamplesPerTick);
+ // set back old row
+ song->currRow = song->row = oldRow;
normalize16bitSigned(editor.pat2SmpBuf, MIN(editor.pat2SmpPos, MAX_SAMPLE_LEN));
--- a/src/pt2_replayer.c
+++ b/src/pt2_replayer.c
@@ -977,8 +977,8 @@
uint16_t *patt;
moduleChannel_t *c;
- if (modBPM > 0)
- editor.musicTime += (65536 / modBPM); // for playback counter
+ if (modBPM >= 32 && modBPM <= 255)
+ editor.musicTime64 += musicTimeTab64[modBPM-32]; // for playback counter
if (updateUIPositions)
{
@@ -1181,8 +1181,6 @@
void modSetTempo(uint16_t bpm, bool doLockAudio)
{
- uint32_t smpsPerTick;
-
if (bpm < 32)
return;
@@ -1200,14 +1198,15 @@
bpm -= 32; // 32..255 -> 0..223
+ double dSamplesPerTick;
if (editor.isSMPRendering)
- smpsPerTick = editor.pat2SmpHQ ? audio.bpmTab28kHz[bpm] : audio.bpmTab22kHz[bpm];
+ dSamplesPerTick = editor.pat2SmpHQ ? audio.bpmTab28kHz[bpm] : audio.bpmTab22kHz[bpm];
else if (editor.isWAVRendering)
- smpsPerTick = audio.bpmTabMod2Wav[bpm];
+ dSamplesPerTick = audio.bpmTabMod2Wav[bpm];
else
- smpsPerTick = audio.bpmTab[bpm];
+ dSamplesPerTick = audio.bpmTab[bpm];
- mixerSetSamplesPerTick(smpsPerTick);
+ audio.dSamplesPerTick = dSamplesPerTick;
// calculate tick time length for audio/video sync timestamp
const uint64_t tickTimeLen64 = audio.tickTimeLengthTab[bpm];
@@ -1251,7 +1250,7 @@
if (!editor.stepPlayEnabled)
pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
- mixerClearSampleCounter();
+ audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
song->currRow = song->row = startRow & 0x3F;
song->tick = song->speed;
@@ -1290,9 +1289,13 @@
{
uint8_t oldPlayMode, oldMode;
+ const bool audioWasntLocked = !audio.locked;
+ if (audioWasntLocked)
+ lockAudio();
+
doStopIt(false);
turnOffVoices();
- mixerClearSampleCounter();
+ audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
if (row != -1)
{
@@ -1347,8 +1350,11 @@
modHasBeenPlayed = false;
editor.songPlaying = true;
editor.didQuantize = false;
- editor.musicTime = 0;
+ editor.musicTime64 = 0;
+ if (audioWasntLocked)
+ unlockAudio();
+
if (!editor.isSMPRendering && !editor.isWAVRendering)
{
ui.updateSongPos = true;
@@ -1381,7 +1387,7 @@
editor.f9Pos = 48;
editor.f10Pos = 63;
- editor.musicTime = 0;
+ editor.musicTime64 = 0;
editor.metroFlag = false;
editor.currSample = 0;
--- a/src/pt2_structs.h
+++ b/src/pt2_structs.h
@@ -178,7 +178,8 @@
uint16_t effectMacros[10], oldTempo, currPlayNote, vol1, vol2, lpCutOff, hpCutOff;
uint16_t smpRedoLoopStarts[MOD_SAMPLES], smpRedoLoopLengths[MOD_SAMPLES], smpRedoLengths[MOD_SAMPLES];
int32_t modulatePos, modulateOffset, markStartOfs, markEndOfs, pat2SmpPos;
- uint32_t musicTime, vblankTimeLen, vblankTimeLenFrac;
+ uint32_t vblankTimeLen, vblankTimeLenFrac;
+ uint64_t musicTime64;
double dPerfFreq, dPerfFreqMulMicro;
note_t trackBuffer[MOD_ROWS], cmdsBuffer[MOD_ROWS], blockBuffer[MOD_ROWS];
note_t patternBuffer[MOD_ROWS * AMIGA_VOICES], undoBuffer[MOD_ROWS * AMIGA_VOICES];
--- a/src/pt2_tables.c
+++ b/src/pt2_tables.c
@@ -156,6 +156,52 @@
8739,9253,24625,12851,13365
};
+/*
+** const double dBpmMs = 1000.0 / (bpm / 2.5);
+** x = (uint64_t)round((UINT32_MAX + 1.0) * dBpmMs);
+*/
+const uint64_t musicTimeTab64[256-32] =
+{
+ 0x4e20000000,0x4bc1f07c1f,0x4987878788,0x476db6db6e,0x4571c71c72,0x43914c1bad,
+ 0x41ca1af287,0x401a41a41a,0x3e80000000,0x3cf9c18f9c,0x3b86186186,0x3a23b88ee2,
+ 0x38d1745d17,0x378e38e38e,0x36590b2164,0x3531057262,0x3415555555,0x330539782a,
+ 0x3200000000,0x3105050505,0x3013b13b14,0x2f2b78c135,0x2e4bda12f7,0x2d745d1746,
+ 0x2ca4924925,0x2bdc11f704,0x2b1a7b9612,0x2a5f75270d,0x29aaaaaaab,0x28fbcda3ac,
+ 0x285294a529,0x27aebaebaf,0x2710000000,0x2676276276,0x25e0f83e10,0x25503d2263,
+ 0x24c3c3c3c4,0x243b5cc0ed,0x23b6db6db7,0x233615a241,0x22b8e38e39,0x223f1f8fc8,
+ 0x21c8a60dd6,0x2155555555,0x20e50d7943,0x2077b03532,0x200d20d20d,0x1fa5440cf6,
+ 0x1f40000000,0x1edd3c0ca4,0x1e7ce0c7ce,0x1e1ed7e753,0x1dc30c30c3,0x1d69696969,
+ 0x1d11dc4771,0x1cbc52640c,0x1c68ba2e8c,0x1c1702e05c,0x1bc71c71c7,0x1b78f78f79,
+ 0x1b2c8590b2,0x1ae1b86e1c,0x1a9882b931,0x1a50d79436,0x1a0aaaaaab,0x19c5f02a3a,
+ 0x19829cbc15,0x1940a57eb5,0x1900000000,0x18c0a237c3,0x1882828283,0x1845979c95,
+ 0x1809d89d8a,0x17cf3cf3cf,0x1795bc609b,0x175d4ef40a,0x1725ed097b,0x16ef8f441c,
+ 0x16ba2e8ba3,0x1685c4093a,0x1652492492,0x161fb78122,0x15ee08fb82,0x15bd37a6f5,
+ 0x158d3dcb09,0x155e15e15e,0x152fba9387,0x150226b902,0x14d5555555,0x14a9419637,
+ 0x147de6d1d6,0x1453408534,0x14294a5295,0x1400000000,0x13d75d75d7,0x13af5ebd7b,
+ 0x1388000000,0x13613d84f6,0x133b13b13b,0x13157f05dd,0x12f07c1f08,0x12cc07b302,
+ 0x12a81e9132,0x1284bda12f,0x1261e1e1e2,0x123f8868a4,0x121dae6077,0x11fc510935,
+ 0x11db6db6db,0x11bb01d0cb,0x119b0ad120,0x117b864407,0x115c71c71c,0x113dcb08d4,
+ 0x111f8fc7e4,0x1101bdd2b9,0x10e45306eb,0x10c74d50c0,0x10aaaaaaab,0x108e691cd2,
+ 0x107286bca2,0x105701ac57,0x103bd81a99,0x1021084211,0x1006906907,0x0fec6ee105,
+ 0x0fd2a2067b,0x0fb9284067,0x0fa0000000,0x0f8727c066,0x0f6e9e0652,0x0f56615fce,
+ 0x0f3e7063e7,0x0f26c9b26d,0x0f0f6bf3aa,0x0ef855d825,0x0ee1861862,0x0ecafb74a4,
+ 0x0eb4b4b4b5,0x0e9eb0a7ac,0x0e88ee23b9,0x0e736c05eb,0x0e5e293206,0x0e49249249,
+ 0x0e345d1746,0x0e1fd1b7af,0x0e0b81702e,0x0df76b4338,0x0de38e38e4,0x0dcfe95ec3,
+ 0x0dbc7bc7bc,0x0da9448be4,0x0d9642c859,0x0d83759f23,0x0d70dc370e,0x0d5e75bb8d,
+ 0x0d4c415c99,0x0d3a3e4e90,0x0d286bca1b,0x0d16c90c10,0x0d05555555,0x0cf40feac7,
+ 0x0ce2f8151d,0x0cd20d20d2,0x0cc14e5e0a,0x0cb0bb207d,0x0ca052bf5b,0x0c9014953a,
+ 0x0c80000000,0x0c701460cc,0x0c60511be2,0x0c50b59897,0x0c41414141,0x0c31f3831f,
+ 0x0c22cbce4b,0x0c13c995a4,0x0c04ec4ec5,0x0bf63371ea,0x0be79e79e8,0x0bd92ce418,
+ 0x0bcade304d,0x0bbcb1e0c0,0x0baea77a05,0x0ba0be82fa,0x0b92f684be,0x0b854f0a9e,
+ 0x0b77c7a20e,0x0b6a5fda98,0x0b5d1745d1,0x0b4fed7750,0x0b42e2049d,0x0b35f4852a,
+ 0x0b29249249,0x0b1c71c71c,0x0b0fdbc091,0x0b03621d52,0x0af7047dc1,0x0aeac283ea,
+ 0x0ade9bd37a,0x0ad29011bb,0x0ac69ee584,0x0abac7f736,0x0aaf0af0af,0x0aa3677d47,
+ 0x0a97dd49c3,0x0a8c6c0452,0x0a81135c81,0x0a75d30337,0x0a6aaaaaab,0x0a5f9a0660,
+ 0x0a54a0cb1c,0x0a49beaee1,0x0a3ef368eb,0x0a343eb1a2,0x0a29a0429a,0x0a1f17d68b,
+ 0x0a14a5294a,0x0a0a47f7c6,0x0a00000000,0x09f5cd0105,0x09ebaebaec,0x09e1a4eecc,
+ 0x09d7af5ebd,0x09cdcdcdce
+};
+
// button tables taken from the ptplay project + modified
const guiButton_t bAsk[] =
--- a/src/pt2_tables.h
+++ b/src/pt2_tables.h
@@ -17,6 +17,7 @@
extern const uint8_t arpTickTable[32];
extern const int16_t periodTable[(37*16)+15];
extern int8_t pNoteTable[32];
+extern const uint64_t musicTimeTab64[256-32];
// changable by config file
extern uint16_t analyzerColors[36];
--- a/src/pt2_visuals.c
+++ b/src/pt2_visuals.c
@@ -507,7 +507,7 @@
void updateSongInfo2(void) // two middle rows of screen, always present
{
char tempChar;
- int32_t secs, MI_TimeM, MI_TimeS, x, i;
+ int32_t x, i;
moduleSample_t *currSample;
if (ui.updateStatusText)
@@ -601,13 +601,15 @@
// playback timer
- secs = ((editor.musicTime >> 8) * 5) >> 9;
- secs -= ((secs / 3600) * 3600);
+ const uint32_t milliseconds = editor.musicTime64 >> 32;
+ uint32_t seconds = milliseconds / 1000;
- if (secs <= 5999) // below 99 minutes 59 seconds
+ seconds -= ((seconds / 3600) * 3600); // remove hours
+ if (seconds <= 5999) // below 99 minutes 59 seconds
{
- MI_TimeM = secs / 60;
- MI_TimeS = secs - (MI_TimeM * 60);
+ uint32_t MI_TimeM = seconds / 60;
+ seconds -= MI_TimeM * 60; // remove minutes
+ uint32_t MI_TimeS = seconds;
// xx:xx
printTwoDecimalsBg(272, 102, MI_TimeM, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);