From 26d6f0db696c8d5ba30d91539485860942a29df3 Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Thu, 15 Sep 2022 15:21:10 +0200 Subject: [PATCH] added on-the-fly WAV resampling (disabled, causes echo) --- src/common/SoundSDL2.cxx | 45 +++++++++++++++++++++++++++++++++++----- src/common/SoundSDL2.hxx | 6 +++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/common/SoundSDL2.cxx b/src/common/SoundSDL2.cxx index 89ae72e7d..43354beb2 100644 --- a/src/common/SoundSDL2.cxx +++ b/src/common/SoundSDL2.cxx @@ -175,6 +175,9 @@ void SoundSDL2::open(shared_ptr audioQueue, openDevice(); myEmulationTiming = emulationTiming; +#ifdef RESAMPLE_WAV_CB + myWavSpeed = 262 * 60 * 2. / myEmulationTiming->audioSampleRate(); +#endif Logger::debug("SoundSDL2::open started ..."); mute(true); @@ -504,12 +507,41 @@ void SoundSDL2::wavCallback(void* udata, uInt8* stream, int len) SDL_memset(stream, myWavSpec.silence, len); if(myWavLen) { - if(static_cast(len) > myWavLen) - len = myWavLen; +#ifdef RESAMPLE_WAV_CB + if(myWavSpeed != 1.0) + { + int newLen = std::round(len / myWavSpeed); + const int newFreq = std::round(static_cast(myWavSpec.freq) * len / newLen); - // Mix volume adjusted WAV data into silent buffer - SDL_MixAudioFormat(stream, myWavPos, myWavSpec.format, len, - SDL_MIX_MAXVOLUME * myWavVolumeFactor); + if(static_cast(newLen) > myWavLen) + newLen = myWavLen; + + SDL_AudioCVT cvt; + SDL_BuildAudioCVT(&cvt, myWavSpec.format, myWavSpec.channels, myWavSpec.freq, + myWavSpec.format, myWavSpec.channels, newFreq); + SDL_assert(cvt.needed); // Obviously, this one is always needed. + cvt.len = newLen * myWavSpec.channels; // Mono 8 bit sample frames + cvt.buf = static_cast(SDL_malloc(cvt.len * cvt.len_mult * 2)); // Double buffer size to avoid memory access exception + // Read original data into conversion buffer + SDL_memcpy(cvt.buf, myWavPos, cvt.len); + SDL_ConvertAudio(&cvt); + // Mix volume adjusted WAV data into silent buffer + SDL_MixAudioFormat(stream, cvt.buf, myWavSpec.format, cvt.len_cvt, + SDL_MIX_MAXVOLUME * myWavVolumeFactor); + SDL_free(cvt.buf); + + cerr << cvt.len_cvt << " "; + } + else +#endif + { + if(static_cast(len) > myWavLen) + len = myWavLen; + + // Mix volume adjusted WAV data into silent buffer + SDL_MixAudioFormat(stream, myWavPos, myWavSpec.format, len, + SDL_MIX_MAXVOLUME * myWavVolumeFactor); + } myWavPos += len; myWavLen -= len; } @@ -520,5 +552,8 @@ float SoundSDL2::myWavVolumeFactor = 0xffff; SDL_AudioSpec SoundSDL2::myWavSpec; // audio output format uInt8* SoundSDL2::myWavPos = nullptr; // pointer to the audio buffer to be played uInt32 SoundSDL2::myWavLen = 0; // remaining length of the sample we have to play +#ifdef RESAMPLE_WAV_CB +double SoundSDL2::myWavSpeed = 1.0; +#endif #endif // SOUND_SUPPORT diff --git a/src/common/SoundSDL2.hxx b/src/common/SoundSDL2.hxx index 7b5bdf673..c42238113 100644 --- a/src/common/SoundSDL2.hxx +++ b/src/common/SoundSDL2.hxx @@ -20,7 +20,8 @@ #ifndef SOUND_SDL2_HXX #define SOUND_SDL2_HXX -//#define RESAMPLE_WAV +//#define RESAMPLE_WAV // does not adjust to speed immediately +//#define RESAMPLE_WAV_CB // causes echo in in-the-fly resampling class OSystem; class AudioQueue; @@ -197,6 +198,9 @@ class SoundSDL2 : public Sound #ifdef RESAMPLE_WAV SDL_AudioCVT myCvt{0}; #endif +#ifdef RESAMPLE_WAV_CB + static double myWavSpeed; +#endif static float myWavVolumeFactor; static SDL_AudioSpec myWavSpec; // audio output format