From 16b4a817bfb3c8e1f110d01931d52e31de5692f2 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 6 Nov 2022 21:34:50 -0800 Subject: Sync reSIDfp with upstream --- src/libs/residfp/WaveformCalculator.cpp | 120 +++++++++++++++++++------------- src/libs/residfp/WaveformGenerator.cpp | 19 ++++- src/libs/residfp/WaveformGenerator.h | 11 +-- src/libs/residfp/resample/test.cpp | 2 +- 4 files changed, 95 insertions(+), 57 deletions(-) diff --git a/src/libs/residfp/WaveformCalculator.cpp b/src/libs/residfp/WaveformCalculator.cpp index 01bf27197..8f047cf2d 100644 --- a/src/libs/residfp/WaveformCalculator.cpp +++ b/src/libs/residfp/WaveformCalculator.cpp @@ -1,7 +1,7 @@ /* * This file is part of libsidplayfp, a SID player engine. * - * Copyright 2011-2016 Leandro Nini + * Copyright 2011-2022 Leandro Nini * Copyright 2007-2010 Antti Lankila * * This program is free software; you can redistribute it and/or modify @@ -46,19 +46,37 @@ WaveformCalculator* WaveformCalculator::getInstance() const CombinedWaveformConfig config[2][4] = { { /* kevtris chip G (6581 R2) */ - {0.90251f, 0.f, 0.f, 1.9147f, 1.6747f, 0.62376f }, // error 1689 (280) - {0.93088f, 2.4843f, 0.f, 1.0353f, 1.1484f, 0.f }, // error 6128 (130) - {0.90988f, 2.26303f, 1.13126f, 1.0035f, 1.13801f, 0.f }, // error 14243 (632) - {0.91f, 1.192f, 0.f, 1.0169f, 1.2f, 0.637f }, // error 64 (2) + {0.90522f, 0.f, 0.f, 1.97506f, 1.66937f, 0.63482f }, // error 1687 (278) + {0.93088f, 2.4843f, 0.f, 1.0353f, 1.1484f, 0.f }, // error 6128 (130) + {0.912142f, 2.32076f, 1.106015f, 0.053906f, 0.25143f, 0.f }, // error 10567 (567) + {0.901f, 1.0845f, 0.f, 1.056f, 1.1848f, 0.599f }, // error 36 (12) }, { /* kevtris chip V (8580 R5) */ - {0.9632f, 0.f, 0.975f, 1.7467f, 2.36132f, 0.975395f}, // error 1380 (169) - {0.92886f, 1.67696f, 0.f, 1.1014f, 1.4352f, 0.f }, // error 8007 (218) - {0.94043f, 1.7937f, 0.981f, 1.1213f, 1.4259f, 0.f }, // error 11957 (362) - {0.96211f, 0.98695f, 1.00387f, 1.46499f, 1.98375f, 0.77777f }, // error 2369 (89) + {0.94344f, 0.f, 0.976f, 1.6347f, 2.51537f, 0.73115f }, // error 1300 (184) + {0.93303f, 1.7025f, 0.f, 1.0868f, 1.43527f, 0.f }, // error 7981 (204) + {0.95831f, 1.95269f, 0.992986f, 0.0077384f, 0.18408f, 0.f }, // error 9596 (324) + {0.94699f, 1.09668f, 0.99586f, 0.94167f, 2.0139f, 0.5633f }, // error 2118 (54) }, }; +typedef float (*distance_t)(float, int); + +// Distance functions +static float exponentialDistance(float distance, int i) +{ + return powf(distance, -i); +} + +static float linearDistance(float distance, int i) +{ + return 1.f / (1.f + i * distance); +} + +static float quadraticDistance(float distance, int i) +{ + return 1.f / (1.f + (i*i) * distance); +} + /** * Generate bitstate based on emulation of combined waves. * @@ -66,7 +84,7 @@ const CombinedWaveformConfig config[2][4] = * @param waveform the waveform to emulate, 1 .. 7 * @param accumulator the high bits of the accumulator value */ -short calculateCombinedWaveform(const CombinedWaveformConfig& config, int waveform, int accumulator) +short calculateCombinedWaveform(const CombinedWaveformConfig& config, int waveform, int accumulator, bool is8580) { float o[12]; @@ -76,8 +94,8 @@ short calculateCombinedWaveform(const CombinedWaveformConfig& config, int wavefo o[i] = (accumulator & (1 << i)) != 0 ? 1.f : 0.f; } - // convert to Triangle - if ((waveform & 3) == 1) + // If Saw is not selected the bits are XORed + if ((waveform & 2) == 0) { const bool top = (accumulator & 0x800) != 0; @@ -89,7 +107,7 @@ short calculateCombinedWaveform(const CombinedWaveformConfig& config, int wavefo o[0] = 0.f; } - // or to Saw+Triangle + // If both Saw and Triangle are selected the bits are interconnected else if ((waveform & 3) == 3) { // bottom bit is grounded via T waveform selector @@ -116,47 +134,49 @@ short calculateCombinedWaveform(const CombinedWaveformConfig& config, int wavefo } // ST, P* waveforms - if (waveform == 3 || waveform > 4) + + const distance_t distFunc = + (waveform & 1) == 1 ? exponentialDistance : is8580 ? quadraticDistance : linearDistance; + + float distancetable[12 * 2 + 1]; + distancetable[12] = 1.f; + for (int i = 12; i > 0; i--) { - float distancetable[12 * 2 + 1]; - distancetable[12] = 1.f; - for (int i = 12; i > 0; i--) - { - distancetable[12-i] = 1.0f / powf(config.distance1, static_cast(i)); // all floats - distancetable[12+i] = 1.0f / powf(config.distance2, static_cast(i)); // all floats - } + distancetable[12-i] = distFunc(config.distance1, i); + distancetable[12+i] = distFunc(config.distance2, i); + } + + float tmp[12]; - float tmp[12]; + for (int i = 0; i < 12; i++) + { + float avg = 0.f; + float n = 0.f; - for (int i = 0; i < 12; i++) + for (int j = 0; j < 12; j++) { - float avg = 0.f; - float n = 0.f; - - for (int j = 0; j < 12; j++) - { - const float weight = distancetable[i - j + 12]; - avg += o[j] * weight; - n += weight; - } - - // pulse control bit - if (waveform > 4) - { - const float weight = distancetable[i - 12 + 12]; - avg += config.pulsestrength * weight; - n += weight; - } - - tmp[i] = (o[i] + avg / n) * 0.5f; + const float weight = distancetable[i - j + 12]; + avg += o[j] * weight; + n += weight; } - for (int i = 0; i < 12; i++) + // pulse control bit + if (waveform > 4) { - o[i] = tmp[i]; + const float weight = distancetable[i - 12 + 12]; + avg += config.pulsestrength * weight; + n += weight; } + + tmp[i] = (o[i] + avg / n) * 0.5f; } + for (int i = 0; i < 12; i++) + { + o[i] = tmp[i]; + } + + // Get the predicted value short value = 0; for (unsigned int i = 0; i < 12; i++) @@ -172,7 +192,9 @@ short calculateCombinedWaveform(const CombinedWaveformConfig& config, int wavefo matrix_t* WaveformCalculator::buildTable(ChipModel model) { - const CombinedWaveformConfig* cfgArray = config[model == MOS6581 ? 0 : 1]; + const bool is8580 = model != MOS6581; + + const CombinedWaveformConfig* cfgArray = config[is8580 ? 1 : 0]; cw_cache_t::iterator lb = CACHE.lower_bound(cfgArray); @@ -188,11 +210,11 @@ matrix_t* WaveformCalculator::buildTable(ChipModel model) wftable[0][idx] = 0xfff; wftable[1][idx] = static_cast((idx & 0x800) == 0 ? idx << 1 : (idx ^ 0xfff) << 1); wftable[2][idx] = static_cast(idx); - wftable[3][idx] = calculateCombinedWaveform(cfgArray[0], 3, idx); + wftable[3][idx] = calculateCombinedWaveform(cfgArray[0], 3, idx, is8580); wftable[4][idx] = 0xfff; - wftable[5][idx] = calculateCombinedWaveform(cfgArray[1], 5, idx); - wftable[6][idx] = calculateCombinedWaveform(cfgArray[2], 6, idx); - wftable[7][idx] = calculateCombinedWaveform(cfgArray[3], 7, idx); + wftable[5][idx] = calculateCombinedWaveform(cfgArray[1], 5, idx, is8580); + wftable[6][idx] = calculateCombinedWaveform(cfgArray[2], 6, idx, is8580); + wftable[7][idx] = calculateCombinedWaveform(cfgArray[3], 7, idx, is8580); } #ifdef HAVE_CXX11 return &(CACHE.emplace_hint(lb, cw_cache_t::value_type(cfgArray, wftable))->second); diff --git a/src/libs/residfp/WaveformGenerator.cpp b/src/libs/residfp/WaveformGenerator.cpp index c97114b0e..21beffa9e 100644 --- a/src/libs/residfp/WaveformGenerator.cpp +++ b/src/libs/residfp/WaveformGenerator.cpp @@ -1,7 +1,7 @@ /* * This file is part of libsidplayfp, a SID player engine. * - * Copyright 2011-2021 Leandro Nini + * Copyright 2011-2022 Leandro Nini * Copyright 2007-2010 Antti Lankila * Copyright 2004 Dag Lem * @@ -83,7 +83,7 @@ const unsigned int SHIFT_REGISTER_FADE_8580R5 = 314300; * This is what happens when the lfsr is clocked: * * cycle 0: bit 19 of the accumulator goes from low to high, the noise register acts normally, - * the output may overwrite a bit; + * the output may pulldown a bit; * * cycle 1: first phase of the shift, the bits are interconnected and the output of each bit * is latched into the following. The output may overwrite the latched value. @@ -93,6 +93,21 @@ const unsigned int SHIFT_REGISTER_FADE_8580R5 = 314300; * * When the test or reset lines are active the first phase is executed at every cyle * until the signal is released triggering the second phase. + * + * | | bit n | bit n+1 + * | bit19 | latch output | latch output + * -----+-------+--------------+-------------- + * phi1 | 0 | A <-> A | B <-> B + * phi2 | 0 | A <-> A | B <-> B + * -----+-------+--------------+-------------- + * phi1 | 1 | A <-> A | B <-> B <- bit19 raises + * phi2 | 1 | A <-> A | B <-> B + * -----+-------+--------------+-------------- + * phi1 | 1 | X A --|-> A B <- shift phase 1 + * phi2 | 1 | X A --|-> A B + * -----+-------+--------------+-------------- + * phi1 | 1 | X --> X | A --> A <- shift phase 2 + * phi2 | 1 | X <-> X | A <-> A */ void WaveformGenerator::clock_shift_register(unsigned int bit0) { diff --git a/src/libs/residfp/WaveformGenerator.h b/src/libs/residfp/WaveformGenerator.h index 66dde8302..9e139cd18 100644 --- a/src/libs/residfp/WaveformGenerator.h +++ b/src/libs/residfp/WaveformGenerator.h @@ -1,7 +1,7 @@ /* * This file is part of libsidplayfp, a SID player engine. * - * Copyright 2011-2016 Leandro Nini + * Copyright 2011-2022 Leandro Nini * Copyright 2007-2010 Antti Lankila * Copyright 2004,2010 Dag Lem * @@ -307,7 +307,7 @@ void WaveformGenerator::clock() const unsigned int accumulator_old = accumulator; accumulator = (accumulator + freq) & 0xffffff; - // Check which bit have changed + // Check which bit have changed from low to high const unsigned int accumulator_bits_set = ~accumulator_old & accumulator; // Check whether the MSB is set high. This is used for synchronization. @@ -354,9 +354,10 @@ unsigned int WaveformGenerator::output(const WaveformGenerator* ringModulator) // In the 6581 the top bit of the accumulator may be driven low by combined waveforms // when the sawtooth is selected - // FIXME doesn't seem to always happen - if ((waveform & 2) && unlikely(waveform & 0xd) && is6581) - accumulator &= (waveform_output << 12) | 0x7fffff; + if (is6581 + && (waveform & 0x2) + && ((waveform_output & 0x800) == 0)) + accumulator &= 0x7fffff; write_shift_register(); } diff --git a/src/libs/residfp/resample/test.cpp b/src/libs/residfp/resample/test.cpp index a1dde18e2..bd90686d7 100644 --- a/src/libs/residfp/resample/test.cpp +++ b/src/libs/residfp/resample/test.cpp @@ -40,7 +40,7 @@ int main(int argc, const char* argv[]) const double RATE = 985248.4; const int RINGSIZE = 2048; - std::auto_ptr r(reSIDfp::TwoPassSincResampler::create(RATE, 48000.0, 20000.0)); + std::unique_ptr r(reSIDfp::TwoPassSincResampler::create(RATE, 48000.0, 20000.0)); std::map results; clock_t start = clock(); -- cgit v1.2.3