From 22d11bbae088d290a2a61ca9695d73a7253297ee Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 14 Aug 2022 19:00:33 +0100 Subject: [PATCH] WIP: Spkr: revert to 41000Hz . try some simple ramping . start with SPKR_DATA_INIT = 0x7FFF + support 88200Hz (via CPP macro) + add Spkr_GetSampleRate() for AppleWin.cpp --- source/Common.h | 2 +- source/Speaker.cpp | 142 +++++++++++++++++++++++++++++++++++- source/Speaker.h | 1 + source/Windows/AppleWin.cpp | 2 +- 4 files changed, 143 insertions(+), 4 deletions(-) diff --git a/source/Common.h b/source/Common.h index 2fb8efaf..98256d9e 100644 --- a/source/Common.h +++ b/source/Common.h @@ -13,7 +13,7 @@ const double CLK_6502_PAL = (_14M_PAL * 65.0) / (65.0*14.0+2.0); // Use a base freq so that DirectX (or sound h/w) doesn't have to up/down-sample // Assume base freqs are 44.1KHz & 48KHz -const DWORD SPKR_SAMPLE_RATE = 48000; // 44100; +const DWORD SPKR_SAMPLE_RATE = 44100; enum AppMode_e { diff --git a/source/Speaker.cpp b/source/Speaker.cpp index d2115da1..75122e28 100644 --- a/source/Speaker.cpp +++ b/source/Speaker.cpp @@ -40,6 +40,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Debugger/Debug.h" // For DWORD extbench +#define FREQ_88200Hz 1 +#if FREQ_88200Hz +#define FREQ_MUL 2 +#endif + +#define DO_RAMP 1 +#if DO_RAMP +#define RAMP_DIV 4 +static short g_rampDiv = 0; +static int g_rampCount = 0; +#endif + // Notes: // // [OLD: 23.191 Apple CLKs == 44100Hz (CLK_6502/44100)] @@ -61,7 +73,7 @@ static const DWORD g_dwDSSpkrBufferSize = MAX_SAMPLES * sizeof(short) * g_nSPKR_ static short* g_pSpeakerBuffer = NULL; // Globals (SOUND_WAVE) -const short SPKR_DATA_INIT = (short)0x8001; +const short SPKR_DATA_INIT = (short)0x7FFF; short g_nSpeakerData = SPKR_DATA_INIT; static UINT g_nBufferIdx = 0; @@ -101,6 +113,15 @@ void Spkr_OutputToRiff(void) g_bSpkrOutputToRiff = true; } +unsigned int Spkr_GetSampleRate(void) +{ +#if FREQ_88200Hz + return SPKR_SAMPLE_RATE * FREQ_MUL; +#else + return SPKR_SAMPLE_RATE; +#endif +} + //============================================================================= static void DisplayBenchmarkResults () @@ -269,7 +290,11 @@ void SpkrInitialize () { InitRemainderBuffer(); +#if FREQ_88200Hz + g_pSpeakerBuffer = new short[SPKR_SAMPLE_RATE * FREQ_MUL]; // Buffer can hold a max of 1 seconds worth of samples +#else g_pSpeakerBuffer = new short [SPKR_SAMPLE_RATE]; // Buffer can hold a max of 1 seconds worth of samples +#endif } } @@ -311,6 +336,90 @@ void SpkrSetEmulationType (SoundType_e newtype) //============================================================================= +#if FREQ_88200Hz + +static void ReinitRemainderBuffer(UINT nCyclesRemaining) +{ + if (nCyclesRemaining == 0) + return; + + for (g_nRemainderBufferIdx = 0; g_nRemainderBufferIdx < nCyclesRemaining; g_nRemainderBufferIdx++) + g_pRemainderBuffer[g_nRemainderBufferIdx] = g_nSpeakerData; + + _ASSERT(g_nRemainderBufferIdx < g_nRemainderBufferSize); +} + +static void UpdateRemainderBuffer(ULONG* pnCycleDiff) +{ + if (g_nRemainderBufferIdx) + { + while ((g_nRemainderBufferIdx < g_nRemainderBufferSize) && *pnCycleDiff) + { + g_pRemainderBuffer[g_nRemainderBufferIdx] = g_nSpeakerData; + g_nRemainderBufferIdx++; + (*pnCycleDiff)--; + + if (g_rampCount) + { + int data = (int) g_nSpeakerData + (int) g_rampDiv; + if (data > SPKR_DATA_INIT) + { + data = SPKR_DATA_INIT; + g_rampCount = 0; + } + else if (data < -SPKR_DATA_INIT) + { + data = -SPKR_DATA_INIT; + g_rampCount = 0; + } + + g_nSpeakerData = (short) data; + } + } + + if (g_nRemainderBufferIdx == g_nRemainderBufferSize) + { + g_nRemainderBufferIdx = 0; + signed long nSampleMean = 0; + for (UINT i = 0; i < g_nRemainderBufferSize; i++) + nSampleMean += (signed long)g_pRemainderBuffer[i]; + signed long total = nSampleMean; + nSampleMean /= (signed long)g_nRemainderBufferSize; + + if (g_nBufferIdx < SPKR_SAMPLE_RATE - 1) + g_pSpeakerBuffer[g_nBufferIdx++] = DCFilter((short)nSampleMean); + else + _ASSERT(0); + } + } +} + +static void UpdateSpkr() +{ + if (!g_bFullSpeed || SoundCore_GetTimerState()) + { + ULONG nCycleDiff = (ULONG)(g_nCumulativeCycles - g_nSpkrLastCycle); +#if FREQ_88200Hz + nCycleDiff *= FREQ_MUL; // 88.2kHz: double sample rate +#endif + + UpdateRemainderBuffer(&nCycleDiff); + + ULONG nNumSamples = (ULONG)((double)nCycleDiff / g_fClksPerSpkrSample); + + ULONG nCyclesRemaining = (ULONG)((double)nCycleDiff - (double)nNumSamples * g_fClksPerSpkrSample); + + while ((nNumSamples--) && (g_nBufferIdx < SPKR_SAMPLE_RATE - 1)) + g_pSpeakerBuffer[g_nBufferIdx++] = DCFilter(g_nSpeakerData); + + ReinitRemainderBuffer(nCyclesRemaining); // Partially fill 1Mhz sample buffer + } + + g_nSpkrLastCycle = g_nCumulativeCycles; +} + +#else + static void ReinitRemainderBuffer(UINT nCyclesRemaining) { if(nCyclesRemaining == 0) @@ -337,6 +446,12 @@ static void UpdateRemainderBuffer(ULONG* pnCycleDiff) g_pRemainderBuffer[g_nRemainderBufferIdx] = g_nSpeakerData; g_nRemainderBufferIdx++; (*pnCycleDiff)--; + + if (g_rampCount) + { + g_nSpeakerData += g_rampDiv; + g_rampCount--; + } } if(g_nRemainderBufferIdx == g_nRemainderBufferSize) @@ -387,6 +502,8 @@ static void UpdateSpkr() g_nSpkrLastCycle = g_nCumulativeCycles; } +#endif + //============================================================================= // Called by emulation code when Speaker I/O reg is accessed @@ -422,10 +539,27 @@ BYTE __stdcall SpkrToggle (WORD, WORD, BYTE, BYTE, ULONG nExecutedCycles) if (!g_bFullSpeed) ResetDCFilter(); - if (g_nSpeakerData == speakerDriveLevel) +#if 0 + // This immediately flips from +N to -N/RAMP_DIV + // - When a change in voltage should just start stepping in the opposite direction + if (g_nSpeakerData < 0) g_nSpeakerData = -speakerDriveLevel; else g_nSpeakerData = speakerDriveLevel; +#if DO_RAMP + g_nSpeakerData /= RAMP_DIV; + g_rampDiv = g_nSpeakerData; + g_rampCount = 1; +#endif +#else + if (g_nSpeakerData > 0) + speakerDriveLevel = -speakerDriveLevel; +#if DO_RAMP + g_rampDiv = speakerDriveLevel / RAMP_DIV; + g_rampCount = 1; +#endif +#endif + } return MemReadFloatingBus(nExecutedCycles); @@ -920,7 +1054,11 @@ bool Spkr_DSInit() SpeakerVoice.bIsSpeaker = true; +#if FREQ_88200Hz + HRESULT hr = DSGetSoundBuffer(&SpeakerVoice, DSBCAPS_CTRLVOLUME, g_dwDSSpkrBufferSize, SPKR_SAMPLE_RATE * FREQ_MUL, 1, "Spkr"); +#else HRESULT hr = DSGetSoundBuffer(&SpeakerVoice, DSBCAPS_CTRLVOLUME, g_dwDSSpkrBufferSize, SPKR_SAMPLE_RATE, 1, "Spkr"); +#endif if (FAILED(hr)) { LogFileOutput("Spkr_DSInit: DSGetSoundBuffer failed (%08X)\n", hr); diff --git a/source/Speaker.h b/source/Speaker.h index 013ff618..f09de24a 100644 --- a/source/Speaker.h +++ b/source/Speaker.h @@ -31,6 +31,7 @@ void Spkr_Unmute(); bool Spkr_IsActive(); bool Spkr_DSInit(); void Spkr_OutputToRiff(void); +unsigned int Spkr_GetSampleRate(void); void SpkrSaveSnapshot(class YamlSaveHelper& yamlSaveHelper); void SpkrLoadSnapshot(class YamlLoadHelper& yamlLoadHelper); diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp index 75f56598..589ed759 100644 --- a/source/Windows/AppleWin.cpp +++ b/source/Windows/AppleWin.cpp @@ -620,7 +620,7 @@ static void OneTimeInitialization(HINSTANCE passinstance) // Currently only support one RIFF file if (!g_cmdLine.wavFileSpeaker.empty()) { - if (RiffInitWriteFile(g_cmdLine.wavFileSpeaker.c_str(), SPKR_SAMPLE_RATE, 1)) + if (RiffInitWriteFile(g_cmdLine.wavFileSpeaker.c_str(), Spkr_GetSampleRate(), 1)) Spkr_OutputToRiff(); } else if (!g_cmdLine.wavFileMockingboard.empty())