From c7cac63a384bf096aad41d6d5c3df2252c22d81b Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Sat, 3 Sep 2022 20:56:38 +0200 Subject: [PATCH] added WAV file volume adjustment (resolves #77) --- src/common/SoundSDL2.cxx | 41 +++++++++++++++++++++++++++++++--------- src/common/SoundSDL2.hxx | 10 ++++++++-- src/emucore/KidVid.cxx | 15 +++++++++++---- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/common/SoundSDL2.cxx b/src/common/SoundSDL2.cxx index 4b619566f..f7b3e256e 100644 --- a/src/common/SoundSDL2.cxx +++ b/src/common/SoundSDL2.cxx @@ -405,17 +405,13 @@ void SoundSDL2::callback(void* udata, uInt8* stream, int len) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool SoundSDL2::playWav(const char* fileName, uInt32 position, uInt32 length) { - // ToDos: - // - volume (requires callback using SDL_MixAudio) - // - (un)mute - SDL_AudioSpec wavSpec; uInt32 wavLength{0}; // Stop any playing WAVs stopWav(); // Load WAV file - SDL_AudioSpec* result = SDL_LoadWAV(fileName, &wavSpec, &myWavBuffer, &wavLength); + SDL_AudioSpec* result = SDL_LoadWAV(fileName, &myWavSpec, &myWavBuffer, &wavLength); if(result == nullptr || position > wavLength) return false; @@ -423,18 +419,24 @@ bool SoundSDL2::playWav(const char* fileName, uInt32 position, uInt32 length) ? std::min(length, wavLength - position) : wavLength; + // Set the callback function + myWavSpec.callback = wavCallback; + myWavSpec.userdata = nullptr; + + myWavPos = myWavBuffer + position; + myWavLen = length; + // Open audio device const char* device = myDeviceId ? myDevices.at(myDeviceId).first.c_str() : nullptr; - myWavDevice = SDL_OpenAudioDevice(device, 0, &wavSpec, nullptr, 0); + myWavDevice = SDL_OpenAudioDevice(device, 0, &myWavSpec, nullptr, 0); if(!myWavDevice) return false; // Play audio - int success = SDL_QueueAudio(myWavDevice, myWavBuffer + position, length); SDL_PauseAudioDevice(myWavDevice, 0); - return success == 0; + return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -452,7 +454,28 @@ void SoundSDL2::stopWav() uInt32 SoundSDL2::wavSize() const { - return myWavBuffer ? SDL_GetQueuedAudioSize(myWavDevice) : 0; + return myWavBuffer ? myWavLen /*SDL_GetQueuedAudioSize(myWavDevice)*/ : 0; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundSDL2::wavCallback(void* udata, uInt8* stream, int len) +{ + SDL_memset(stream, myWavSpec.silence, len); + if(myWavLen) + { + if(static_cast(len) > myWavLen) + len = myWavLen; + // Mix volume adjusted WAV into silent buffer + SDL_MixAudioFormat(stream, myWavPos, myWavSpec.format, len, + SDL_MIX_MAXVOLUME * myVolumeFactor); + myWavPos += len; + myWavLen -= len; + } +} + +float SoundSDL2::myVolumeFactor = 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 + #endif // SOUND_SUPPORT diff --git a/src/common/SoundSDL2.hxx b/src/common/SoundSDL2.hxx index 20a58429a..567dd08ad 100644 --- a/src/common/SoundSDL2.hxx +++ b/src/common/SoundSDL2.hxx @@ -164,7 +164,7 @@ class SoundSDL2 : public Sound // Current volume as a percentage (0 - 100) uInt32 myVolume{100}; - float myVolumeFactor{0xffff}; + static float myVolumeFactor; // Audio specification structure SDL_AudioSpec myHardwareSpec; @@ -184,14 +184,20 @@ class SoundSDL2 : public Sound AudioSettings& myAudioSettings; + // WAV file sound variables SDL_AudioDeviceID myWavDevice{0}; uInt8* myWavBuffer{nullptr}; + static SDL_AudioSpec myWavSpec; // audio output format + static uInt8* myWavPos; // pointer to the audio buffer to be played + static uInt32 myWavLen; // remaining length of the sample we have to play + string myAboutString; private: - // Callback function invoked by the SDL Audio library when it needs data + // Callback functions invoked by the SDL Audio library when it needs data static void callback(void* udata, uInt8* stream, int len); + static void wavCallback(void* udata, uInt8* stream, int len); // Following constructors and assignment operators not supported SoundSDL2() = delete; diff --git a/src/emucore/KidVid.cxx b/src/emucore/KidVid.cxx index 9d4a6e137..351cee40c 100644 --- a/src/emucore/KidVid.cxx +++ b/src/emucore/KidVid.cxx @@ -162,14 +162,17 @@ void KidVid::openSampleFiles() mySampleFile = myBaseDir + fileNames[i]; std::ifstream f1, f2; - f1.open(mySampleFile, std::ios::binary); - f2.open(myBaseDir + "KVSHARED.WAV", std::ios::binary); + f1.open(mySampleFile); + f2.open(myBaseDir + "KVSHARED.WAV"); myFilesFound = f1.is_open() && f2.is_open(); +#ifdef DEBUG_BUILD if(myFilesFound) - cerr << "found file: " << fileNames[i] << endl + cerr << endl + << "found file: " << fileNames[i] << endl << "found file: " << "KVSHARED.WAV" << endl; +#endif mySongLength = 0; mySongPointer = firstSongPointer[i]; @@ -185,11 +188,15 @@ void KidVid::setNextSong() myBeep = (ourSongPositions[mySongPointer] & 0x80) == 0; const uInt8 temp = ourSongPositions[mySongPointer] & 0x7f; - mySongLength = ourSongStart[temp+1] - ourSongStart[temp]; + mySongLength = ourSongStart[temp + 1] - ourSongStart[temp]; // Play the WAV file const string fileName = (temp < 10) ? myBaseDir + "KVSHARED.WAV" : mySampleFile; mySound.playWav(fileName.c_str(), ourSongStart[temp], mySongLength); +#ifdef DEBUG_BUILD + cerr << fileName << ": " << (ourSongPositions[mySongPointer] & 0x7f) << endl; +#endif + mySongPlaying = myTapeBusy = true; ++mySongPointer;