mirror of https://github.com/stella-emu/stella.git
Merge branch 'master' into feature/filesystem
This commit is contained in:
commit
5be7d842ad
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
Loading…
Reference in New Issue