Merge branch 'master' into feature/filesystem

This commit is contained in:
Stephen Anthony 2022-09-19 14:12:46 -02:30
commit 5be7d842ad
3 changed files with 79 additions and 13 deletions

View File

@ -64,6 +64,8 @@ SoundSDL2::SoundSDL2(OSystem& osystem, AudioSettings& audioSettings)
return; return;
SoundSDL2::mute(true); SoundSDL2::mute(true);
myMuteState = !audioSettings.enabled();
myWavVolumeFactor = myMuteState ? 0 : myVolumeFactor;
Logger::debug("SoundSDL2::SoundSDL2 initialized"); Logger::debug("SoundSDL2::SoundSDL2 initialized");
} }
@ -151,6 +153,10 @@ void SoundSDL2::setEnabled(bool enable)
if(myAudioQueue) if(myAudioQueue)
myAudioQueue->ignoreOverflows(!enable); myAudioQueue->ignoreOverflows(!enable);
// Set new mute state and resulting WAV data volume
myMuteState = !enable;
myWavVolumeFactor = myMuteState ? 0 : myVolumeFactor;
Logger::debug(enable ? "SoundSDL2::setEnabled(true)" : Logger::debug(enable ? "SoundSDL2::setEnabled(true)" :
"SoundSDL2::setEnabled(false)"); "SoundSDL2::setEnabled(false)");
} }
@ -169,6 +175,7 @@ void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
openDevice(); openDevice();
myEmulationTiming = emulationTiming; myEmulationTiming = emulationTiming;
myWavSpeed = 262 * 60 * 2. / myEmulationTiming->audioSampleRate();
Logger::debug("SoundSDL2::open started ..."); Logger::debug("SoundSDL2::open started ...");
mute(true); mute(true);
@ -195,7 +202,7 @@ void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
Logger::info(myAboutString); Logger::info(myAboutString);
// And start the SDL sound subsystem ... // And start the SDL sound subsystem ...
mute(false); mute(myMuteState);
Logger::debug("SoundSDL2::open finished"); Logger::debug("SoundSDL2::open finished");
} }
@ -203,11 +210,11 @@ void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL2::close() void SoundSDL2::close()
{ {
stopWav();
if(!myIsInitializedFlag) if(!myIsInitializedFlag)
return; return;
mute(true); // Mute and remember current mute state for 'open()'
myMuteState = mute(true);
if(myAudioQueue) if(myAudioQueue)
myAudioQueue->closeSink(myCurrentFragment); myAudioQueue->closeSink(myCurrentFragment);
@ -235,6 +242,13 @@ bool SoundSDL2::toggleMute()
setEnabled(enabled); setEnabled(enabled);
myOSystem.console().initializeAudio(); myOSystem.console().initializeAudio();
// Adjust TIA sound to new mute state
myMuteState = !enabled;
mute(myMuteState);
// Make sure the current WAV file continues playing if it got stopped by 'mute()'
if(myWavDevice)
SDL_PauseAudioDevice(myWavDevice, 0);
string message = "Sound "; string message = "Sound ";
message += enabled ? "unmuted" : "muted"; message += enabled ? "unmuted" : "muted";
@ -253,6 +267,7 @@ void SoundSDL2::setVolume(uInt32 percent)
SDL_LockAudioDevice(myDevice); SDL_LockAudioDevice(myDevice);
myVolumeFactor = static_cast<float>(percent) / 100.F; myVolumeFactor = static_cast<float>(percent) / 100.F;
myWavVolumeFactor = myAudioSettings.enabled() ? myVolumeFactor : 0;
SDL_UnlockAudioDevice(myDevice); SDL_UnlockAudioDevice(myDevice);
} }
} }
@ -263,16 +278,17 @@ void SoundSDL2::adjustVolume(int direction)
Int32 percent = myVolume; Int32 percent = myVolume;
percent = BSPF::clamp(percent + direction * 2, 0, 100); percent = BSPF::clamp(percent + direction * 2, 0, 100);
setVolume(percent);
// Enable audio if it is currently disabled // Enable audio if it is currently disabled
const bool enabled = myAudioSettings.enabled(); const bool enabled = myAudioSettings.enabled();
if(percent > 0 && !enabled) if(percent > 0 && direction && !enabled)
{ {
setEnabled(true); setEnabled(true);
myOSystem.console().initializeAudio(); myOSystem.console().initializeAudio();
myMuteState = false;
mute(false);
} }
setVolume(percent);
// Now show an onscreen message // Now show an onscreen message
ostringstream strval; ostringstream strval;
@ -418,6 +434,7 @@ bool SoundSDL2::playWav(const string& fileName, const uInt32 position,
// Set the callback function // Set the callback function
myWavSpec.callback = wavCallback; myWavSpec.callback = wavCallback;
myWavSpec.userdata = nullptr; myWavSpec.userdata = nullptr;
//myWavSpec.samples = 4096; // decrease for smaller samples;
} }
if(position > myWavLength) if(position > myWavLength)
return false; return false;
@ -455,6 +472,11 @@ void SoundSDL2::stopWav()
SDL_FreeWAV(myWavBuffer); SDL_FreeWAV(myWavBuffer);
myWavBuffer = nullptr; myWavBuffer = nullptr;
} }
if(myWavCvtBuffer)
{
myWavCvtBuffer.reset();
myWavCvtBufferSize = 0;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -469,21 +491,58 @@ void SoundSDL2::wavCallback(void* udata, uInt8* stream, int len)
SDL_memset(stream, myWavSpec.silence, len); SDL_memset(stream, myWavSpec.silence, len);
if(myWavLen) if(myWavLen)
{ {
if(static_cast<uInt32>(len) > myWavLen) if(myWavSpeed != 1.0)
len = myWavLen; {
const int origLen = len;
len = std::round(len / myWavSpeed);
const int newFreq =
std::round(static_cast<double>(myWavSpec.freq) * origLen / len);
// Mix volume adjusted WAV into silent buffer if(static_cast<uInt32>(len) > myWavLen)
SDL_MixAudioFormat(stream, myWavPos, myWavSpec.format, len, len = myWavLen;
SDL_MIX_MAXVOLUME * myVolumeFactor);
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 = len * myWavSpec.channels; // Mono 8 bit sample frames
if(!myWavCvtBuffer ||
myWavCvtBufferSize < static_cast<uInt32>(cvt.len * cvt.len_mult))
{
myWavCvtBufferSize = cvt.len * cvt.len_mult;
myWavCvtBuffer = make_unique<uInt8[]>(myWavCvtBufferSize);
}
cvt.buf = myWavCvtBuffer.get();
// 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);
}
else
{
if(static_cast<uInt32>(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; myWavPos += len;
myWavLen -= len; myWavLen -= len;
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float SoundSDL2::myVolumeFactor = 0xffff; float SoundSDL2::myWavVolumeFactor = 0xffff;
SDL_AudioSpec SoundSDL2::myWavSpec; // audio output format SDL_AudioSpec SoundSDL2::myWavSpec; // audio output format
uInt8* SoundSDL2::myWavPos = nullptr; // pointer to the audio buffer to be played 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 uInt32 SoundSDL2::myWavLen = 0; // remaining length of the sample we have to play
double SoundSDL2::myWavSpeed = 1.0;
unique_ptr<uInt8[]> SoundSDL2::myWavCvtBuffer;
uInt32 SoundSDL2::myWavCvtBufferSize = 0;
#endif // SOUND_SUPPORT #endif // SOUND_SUPPORT

View File

@ -165,7 +165,9 @@ class SoundSDL2 : public Sound
// Current volume as a percentage (0 - 100) // Current volume as a percentage (0 - 100)
uInt32 myVolume{100}; uInt32 myVolume{100};
static float myVolumeFactor; float myVolumeFactor{0xffff};
// Current mute state, used to control WAV file sound
bool myMuteState{false};
// Audio specification structure // Audio specification structure
SDL_AudioSpec myHardwareSpec; SDL_AudioSpec myHardwareSpec;
@ -191,6 +193,10 @@ class SoundSDL2 : public Sound
SDL_AudioDeviceID myWavDevice{0}; SDL_AudioDeviceID myWavDevice{0};
uInt8* myWavBuffer{nullptr}; uInt8* myWavBuffer{nullptr};
static double myWavSpeed;
static unique_ptr<uInt8[]> myWavCvtBuffer;
static uInt32 myWavCvtBufferSize;
static float myWavVolumeFactor;
static SDL_AudioSpec myWavSpec; // audio output format static SDL_AudioSpec myWavSpec; // audio output format
static uInt8* myWavPos; // pointer to the audio buffer to be played static uInt8* myWavPos; // pointer to the audio buffer to be played
static uInt32 myWavLen; // remaining length of the sample we have to play static uInt32 myWavLen; // remaining length of the sample we have to play

View File

@ -253,6 +253,7 @@ Console::~Console()
// Close audio to prevent invalid access to myConsoleTiming from the audio // Close audio to prevent invalid access to myConsoleTiming from the audio
// callback // callback
myOSystem.sound().close(); myOSystem.sound().close();
myOSystem.sound().stopWav();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -