mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 06:05: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_AudioSpec AudioManager::sAudioFormat;
|
||||
SDL_AudioStream* AudioManager::sConversionStream;
|
||||
bool AudioManager::sMuteStream = false;
|
||||
bool AudioManager::sHasAudioDevice = true;
|
||||
bool AudioManager::mIsClearingStream = false;
|
||||
|
||||
AudioManager::AudioManager()
|
||||
{
|
||||
|
@ -115,8 +117,6 @@ void AudioManager::init()
|
|||
if (Settings::getInstance()->getInt("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);
|
||||
}
|
||||
|
||||
|
@ -163,10 +163,13 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
|||
soundIt++;
|
||||
}
|
||||
|
||||
// Process video stream audio generated by VideoFFmpegComponent.
|
||||
int streamLength = SDL_AudioStreamAvailable(sConversionStream);
|
||||
int streamLength = 0;
|
||||
|
||||
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 (!stillPlaying)
|
||||
SDL_PauseAudioDevice(sAudioDevice, 1);
|
||||
|
@ -186,7 +189,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
|||
int processedLength = SDL_AudioStreamGet(sConversionStream,
|
||||
static_cast<void*>(&converted.at(0)), chunkLength);
|
||||
|
||||
if (processedLength == -1) {
|
||||
if (processedLength < 0) {
|
||||
LOG(LogError) << "AudioManager::mixAudio(): Couldn't convert sound chunk:";
|
||||
LOG(LogError) << SDL_GetError();
|
||||
return;
|
||||
|
@ -197,9 +200,17 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
|||
// "/ processedLength / streamLength: " << chunkLength << " / " <<
|
||||
// " / " << processedLength << " / " << streamLength;
|
||||
|
||||
SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength,
|
||||
static_cast<int>(Settings::getInstance()->
|
||||
getInt("SoundVolumeVideos") * 1.28f));
|
||||
// This mute flag is used to make sure that the audio buffer already sent to the
|
||||
// stream is not played when the video player has been stopped. Otherwise there would
|
||||
// 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 (!stillPlaying && SDL_AudioStreamAvailable(sConversionStream) == 0)
|
||||
|
@ -264,6 +275,9 @@ void AudioManager::setupAudioStream(int sampleRate)
|
|||
|
||||
void AudioManager::processStream(const void* samples, unsigned count)
|
||||
{
|
||||
if (mIsClearingStream)
|
||||
return;
|
||||
|
||||
if (SDL_AudioStreamPut(sConversionStream, samples, count * sizeof(Uint8)) == -1) {
|
||||
LOG(LogError) << "Failed to put samples in the conversion stream:";
|
||||
LOG(LogError) << SDL_GetError();
|
||||
|
@ -276,5 +290,24 @@ void AudioManager::processStream(const void* samples, unsigned count)
|
|||
|
||||
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 clearStream();
|
||||
|
||||
bool getHasAudioDevice() { return sHasAudioDevice; };
|
||||
void muteStream() { sMuteStream = true; }
|
||||
void unmuteStream() { sMuteStream = false; }
|
||||
|
||||
bool getHasAudioDevice() { return sHasAudioDevice; }
|
||||
|
||||
static SDL_AudioDeviceID sAudioDevice;
|
||||
static SDL_AudioSpec sAudioFormat;
|
||||
|
@ -48,7 +51,9 @@ private:
|
|||
static SDL_AudioStream* sConversionStream;
|
||||
static std::vector<std::shared_ptr<Sound>> sSoundVector;
|
||||
static std::shared_ptr<AudioManager> sInstance;
|
||||
static bool sMuteStream;
|
||||
static bool sHasAudioDevice;
|
||||
static bool mIsClearingStream;
|
||||
};
|
||||
|
||||
#endif // ES_CORE_AUDIO_MANAGER_H
|
||||
|
|
Loading…
Reference in a new issue