ref: 028871c49c340acc62c3ca8771d2eadc5b4cbc75
parent: e8a29beb7a6ba80b8a6596010bee8cdfd8a24421
author: Olav Sørensen <olav.sorensen@live.no>
date: Tue Jun 23 16:06:27 EDT 2020
Pushed v1.26 code - Song BPM is now more accurate (it used to be slightly off for some BPMs) - Arpeggio is now 100% FT2-correct for ticks 31..99 (speed 31..99 is only obtainable by hex-editing XMs). - Fixed compiling error on ARM CPUs - Code cleanup
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -161,7 +161,8 @@
if (bpm > MAX_BPM)
return;
- audio.samplesPerTick = audio.speedValTab[bpm];
+ audio.dSamplesPerTick = audio.dSpeedValTab[bpm];
+ audio.samplesPerTick = (int32_t)(audio.dSamplesPerTick + 0.5);
// get tick time length for audio/video sync timestamp
const uint64_t tickTimeLen64 = audio.tickTimeLengthTab[bpm];
@@ -579,13 +580,13 @@
}
// used for song-to-WAV renderer
-uint32_t mixReplayerTickToBuffer(uint8_t *stream, uint8_t bitDepth)
+void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth)
{
voice_t *v, *r;
- assert(audio.speedVal <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
- memset(audio.mixBufferL, 0, audio.samplesPerTick * sizeof (int32_t));
- memset(audio.mixBufferR, 0, audio.samplesPerTick * sizeof (int32_t));
+ assert(samplesToMix <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
+ memset(audio.mixBufferL, 0, samplesToMix * sizeof (int32_t));
+ memset(audio.mixBufferR, 0, samplesToMix * sizeof (int32_t));
// mix channels
v = voice; // normal voices
@@ -594,8 +595,8 @@
for (int32_t i = 0; i < song.antChn; i++, v++, r++)
{
// call the mixing routine currently set for the voice
- if (v->mixRoutine != NULL) v->mixRoutine(v, audio.samplesPerTick); // mix normal voice
- if (r->mixRoutine != NULL) r->mixRoutine(r, audio.samplesPerTick); // mix volume ramp voice
+ if (v->mixRoutine != NULL) v->mixRoutine(v, samplesToMix); // mix normal voice
+ if (r->mixRoutine != NULL) r->mixRoutine(r, samplesToMix); // mix volume ramp voice
}
// normalize mix buffer and send to audio stream
@@ -602,16 +603,14 @@
if (bitDepth == 16)
{
if (config.specialFlags2 & DITHERED_AUDIO)
- sendSamples16BitDitherStereo(stream, audio.samplesPerTick, 2);
+ sendSamples16BitDitherStereo(stream, samplesToMix, 2);
else
- sendSamples16BitStereo(stream, audio.samplesPerTick, 2);
+ sendSamples16BitStereo(stream, samplesToMix, 2);
}
else
{
- sendSamples24BitStereo(stream, audio.samplesPerTick, 2);
+ sendSamples24BitStereo(stream, samplesToMix, 2);
}
-
- return audio.samplesPerTick;
}
int32_t pattQueueReadSize(void)
@@ -930,9 +929,6 @@
static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len)
{
- assert(len < 65536); // limitation in mixer
- assert(pmpCountDiv > 0);
-
int32_t samplesLeft = len / pmpCountDiv;
if (samplesLeft <= 0)
return;
@@ -939,7 +935,7 @@
while (samplesLeft > 0)
{
- if (audio.tickSampleCounter == 0)
+ if (audio.dTickSampleCounter <= 0.0)
{
// new replayer tick
@@ -952,23 +948,25 @@
mix_UpdateChannelVolPanFrq();
fillVisualsSyncBuffer();
- audio.tickSampleCounter = audio.samplesPerTick;
+ audio.dTickSampleCounter += audio.dSamplesPerTick;
replayerBusy = false;
}
+ const int32_t remainingTick = (int32_t)ceil(audio.dTickSampleCounter);
+
int32_t samplesToMix = samplesLeft;
- if (samplesToMix > audio.tickSampleCounter)
- samplesToMix = audio.tickSampleCounter;
+ if (samplesToMix > remainingTick)
+ samplesToMix = remainingTick;
mixAudio(stream, samplesToMix, pmpChannels);
stream += samplesToMix * pmpCountDiv;
samplesLeft -= samplesToMix;
- audio.tickSampleCounter -= samplesToMix;
+ audio.dTickSampleCounter -= samplesToMix;
}
- (void)userdata;
+ (void)userdata; // make compiler not complain
}
static bool setupAudioBuffers(void)
@@ -1223,7 +1221,7 @@
stopAllScopes();
- audio.tickSampleCounter = 0; // zero tick sample counter so that it will instantly initiate a tick
+ audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
calcReplayRate(audio.freq);
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -50,12 +50,11 @@
bool linearFreqTable, rescanAudioDevicesSupported;
int32_t inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;
int32_t quickVolSizeVal, *mixBufferL, *mixBufferR, *mixBufferLUnaligned, *mixBufferRUnaligned;
- int32_t rampQuickVolMul, rampSpeedValMul, speedValTab[MAX_BPM+1], rampSpeedValMulTab[MAX_BPM+1];
- int32_t tickSampleCounter;
+ int32_t rampQuickVolMul, rampSpeedValMul, rampSpeedValMulTab[MAX_BPM+1];
uint32_t freq;
uint32_t audLatencyPerfValInt, audLatencyPerfValFrac, samplesPerTick, musicTimeSpeedVal;
uint64_t tickTime64, tickTime64Frac, tickTimeLengthTab[MAX_BPM+1];
- double dAudioLatencyMs;
+ double dAudioLatencyMs, dSamplesPerTick, dTickSampleCounter, dSpeedValTab[MAX_BPM+1];
SDL_AudioDeviceID dev;
uint32_t wantFreq, haveFreq, wantSamples, haveSamples, wantChannels, haveChannels;
} audio_t;
@@ -139,7 +138,7 @@
void updateSendAudSamplesRoutine(bool lockMixer);
void mix_SaveIPVolumes(void);
void mix_UpdateChannelVolPanFrq(void);
-uint32_t mixReplayerTickToBuffer(uint8_t *stream, uint8_t bitDepth);
+void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth);
// in ft2_audio.c
extern audio_t audio;
--- a/src/ft2_pattern_ed.c
+++ b/src/ft2_pattern_ed.c
@@ -2244,7 +2244,8 @@
{
if (songPlaying)
{
- uint32_t seconds = song.musicTime64 >> 32;
+ const uint32_t milliseconds = song.musicTime64 >> 32;
+ uint32_t seconds = milliseconds / 1000;
last_TimeH = seconds / 3600; seconds -= last_TimeH * 3600;
last_TimeM = seconds / 60; seconds -= last_TimeM * 60;
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -27,7 +27,6 @@
*/
// non-FT2 precalced stuff
-static uint32_t musicTimeTab[MAX_BPM+1];
static double dPeriod2HzTab[65536], dLogTab[768], dAudioRateFactor;
static bool bxxOverflow;
@@ -359,24 +358,21 @@
** but it doesn't take up a lot of RAM, so why not.
*/
- audio.speedValTab[0] = 0;
- musicTimeTab[0] = UINT32_MAX;
+ audio.dSpeedValTab[0] = 0.0;
audio.tickTimeLengthTab[0] = UINT64_MAX;
audio.rampSpeedValMulTab[0] = INT32_MAX;
- const double dMul1 = (UINT32_MAX + 1.0) / audioFreq;
- const double dMul2 = (editor.dPerfFreq / audioFreq) * (UINT32_MAX + 1.0);
-
- for (int32_t i = 1; i <= MAX_BPM; i++)
+ const double dMul = (UINT32_MAX + 1.0) / audioFreq;
+ for (int32_t i = MIN_BPM; i <= MAX_BPM; i++)
{
- const int32_t samplesPerTick = (int32_t)(((audioFreq * 2.5) / i) + 0.5); // rounded
- audio.speedValTab[i] = samplesPerTick;
+ const double dBpmHz = i / 2.5;
+ const double dSamplesPerTick = audioFreq / dBpmHz;
+ const int32_t samplesPerTick = (int32_t)(dSamplesPerTick + 0.5); // rounded
- // used for song playback counter (hh:mm:ss)
- musicTimeTab[i] = (uint32_t)((samplesPerTick * dMul1) + 0.5);
+ audio.dSpeedValTab[i] = dSamplesPerTick;
// number of samples per tick -> tick length for performance counter (syncing visuals to audio)
- audio.tickTimeLengthTab[i] = (uint64_t)(samplesPerTick * dMul2);
+ audio.tickTimeLengthTab[i] = (uint64_t)(dSamplesPerTick * dMul);
// for calculating volume ramp length for "tick" ramps
audio.rampSpeedValMulTab[i] = (int32_t)(((UINT32_MAX + 1.0) / samplesPerTick) + 0.5);
@@ -2100,8 +2096,8 @@
return;
}
- assert(song.speed >= MIN_BPM && song.speed <= MAX_BPM);
- song.musicTime64 += musicTimeTab[song.speed]; // for song playback counter (hh:mm:ss)
+ if (song.speed >= MIN_BPM && song.speed <= MAX_BPM)
+ song.musicTime64 += musicTimeTab64[song.speed]; // for song playback counter (hh:mm:ss)
readNewNote = false;
@@ -2780,7 +2776,7 @@
if (song.tempo == 0)
song.tempo = song.initialTempo;
- audio.tickSampleCounter = 0; // zero tick sample counter so that it will instantly initiate a tick
+ audio.dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
unlockMixerCallback();
--- a/src/ft2_tables.c
+++ b/src/ft2_tables.c
@@ -1006,3 +1006,182 @@
0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,
0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x40,0x1F,0x01,0x00,0x00,0x08,0x00,0x00,0x00
};
+
+/* ----------------------------------------------------------------------- */
+/* MISCELLANEOUS TABLES */
+/* ----------------------------------------------------------------------- */
+
+/*
+** const double dBpmMs = 1000.0 / (bpm / 2.5);
+** x = (uint64_t)round((UINT32_MAX + 1.0) * dBpmMs);
+*/
+const uint64_t musicTimeTab64[MAX_BPM+1] =
+{
+ 0x00000000000,0x9c400000000,0x4e200000000,0x34155555555,0x27100000000,0x1f400000000,
+ 0x1a0aaaaaaab,0x16524924925,0x13880000000,0x115c71c71c7,0x0fa00000000,0x0e345d1745d,
+ 0x0d055555555,0x0c04ec4ec4f,0x0b292492492,0x0a6aaaaaaab,0x09c40000000,0x0930f0f0f0f,
+ 0x08ae38e38e4,0x0839435e50d,0x07d00000000,0x0770c30c30c,0x071a2e8ba2f,0x06cb21642c8,
+ 0x0682aaaaaab,0x06400000000,0x06027627627,0x05c97b425ed,0x05949249249,0x05634f72c23,
+ 0x05355555555,0x050a5294a53,0x04e20000000,0x04bc1f07c1f,0x04987878788,0x0476db6db6e,
+ 0x04571c71c72,0x043914c1bad,0x041ca1af287,0x0401a41a41a,0x03e80000000,0x03cf9c18f9c,
+ 0x03b86186186,0x03a23b88ee2,0x038d1745d17,0x0378e38e38e,0x036590b2164,0x03531057262,
+ 0x03415555555,0x0330539782a,0x03200000000,0x03105050505,0x03013b13b14,0x02f2b78c135,
+ 0x02e4bda12f7,0x02d745d1746,0x02ca4924925,0x02bdc11f704,0x02b1a7b9612,0x02a5f75270d,
+ 0x029aaaaaaab,0x028fbcda3ac,0x0285294a529,0x027aebaebaf,0x02710000000,0x02676276276,
+ 0x025e0f83e10,0x025503d2263,0x024c3c3c3c4,0x0243b5cc0ed,0x023b6db6db7,0x0233615a241,
+ 0x022b8e38e39,0x0223f1f8fc8,0x021c8a60dd6,0x02155555555,0x020e50d7943,0x02077b03532,
+ 0x0200d20d20d,0x01fa5440cf6,0x01f40000000,0x01edd3c0ca4,0x01e7ce0c7ce,0x01e1ed7e753,
+ 0x01dc30c30c3,0x01d69696969,0x01d11dc4771,0x01cbc52640c,0x01c68ba2e8c,0x01c1702e05c,
+ 0x01bc71c71c7,0x01b78f78f79,0x01b2c8590b2,0x01ae1b86e1c,0x01a9882b931,0x01a50d79436,
+ 0x01a0aaaaaab,0x019c5f02a3a,0x019829cbc15,0x01940a57eb5,0x01900000000,0x018c0a237c3,
+ 0x01882828283,0x01845979c95,0x01809d89d8a,0x017cf3cf3cf,0x01795bc609b,0x0175d4ef40a,
+ 0x01725ed097b,0x016ef8f441c,0x016ba2e8ba3,0x01685c4093a,0x01652492492,0x0161fb78122,
+ 0x015ee08fb82,0x015bd37a6f5,0x0158d3dcb09,0x0155e15e15e,0x0152fba9387,0x0150226b902,
+ 0x014d5555555,0x014a9419637,0x0147de6d1d6,0x01453408534,0x014294a5295,0x01400000000,
+ 0x013d75d75d7,0x013af5ebd7b,0x01388000000,0x013613d84f6,0x0133b13b13b,0x013157f05dd,
+ 0x012f07c1f08,0x012cc07b302,0x012a81e9132,0x01284bda12f,0x01261e1e1e2,0x0123f8868a4,
+ 0x0121dae6077,0x011fc510935,0x011db6db6db,0x011bb01d0cb,0x0119b0ad120,0x0117b864407,
+ 0x0115c71c71c,0x0113dcb08d4,0x0111f8fc7e4,0x01101bdd2b9,0x010e45306eb,0x010c74d50c0,
+ 0x010aaaaaaab,0x0108e691cd2,0x0107286bca2,0x0105701ac57,0x0103bd81a99,0x01021084211,
+ 0x01006906907,0x00fec6ee105,0x00fd2a2067b,0x00fb9284067,0x00fa0000000,0x00f8727c066,
+ 0x00f6e9e0652,0x00f56615fce,0x00f3e7063e7,0x00f26c9b26d,0x00f0f6bf3aa,0x00ef855d825,
+ 0x00ee1861862,0x00ecafb74a4,0x00eb4b4b4b5,0x00e9eb0a7ac,0x00e88ee23b9,0x00e736c05eb,
+ 0x00e5e293206,0x00e49249249,0x00e345d1746,0x00e1fd1b7af,0x00e0b81702e,0x00df76b4338,
+ 0x00de38e38e4,0x00dcfe95ec3,0x00dbc7bc7bc,0x00da9448be4,0x00d9642c859,0x00d83759f23,
+ 0x00d70dc370e,0x00d5e75bb8d,0x00d4c415c99,0x00d3a3e4e90,0x00d286bca1b,0x00d16c90c10,
+ 0x00d05555555,0x00cf40feac7,0x00ce2f8151d,0x00cd20d20d2,0x00cc14e5e0a,0x00cb0bb207d,
+ 0x00ca052bf5b,0x00c9014953a,0x00c80000000,0x00c701460cc,0x00c60511be2,0x00c50b59897,
+ 0x00c41414141,0x00c31f3831f,0x00c22cbce4b,0x00c13c995a4,0x00c04ec4ec5,0x00bf63371ea,
+ 0x00be79e79e8,0x00bd92ce418,0x00bcade304d,0x00bbcb1e0c0,0x00baea77a05,0x00ba0be82fa,
+ 0x00b92f684be,0x00b854f0a9e,0x00b77c7a20e,0x00b6a5fda98,0x00b5d1745d1,0x00b4fed7750,
+ 0x00b42e2049d,0x00b35f4852a,0x00b29249249,0x00b1c71c71c,0x00b0fdbc091,0x00b03621d52,
+ 0x00af7047dc1,0x00aeac283ea,0x00ade9bd37a,0x00ad29011bb,0x00ac69ee584,0x00abac7f736,
+ 0x00aaf0af0af,0x00aa3677d47,0x00a97dd49c3,0x00a8c6c0452,0x00a81135c81,0x00a75d30337,
+ 0x00a6aaaaaab,0x00a5f9a0660,0x00a54a0cb1c,0x00a49beaee1,0x00a3ef368eb,0x00a343eb1a2,
+ 0x00a29a0429a,0x00a1f17d68b,0x00a14a5294a,0x00a0a47f7c6,0x00a00000000,0x009f5cd0105,
+ 0x009ebaebaec,0x009e1a4eecc,0x009d7af5ebd,0x009cdcdcdce,0x009c4000000,0x009ba45ba46,
+ 0x009b09ec27b,0x009a70adf62,0x0099d89d89e,0x009941b76af,0x0098abf82ee,0x0098175c78b,
+ 0x009783e0f84,0x0096f1826a4,0x0096603d981,0x0095d00f574,0x009540f4899,0x0094b2ea1c9,
+ 0x009425ed098,0x009399fa550,0x00930f0f0f1,0x00928528528,0x0091fc43452,0x0091745d174,
+ 0x0090ed7303b,0x009067824f8,0x008fe28849b,0x008f5e824b4,0x008edb6db6e,0x008e5947f8b,
+ 0x008dd80e866,0x008d57bede8,0x008cd856890,0x008c59d3167,0x008bdc32204,0x008b5f71484,
+ 0x008ae38e38e,0x008a6886a4c,0x0089ee5846a,0x00897500e13,0x0088fc7e3f2,0x008884ce32b,
+ 0x00880dee95c,0x008797dd49c,0x00872298376,0x0086ae1d4e7,0x00863a6a860,0x0085c77ddc1,
+ 0x00855555555,0x0084e3eefd7,0x00847348e69,0x00840361296,0x00839435e51,0x008325c53ef,
+ 0x0082b80d62c,0x00824b0c821,0x0081dec0d4c,0x00817328987,0x00810842108,0x00809e0b863,
+ 0x00803483483,0x007fcba7aaf,0x007f6377082,0x007efbefbf0,0x007e951033e,0x007e2ed6d06,
+ 0x007dc942034,0x007d6450403,0x007d0000000,0x007c9c4fc03,0x007c393e033,0x007bd6c9501,
+ 0x007b74f0329,0x007b13b13b1,0x007ab30afe7,0x007a52fc15f,0x0079f3831f4,0x0079949ebc5,
+ 0x0079364d936,0x0078d88e4ee,0x00787b5f9d5,0x00781ec0313,0x0077c2aec12,0x0077672a07a,
+ 0x00770c30c31,0x0076b1c1b59,0x007657dba52,0x0075fe7d5b6,0x0075a5a5a5a,0x00754d5354d,
+ 0x0074f5853d6,0x00749e3a374,0x007447711dc,0x0073f128cfc,0x00739b602f6,0x0073461621f,
+ 0x0072f149903,0x00729cf965f,0x00724924925,0x0071f5ca075,0x0071a2e8ba3,0x0071507fa33,
+ 0x0070fe8dbd8,0x0070ad12073,0x00705c0b817,0x00700b79301,0x006fbb5a19c,0x006f6bad480,
+ 0x006f1c71c72,0x006ecda6a5f,0x006e7f4af62,0x006e315dcbd,0x006de3de3de,0x006d96cb65b,
+ 0x006d4a245f2,0x006cfde8489,0x006cb21642d,0x006c66ad711,0x006c1bacf91,0x006bd11402c,
+ 0x006b86e1b87,0x006b3d1546b,0x006af3addc7,0x006aaaaaaab,0x006a620ae4c,0x006a19cdc03,
+ 0x0069d1f2748,0x00698a783b7,0x0069435e50d,0x0068fca3f29,0x0068b648608,0x0068704adc9,
+ 0x00682aaaaab,0x0067e56710a,0x0067a07f563,0x00675bf2c52,0x006717c0a8f,0x0066d3e84f0,
+ 0x00669069069,0x00664d4220c,0x00660a72f05,0x0065c7fac9f,0x006585d903e,0x0065440cf64,
+ 0x00650295fad,0x0064c1736d0,0x006480a4a9d,0x00644029101,0x00640000000,0x0063c028dba,
+ 0x006380a3066,0x0063416de55,0x00630288df1,0x0062c3f35ba,0x006285acc4c,0x006247b4856,
+ 0x00620a0a0a1,0x0061ccacc0d,0x00618f9c190,0x006152d7837,0x0061165e725,0x0060da30594,
+ 0x00609e4cad2,0x006062b2e44,0x00602762762,0x005fec5adbc,0x005fb19b8f5,0x005f77240c4,
+ 0x005f3cf3cf4,0x005f030a566,0x005ec96720c,0x005e9009aee,0x005e56f1827,0x005e1e1e1e2,
+ 0x005de58f060,0x005dad43bf4,0x005d753bd02,0x005d3d76c02,0x005d05f417d,0x005cceb360d,
+ 0x005c97b425f,0x005c60f5f30,0x005c2a7854f,0x005bf43ad9c,0x005bbe3d107,0x005b887e891,
+ 0x005b52fed4c,0x005b1dbd859,0x005ae8ba2e9,0x005ab3f463e,0x005a7f6bba8,0x005a4b1fc88,
+ 0x005a171024e,0x0059e33c679,0x0059afa4295,0x00597c47040,0x00594924925,0x0059163c6fc,
+ 0x0058e38e38e,0x0058b1198b1,0x00587ede048,0x00584cdb446,0x00581b10ea9,0x0057e97e97f,
+ 0x0057b823ee1,0x005787008f6,0x005756141f5,0x0057255e41d,0x0056f4de9bd,0x0056c494d30,
+ 0x005694808de,0x005664a1739,0x005634f72c2,0x00560581606,0x0055d63fb9b,0x0055a731e26,
+ 0x00557857858,0x005549b04ea,0x00551b3bea3,0x0054ecfa057,0x0054beea4e2,0x0054910c72c,
+ 0x00546360229,0x005435e50d8,0x0054089ae41,0x0053db81578,0x0053ae9819b,0x005381dedd4,
+ 0x00535555555,0x005328fb35c,0x0052fcd0330,0x0052d0d4022,0x0052a50658e,0x00527966ed8,
+ 0x00524df5771,0x005222b1acf,0x0051f79b476,0x0051ccb1fef,0x0051a1f58d1,0x00517765ab9,
+ 0x00514d0214d,0x005122ca83e,0x0050f8beb45,0x0050cede624,0x0050a5294a5,0x00507b9f29c,
+ 0x0050523fbe3,0x0050290ac60,0x00500000000,0x004fd71f2b7,0x004fae68083,0x004f85da568,
+ 0x004f5d75d76,0x004f353a4c1,0x004f0d27766,0x004ee53d18c,0x004ebd7af5f,0x004e95e0d14,
+ 0x004e6e6e6e7,0x004e472391d,0x004e2000000,0x004df9037e4,0x004dd22dd23,0x004dab7ec1e,
+ 0x004d84f613e,0x004d5e938f2,0x004d3856fb1,0x004d12401f9,0x004cec4ec4f,0x004cc682b3d,
+ 0x004ca0dbb57,0x004c7b59935,0x004c55fc177,0x004c30c30c3,0x004c0bae3c6,0x004be6bd732,
+ 0x004bc1f07c2,0x004b9d47235,0x004b78c1352,0x004b545e7e5,0x004b301ecc0,0x004b0c01ebd,
+ 0x004ae807aba,0x004ac42fd9c,0x004aa07a44c,0x004a7ce6bbd,0x004a59750e4,0x004a36250be,
+ 0x004a12f684c,0x0049efe9496,0x0049ccfd2a8,0x0049aa31f96,0x00498787878,0x004964fda6c,
+ 0x00494294294,0x0049204ae19,0x0048fe21a29,0x0048dc183f7,0x0048ba2e8ba,0x004898645b1,
+ 0x004876b981e,0x0048552dd48,0x004833c127c,0x0048127350c,0x0047f14424d,0x0047d03379d,
+ 0x0047af4125a,0x00478e6cfea,0x00476db6db7,0x00474d1e92f,0x00472ca3fc6,0x00470c46ef3,
+ 0x0046ec07433,0x0046cbe4d07,0x0046abdf6f4,0x00468bf6f85,0x00466c2b448,0x00464c7c2d0,
+ 0x00462ce98b4,0x00460d7338f,0x0045ee19102,0x0045cedaeb0,0x0045afb8a42,0x004590b2164,
+ 0x004571c71c7,0x004552f7920,0x00453443526,0x004515aa398,0x0044f72c235,0x0044d8c8ec3,
+ 0x0044ba8070a,0x00449c528d6,0x00447e3f1f9,0x00446046046,0x00444267195,0x004424a23c3,
+ 0x004406f74ae,0x0043e96623a,0x0043cbeea4e,0x0043ae90ad4,0x0043914c1bb,0x00437420cf3,
+ 0x0043570ea74,0x00433a15834,0x00431d35430,0x0043006dc69,0x0042e3beee0,0x0042c72899e,
+ 0x0042aaaaaab,0x00428e45014,0x004271f77ec,0x004255c2044,0x004239a4735,0x00421d9ead8,
+ 0x004201b094b,0x0041e5da0af,0x0041ca1af28,0x0041ae732dd,0x004192e29f8,0x004177692a5,
+ 0x00415c06b16,0x004140bb17d,0x00412586411,0x00410a6810a,0x0040ef606a6,0x0040d46f323,
+ 0x0040b9944c4,0x00409ecf9cc,0x00408421084,0x00406988737,0x00404f05c31,0x00403498dc4,
+ 0x00401a41a42,0x00400000000,0x003fe5d3d58,0x003fcbbd0a3,0x003fb1bb841,0x003f97cf292,
+ 0x003f7df7df8,0x003f64358d9,0x003f4a8819f,0x003f30ef6b3,0x003f176b683,0x003efdfbf7f,
+ 0x003ee4a101a,0x003ecb5a6c8,0x003eb228202,0x003e990a040,0x003e8000000,0x003e6709fc0,
+ 0x003e4e27e02,0x003e3559948,0x003e1c9f019,0x003e03f80fe,0x003deb64a80,0x003dd2e4b2e,
+ 0x003dba78195,0x003da21ec47,0x003d89d89d9,0x003d71a58df,0x003d59857f3,0x003d41785af,
+ 0x003d297e0af,0x003d1196793,0x003cf9c18fa,0x003ce1ff388,0x003cca4f5e2,0x003cb2b1eb0,
+ 0x003c9b26c9b,0x003c83ade4e,0x003c6c47277,0x003c54f27c5,0x003c3dafcea,0x003c267f09a,
+ 0x003c0f6018a,0x003bf852e71,0x003be157609,0x003bca6d70e,0x003bb39503d,0x003b9cce055,
+ 0x003b8618618,0x003b6f74049,0x003b58e0dac,0x003b425ed09,0x003b2bedd29,0x003b158dcd5,
+ 0x003aff3eadb,0x003ae900608,0x003ad2d2d2d,0x003abcb5f1b,0x003aa6a9aa7,0x003a90adea4,
+ 0x003a7ac29eb,0x003a64e7b54,0x003a4f1d1ba,0x003a3962bf9,0x003a23b88ee,0x003a0e1e77a,
+ 0x0039f89467e,0x0039e31a4dd,0x0039cdb017b,0x0039b855b3e,0x0039a30b10f,0x00398dd01d7,
+ 0x003978a4c81,0x00396388ffa,0x00394e7cb30,0x0039397fd12,0x00392492492,0x00390fb40a4,
+ 0x0038fae503a,0x0038e62524c,0x0038d1745d1,0x0038bcd29c2,0x0038a83fd19,0x003893bbed3,
+ 0x00387f46dec,0x00386ae0963,0x0038568903a,0x00384240171,0x00382e05c0c,0x003819d9f0f,
+ 0x003805bc980,0x0037f1ada68,0x0037ddad0ce,0x0037c9babbd,0x0037b5d6a40,0x0037a200b65,
+ 0x00378e38e39,0x00377a7f1cc,0x003766d3530,0x00375335775,0x00373fa57b1,0x00372c234f7,
+ 0x003718aee5f,0x003705482fe,0x0036f1ef1ef,0x0036dea3a4b,0x0036cb65b2e,0x0036b8353b3,
+ 0x0036a5122f9,0x003691fc81f,0x00367ef4244,0x00366bf908b,0x0036590b216,0x0036462a609,
+ 0x00363356b89,0x003620901bb,0x00360dd67c9,0x0035fb29cd9,0x0035e88a016,0x0035d5f70ab,
+ 0x0035c370dc3,0x0035b0f768d,0x00359e8aa36,0x00358c2a7ed,0x003579d6ee3,0x0035678fe4b,
+ 0x00355555555,0x00354327338,0x00353105726,0x00351ef0057,0x00350ce6e01,0x0034fae9f5d,
+ 0x0034e8f93a4,0x0034d714a10,0x0034c53c1dc,0x0034b36fa44,0x0034a1af287,0x00348ffa9e2,
+ 0x00347e51f94,0x00346cb52df,0x00345b24304,0x0034499ef45,0x003438256e5,0x003426b7928,
+ 0x00341555555,0x003403feab2,0x0033f2b3885,0x0033e173e17,0x0033d03fab2,0x0033bf16d9f,
+ 0x0033adf9629,0x00339ce739d,0x00338be0547,0x00337ae4a76,0x003369f4278,0x0033590ec9c,
+ 0x00334834835,0x00333765492,0x003326a1106,0x003315e7ce5,0x00330539783,0x0032f496034,
+ 0x0032e3fd64f,0x0032d36f92b,0x0032c2ec81f,0x0032b274284,0x0032a2067b2,0x003291a3705,
+ 0x0032814afd7,0x003270fd183,0x003260b9b68,0x00325080ce1,0x0032405254e,0x0032302e40e,
+ 0x00322014880,0x00321005206,0x00320000000,0x0031f0051d1,0x0031e0146dd,0x0031d02de87,
+ 0x0031c051833,0x0031b07f348,0x0031a0b6f2b,0x003190f8b43,0x003181446f8,0x0031719a1b3,
+ 0x003161f9add,0x003152631e0,0x003142d6626,0x0031335371b,0x003123da42b,0x0031146acc3,
+ 0x00310505050,0x0030f5a8e42,0x0030e656606,0x0030d70d70d,0x0030c7ce0c8,0x0030b8982a7,
+ 0x0030a96bc1b,0x00309a48c99,0x00308b2f393,0x00307c1f07c,0x00306d182ca,0x00305e1a9f2,
+ 0x00304f26569,0x0030403b4a7,0x00303159722,0x00302280c53,0x003013b13b1,0x003004eacb7,
+ 0x002ff62d6de,0x002fe7791a1,0x002fd8cdc7a,0x002fca2b6e7,0x002fbb92062,0x002fad01869,
+ 0x002f9e79e7a,0x002f8ffb213,0x002f81852b3,0x002f7317fd9,0x002f64b3906,0x002f5657dba,
+ 0x002f4804d77,0x002f39ba7bf,0x002f2b78c13,0x002f1d3f9f8,0x002f0f0f0f1,0x002f00e7082,
+ 0x002ef2c7830,0x002ee4b0781,0x002ed6a1dfa,0x002ec89bb22,0x002eba9de81,0x002eaca879e,
+ 0x002e9ebb601,0x002e90d6934,0x002e82fa0bf,0x002e7525c2c,0x002e6759b07,0x002e5995cd9,
+ 0x002e4bda12f,0x002e3e26795,0x002e307af98,0x002e22d78c4,0x002e153c2a8,0x002e07a8cd1,
+ 0x002dfa1d6ce,0x002dec9a02f,0x002ddf1e884,0x002dd1aaf5c,0x002dc43f449,0x002db6db6db,
+ 0x002da97f6a6,0x002d9c2b33b,0x002d8edec2c,0x002d819a10e,0x002d745d174,0x002d6727cf3,
+ 0x002d59fa31f,0x002d4cd438d,0x002d3fb5dd4,0x002d329f189,0x002d258fe44,0x002d188839c,
+ 0x002d0b88127,0x002cfe8f67f,0x002cf19e33c,0x002ce4b46f8,0x002cd7d214b,0x002ccaf71cf,
+ 0x002cbe23820,0x002cb1573d8,0x002ca492492,0x002c97d49eb,0x002c8b1e37e,0x002c7e6f0e8,
+ 0x002c71c71c7,0x002c65265b8,0x002c588cc59,0x002c4bfa548,0x002c3f6f024,0x002c32eac8d,
+ 0x002c266da23,0x002c19f7885,0x002c0d88755,0x002c0120632,0x002bf4bf4bf,0x002be86529e,
+ 0x002bdc11f70,0x002bcfc5ad9,0x002bc38047b,0x002bb741bfa,0x002bab0a0fa,0x002b9ed9320,
+ 0x002b92af20f,0x002b868bd6c,0x002b7a6f4df,0x002b6e5980b,0x002b624a698,0x002b564202c,
+ 0x002b4a4046f,0x002b3e45307,0x002b3250b9c,0x002b2662dd8,0x002b1a7b961,0x002b0e9ade2,
+ 0x002b02c0b03,0x002af6ed06e,0x002aeb1fdcd,0x002adf592cc,0x002ad398f13,0x002ac7df24f,
+ 0x002abc2bc2c,0x002ab07ec54,0x002aa4d8275,0x002a9937e3a,0x002a8d9df52,0x002a820a568,
+ 0x002a767d02b,0x002a6af5f4a,0x002a5f75271,0x002a53fa950,0x002a4886396,0x002a3d180f2,
+ 0x002a31b0115,0x002a264e3ad,0x002a1af286c,0x002a0f9cf02,0x002a044d720,0x0029f904078,
+ 0x0029edc0abc,0x0029e28359d,0x0029d74c0ce,0x0029cc1ac01,0x0029c0ef6ea,0x0029b5ca13c,
+ 0x0029aaaaaab,0x00299f912ea,0x0029947d9ae,0x0029896feac,0x00297e68198,0x00297366228,
+ 0x0029686a011,0x00295d73b09,0x002952832c7,0x00294798700,0x00293cb376c,0x002931d43c2,
+ 0x002926fabb8,0x00291c26f08,0x00291158d68,0x00290690690,0x0028fbcda3b,0x0028f11081f,
+ 0x0028e658ff8,0x0028dba717d,0x0028d0fac68,0x0028c654075,0x0028bbb2d5c,0x0028b1172d9,
+ 0x0028a6810a7,0x00289bf067f,0x0028916541f,0x002886df942,0x00287c5f5a3,0x002871e48ff,
+ 0x0028676f312,0x00285cff39a,0x00285294a53,0x0028482f6fa,0x00283dcf94e,0x0028337510c,
+ 0x0028291fdf2,0x00281ecffbe,0x00281485630,0x00280a40106
+};
--- a/src/ft2_tables.h
+++ b/src/ft2_tables.h
@@ -47,3 +47,5 @@
extern const uint16_t scopeLenTab[16][32];
extern const uint8_t defConfigData[CONFIG_FILE_SIZE];
+
+extern const uint64_t musicTimeTab64[MAX_BPM+1];
--- a/src/ft2_wav_renderer.c
+++ b/src/ft2_wav_renderer.c
@@ -265,7 +265,7 @@
return returnValue;
}
-uint32_t dump_RenderTick(uint8_t *buffer) // returns bytes mixed
+void dump_RenderTick(uint32_t samplesPerTick, uint8_t *buffer)
{
replayerBusy = true;
@@ -277,7 +277,7 @@
replayerBusy = false;
- return mixReplayerTickToBuffer(buffer, WDBitDepth);
+ mixReplayerTickToBuffer(samplesPerTick, buffer, WDBitDepth);
}
static void updateVisuals(void)
@@ -304,7 +304,7 @@
{
bool renderDone;
uint8_t *ptr8, loopCounter;
- uint32_t samplesInChunk, tickSamples, sampleCounter;
+ uint32_t samplesInChunk, sampleCounter;
FILE *f;
(void)ptr;
@@ -325,6 +325,8 @@
renderDone = false;
loopCounter = 8;
+ double dTickSamples = audio.dSamplesPerTick;
+
editor.wavReachedEndFlag = false;
while (!renderDone)
{
@@ -340,16 +342,21 @@
break;
}
- tickSamples = dump_RenderTick(ptr8) << 1; // *2 for stereo
+ int32_t tickSamples = (int32_t)dTickSamples;
+ dump_RenderTick(tickSamples, ptr8);
+ dTickSamples -= tickSamples; // keep fractional part
+ dTickSamples += audio.dSamplesPerTick;
+
+ tickSamples *= 2; // stereo
samplesInChunk += tickSamples;
- sampleCounter += tickSamples;
+ sampleCounter += tickSamples;
// increase buffer pointer
if (WDBitDepth == 16)
- ptr8 += (tickSamples * sizeof (int16_t));
+ ptr8 += tickSamples * sizeof (int16_t);
else
- ptr8 += (tickSamples * sizeof (float));
+ ptr8 += tickSamples * sizeof (float);
if (++loopCounter >= 8)
{
--- a/src/ft2_wav_renderer.h
+++ b/src/ft2_wav_renderer.h
@@ -22,7 +22,7 @@
void showWavRenderer(void);
void hideWavRenderer(void);
void exitWavRenderer(void);
-uint32_t dump_RenderTick(uint8_t *buffer);
+void dump_RenderTick(uint32_t samplesPerTick, uint8_t *buffer);
void pbWavRender(void);
void pbWavExit(void);
void pbWavFreqUp(void);