mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Implemented a stable solution to video stream muting and clearing.
This commit is contained in:
parent
17fec1aac7
commit
c91662befa
|
@ -19,7 +19,9 @@ std::vector<std::shared_ptr<Sound>> AudioManager::sSoundVector;
|
||||||
SDL_AudioDeviceID AudioManager::sAudioDevice = 0;
|
SDL_AudioDeviceID AudioManager::sAudioDevice = 0;
|
||||||
SDL_AudioSpec AudioManager::sAudioFormat;
|
SDL_AudioSpec AudioManager::sAudioFormat;
|
||||||
SDL_AudioStream* AudioManager::sConversionStream;
|
SDL_AudioStream* AudioManager::sConversionStream;
|
||||||
|
bool AudioManager::sMuteStream = false;
|
||||||
bool AudioManager::sHasAudioDevice = true;
|
bool AudioManager::sHasAudioDevice = true;
|
||||||
|
bool AudioManager::mIsClearingStream = false;
|
||||||
|
|
||||||
AudioManager::AudioManager()
|
AudioManager::AudioManager()
|
||||||
{
|
{
|
||||||
|
@ -115,8 +117,6 @@ void AudioManager::init()
|
||||||
if (Settings::getInstance()->getInt("SoundVolumeVideos") < 0)
|
if (Settings::getInstance()->getInt("SoundVolumeVideos") < 0)
|
||||||
Settings::getInstance()->setInt("SoundVolumeVideos", 0);
|
Settings::getInstance()->setInt("SoundVolumeVideos", 0);
|
||||||
|
|
||||||
// Use the default sample rate initially, this will possibly be changed by the
|
|
||||||
// video player when a video is started.
|
|
||||||
setupAudioStream(sRequestedAudioFormat.freq);
|
setupAudioStream(sRequestedAudioFormat.freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,10 +163,13 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
||||||
soundIt++;
|
soundIt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process video stream audio generated by VideoFFmpegComponent.
|
int streamLength = 0;
|
||||||
int streamLength = SDL_AudioStreamAvailable(sConversionStream);
|
|
||||||
|
|
||||||
if (streamLength == 0) {
|
// Process video stream audio generated by VideoFFmpegComponent.
|
||||||
|
if (!mIsClearingStream)
|
||||||
|
streamLength = SDL_AudioStreamAvailable(sConversionStream);
|
||||||
|
|
||||||
|
if (streamLength <= 0 || mIsClearingStream) {
|
||||||
// If nothing is playing, pause the device until there is more audio to output.
|
// If nothing is playing, pause the device until there is more audio to output.
|
||||||
if (!stillPlaying)
|
if (!stillPlaying)
|
||||||
SDL_PauseAudioDevice(sAudioDevice, 1);
|
SDL_PauseAudioDevice(sAudioDevice, 1);
|
||||||
|
@ -186,7 +189,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
||||||
int processedLength = SDL_AudioStreamGet(sConversionStream,
|
int processedLength = SDL_AudioStreamGet(sConversionStream,
|
||||||
static_cast<void*>(&converted.at(0)), chunkLength);
|
static_cast<void*>(&converted.at(0)), chunkLength);
|
||||||
|
|
||||||
if (processedLength == -1) {
|
if (processedLength < 0) {
|
||||||
LOG(LogError) << "AudioManager::mixAudio(): Couldn't convert sound chunk:";
|
LOG(LogError) << "AudioManager::mixAudio(): Couldn't convert sound chunk:";
|
||||||
LOG(LogError) << SDL_GetError();
|
LOG(LogError) << SDL_GetError();
|
||||||
return;
|
return;
|
||||||
|
@ -197,9 +200,17 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
||||||
// "/ processedLength / streamLength: " << chunkLength << " / " <<
|
// "/ processedLength / streamLength: " << chunkLength << " / " <<
|
||||||
// " / " << processedLength << " / " << streamLength;
|
// " / " << processedLength << " / " << streamLength;
|
||||||
|
|
||||||
SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength,
|
// This mute flag is used to make sure that the audio buffer already sent to the
|
||||||
static_cast<int>(Settings::getInstance()->
|
// stream is not played when the video player has been stopped. Otherwise there would
|
||||||
getInt("SoundVolumeVideos") * 1.28f));
|
// be a short time period when the audio would keep playing after the video was stopped
|
||||||
|
// and before the stream was cleared in clearStream().
|
||||||
|
if (sMuteStream) {
|
||||||
|
SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength,
|
||||||
|
static_cast<int>(Settings::getInstance()->getInt("SoundVolumeVideos") * 1.28f));
|
||||||
|
}
|
||||||
|
|
||||||
// If nothing is playing, pause the device until there is more audio to output.
|
// If nothing is playing, pause the device until there is more audio to output.
|
||||||
if (!stillPlaying && SDL_AudioStreamAvailable(sConversionStream) == 0)
|
if (!stillPlaying && SDL_AudioStreamAvailable(sConversionStream) == 0)
|
||||||
|
@ -264,6 +275,9 @@ void AudioManager::setupAudioStream(int sampleRate)
|
||||||
|
|
||||||
void AudioManager::processStream(const void* samples, unsigned count)
|
void AudioManager::processStream(const void* samples, unsigned count)
|
||||||
{
|
{
|
||||||
|
if (mIsClearingStream)
|
||||||
|
return;
|
||||||
|
|
||||||
if (SDL_AudioStreamPut(sConversionStream, samples, count * sizeof(Uint8)) == -1) {
|
if (SDL_AudioStreamPut(sConversionStream, samples, count * sizeof(Uint8)) == -1) {
|
||||||
LOG(LogError) << "Failed to put samples in the conversion stream:";
|
LOG(LogError) << "Failed to put samples in the conversion stream:";
|
||||||
LOG(LogError) << SDL_GetError();
|
LOG(LogError) << SDL_GetError();
|
||||||
|
@ -276,5 +290,24 @@ void AudioManager::processStream(const void* samples, unsigned count)
|
||||||
|
|
||||||
void AudioManager::clearStream()
|
void AudioManager::clearStream()
|
||||||
{
|
{
|
||||||
SDL_AudioStreamClear(sConversionStream);
|
// The SDL_AudioStreamClear() function is unstable and causes random crashes, so
|
||||||
|
// we have to implement a workaround instead where SDL_AudioStreamGet() is used
|
||||||
|
// to empty the stream.
|
||||||
|
// SDL_AudioStreamClear(sConversionStream);
|
||||||
|
|
||||||
|
mIsClearingStream = true;
|
||||||
|
|
||||||
|
int streamSize;
|
||||||
|
int length = sAudioFormat.samples * 4;
|
||||||
|
|
||||||
|
while ((streamSize = SDL_AudioStreamAvailable(sConversionStream)) > 0) {
|
||||||
|
std::vector<Uint8> readBuffer(length);
|
||||||
|
int processedLength = SDL_AudioStreamGet(sConversionStream,
|
||||||
|
static_cast<void*>(&readBuffer.at(0)), length);
|
||||||
|
if (processedLength <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsClearingStream = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,10 @@ public:
|
||||||
void processStream(const void* samples, unsigned count);
|
void processStream(const void* samples, unsigned count);
|
||||||
void clearStream();
|
void clearStream();
|
||||||
|
|
||||||
bool getHasAudioDevice() { return sHasAudioDevice; };
|
void muteStream() { sMuteStream = true; }
|
||||||
|
void unmuteStream() { sMuteStream = false; }
|
||||||
|
|
||||||
|
bool getHasAudioDevice() { return sHasAudioDevice; }
|
||||||
|
|
||||||
static SDL_AudioDeviceID sAudioDevice;
|
static SDL_AudioDeviceID sAudioDevice;
|
||||||
static SDL_AudioSpec sAudioFormat;
|
static SDL_AudioSpec sAudioFormat;
|
||||||
|
@ -48,7 +51,9 @@ private:
|
||||||
static SDL_AudioStream* sConversionStream;
|
static SDL_AudioStream* sConversionStream;
|
||||||
static std::vector<std::shared_ptr<Sound>> sSoundVector;
|
static std::vector<std::shared_ptr<Sound>> sSoundVector;
|
||||||
static std::shared_ptr<AudioManager> sInstance;
|
static std::shared_ptr<AudioManager> sInstance;
|
||||||
|
static bool sMuteStream;
|
||||||
static bool sHasAudioDevice;
|
static bool sHasAudioDevice;
|
||||||
|
static bool mIsClearingStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_CORE_AUDIO_MANAGER_H
|
#endif // ES_CORE_AUDIO_MANAGER_H
|
||||||
|
|
Loading…
Reference in a new issue