ref: 2c1dbb2b5046daab3ee22d83e2cd8501292cb504
parent: 64789ba9ad662eab1a1c7a4def30a618d8f9417d
author: Olav Sørensen <olav.sorensen@live.no>
date: Fri Feb 26 09:09:24 EST 2021
tuneSample() fix for Amiga periods
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -130,7 +130,9 @@
#define MIN_PERIOD (0)
#define MAX_PERIOD (((10*12*16)-1)-1) /* -1 (because of bugged amigaPeriods table values) */
+ double (*dGetHzFromPeriod)(int32_t) = linearPeriodsFlag ? &linearPeriod2Hz : &amigaPeriod2Hz;
const uint16_t *periodTab = linearPeriodsFlag ? linearPeriods : amigaPeriods;
+
if (midCFreq <= 0 || periodTab == NULL)
{
s->fine = s->relTon = 0;
@@ -139,7 +141,7 @@
// handle frequency boundaries first...
- if (midCFreq <= (int32_t)dPeriod2HzTab[periodTab[MIN_PERIOD]])
+ if (midCFreq <= (int32_t)dGetHzFromPeriod(periodTab[MIN_PERIOD]))
{
s->fine = -128;
s->relTon = -48;
@@ -146,7 +148,7 @@
return;
}
- if (midCFreq >= (int32_t)dPeriod2HzTab[periodTab[MAX_PERIOD]])
+ if (midCFreq >= (int32_t)dGetHzFromPeriod(periodTab[MAX_PERIOD]))
{
s->fine = 127;
s->relTon = 71;
@@ -154,9 +156,10 @@
}
// check if midCFreq is matching any of the non-finetuned note frequencies (C-0..B-9)
+
for (int8_t i = 0; i < 10*12; i++)
{
- if (midCFreq == (int32_t)dPeriod2HzTab[periodTab[16 + (i<<4)]])
+ if (midCFreq == (int32_t)dGetHzFromPeriod(periodTab[16 + (i<<4)]))
{
s->fine = 0;
s->relTon = i - NOTE_C4;
@@ -169,13 +172,13 @@
int32_t period = MAX_PERIOD;
for (; period >= MIN_PERIOD; period--)
{
- const int32_t curr = (int32_t)dPeriod2HzTab[periodTab[period]];
+ const int32_t curr = (int32_t)dGetHzFromPeriod(periodTab[period]);
if (midCFreq == curr)
break;
if (midCFreq > curr)
{
- const int32_t next = (int32_t)dPeriod2HzTab[periodTab[period+1]];
+ const int32_t next = (int32_t)dGetHzFromPeriod(periodTab[period+1]);
const int32_t errorCurr = ABS(curr-midCFreq);
const int32_t errorNext = ABS(next-midCFreq);
@@ -257,27 +260,39 @@
return i+1;
}
-static void calcPeriod2HzTable(void) // called every time "linear/amiga frequency" mode is changed
+double linearPeriod2Hz(int32_t period)
{
- dPeriod2HzTab[0] = 0.0; // in FT2, a period of 0 converts to 0Hz
+ if (period == 0)
+ return 0.0; // in FT2, a period of 0 gives 0Hz
+ const uint16_t invPeriod = (uint16_t)(12 * 192 * 4) - (uint16_t)period; // this intentionally 16-bit-underflows to be accurate to FT2
+ const int32_t quotient = invPeriod / 768;
+ const int32_t remainder = invPeriod % 768;
+
+ return dLogTab[remainder] * dExp2MulTab[(14-quotient) & 31]; // x = y >> ((14-octave) & 31)
+}
+
+double amigaPeriod2Hz(int32_t period)
+{
+ if (period == 0)
+ return 0.0; // in FT2, a period of 0 gives 0Hz
+
+ return (double)(8363*1712) / period;
+}
+
+static void calcPeriod2HzTable(void) // called every time "linear/amiga frequency" mode is changed
+{
if (audio.linearPeriodsFlag)
{
// linear periods
- for (int32_t i = 1; i < 65536; i++)
- {
- const uint16_t invPeriod = (12 * 192 * 4) - (uint16_t)i; // this intentionally 16-bit-underflows to be accurate to FT2
- const int32_t octave = invPeriod / 768;
- const int32_t period = invPeriod % 768;
-
- dPeriod2HzTab[i] = dLogTab[period] * dExp2MulTab[(14-octave) & 31]; // x = y >> ((14-octave) & 31)
- }
+ for (int32_t i = 0; i < 65536; i++)
+ dPeriod2HzTab[i] = linearPeriod2Hz(i);
}
else
{
// Amiga periods
- for (int32_t i = 1; i < 65536; i++)
- dPeriod2HzTab[i] = (8363.0 * 1712.0) / i;
+ for (int32_t i = 0; i < 65536; i++)
+ dPeriod2HzTab[i] = amigaPeriod2Hz(i);
}
}
@@ -466,7 +481,7 @@
}
}
-double dPeriod2Hz(uint16_t period)
+double dPeriod2Hz(uint16_t period) // uses LUT for fast operation
{
return dPeriod2HzTab[period];
}
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -265,7 +265,11 @@
void calcRevMixDeltaTable(void);
void calcReplayerLogTab(void);
-double dPeriod2Hz(uint16_t period);
+
+double linearPeriod2Hz(int32_t period);
+double amigaPeriod2Hz(int32_t period);
+
+double dPeriod2Hz(uint16_t period); // uses LUT for fast operation
int64_t getMixerDelta(uint16_t period);
uint32_t getRevMixerDelta(uint16_t period);