mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-21 21:55:38 +00:00
Improved the audio streaming in AudioManager.
This commit is contained in:
parent
9c4b116681
commit
fbbb6aece1
|
@ -23,6 +23,7 @@
|
|||
#include "views/gamelist/VideoGameListView.h"
|
||||
#include "views/SystemView.h"
|
||||
#include "views/UIModeController.h"
|
||||
#include "AudioManager.h"
|
||||
#include "FileFilterIndex.h"
|
||||
#include "InputManager.h"
|
||||
#include "Log.h"
|
||||
|
@ -319,6 +320,7 @@ void ViewController::restoreViewPosition()
|
|||
|
||||
void ViewController::goToSystemView(SystemData* system, bool playTransition)
|
||||
{
|
||||
AudioManager::getInstance()->clearStream();
|
||||
bool applicationStartup = false;
|
||||
|
||||
if (mState.viewing == NOTHING)
|
||||
|
|
|
@ -115,13 +115,9 @@ void AudioManager::init()
|
|||
if (Settings::getInstance()->getInt("SoundVolumeVideos") < 0)
|
||||
Settings::getInstance()->setInt("SoundVolumeVideos", 0);
|
||||
|
||||
// Used for streaming audio from videos.
|
||||
sConversionStream = SDL_NewAudioStream(AUDIO_S16, 2, 44100, sAudioFormat.format,
|
||||
sAudioFormat.channels, sAudioFormat.freq);
|
||||
if (sConversionStream == nullptr) {
|
||||
LOG(LogError) << "Failed to create audio conversion stream:";
|
||||
LOG(LogError) << SDL_GetError();
|
||||
}
|
||||
// Use the default sample rate initially, this will possibly be changed by the
|
||||
// video player when a video is started.
|
||||
setupAudioStream(sRequestedAudioFormat.freq);
|
||||
}
|
||||
|
||||
void AudioManager::deinit()
|
||||
|
@ -136,6 +132,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
|||
{
|
||||
// Process navigation sounds.
|
||||
bool stillPlaying = false;
|
||||
bool playedSample = false;
|
||||
|
||||
// Initialize the buffer to "silence".
|
||||
SDL_memset(stream, 0, len);
|
||||
|
@ -145,6 +142,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
|||
while (soundIt != sSoundVector.cend()) {
|
||||
std::shared_ptr<Sound> sound = *soundIt;
|
||||
if (sound->isPlaying()) {
|
||||
playedSample = true;
|
||||
// Calculate rest length of current sample.
|
||||
Uint32 restLength = (sound->getLength() - sound->getPosition());
|
||||
if (restLength > static_cast<Uint32>(len)) {
|
||||
|
@ -167,58 +165,49 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
|
|||
soundIt++;
|
||||
}
|
||||
|
||||
if (playedSample) {
|
||||
// We have processed all samples. check if some will continue playing.
|
||||
if (!stillPlaying) {
|
||||
// Nothing is playing, pause the audio until Sound::play() wakes us up.
|
||||
SDL_PauseAudioDevice(sAudioDevice, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Process video stream audio.
|
||||
// The calling function in VideoVlcComponent is currently disabled as the internal
|
||||
// handling of audio streaming from videos does not work correctly.
|
||||
// Currently only used by VideoFFmpegComponent as the audio streaming seems to
|
||||
// be broken for libVLC.
|
||||
int chunkLength = SDL_AudioStreamAvailable(sConversionStream);
|
||||
|
||||
if (chunkLength != 0) {
|
||||
// Initialize the buffer to "silence".
|
||||
SDL_memset(stream, 0, len);
|
||||
if (chunkLength == 0)
|
||||
return;
|
||||
|
||||
Uint8* converted;
|
||||
converted = new Uint8[chunkLength];
|
||||
int chunkSegment;
|
||||
// Cap the chunk length to the buffer size.
|
||||
if (chunkLength > len)
|
||||
chunkLength = len;
|
||||
|
||||
// Break down the chunk into segments that do not exceed the buffer size.
|
||||
while (chunkLength > 0) {
|
||||
if (chunkLength > len) {
|
||||
chunkSegment = len;
|
||||
chunkLength -= len;
|
||||
}
|
||||
else {
|
||||
chunkSegment = chunkLength;
|
||||
chunkLength = 0;
|
||||
}
|
||||
std::vector<Uint8> converted(chunkLength);
|
||||
|
||||
int processedLength = SDL_AudioStreamGet(sConversionStream, converted, chunkSegment);
|
||||
if (processedLength == -1) {
|
||||
LOG(LogError) << "Failed to convert sound chunk:";
|
||||
LOG(LogError) << SDL_GetError();
|
||||
delete[] converted;
|
||||
return;
|
||||
}
|
||||
int processedLength = SDL_AudioStreamGet(sConversionStream,
|
||||
static_cast<void*>(&converted.at(0)), chunkLength);
|
||||
|
||||
// Enable only when needed, as it generates a lot of debug output.
|
||||
// LOG(LogDebug) << "AudioManager::mixAudio(): chunkLength / chunkSegment "
|
||||
// "/ processedLength: " << chunkLength << " / " << chunkSegment <<
|
||||
// " / " << processedLength;
|
||||
|
||||
if (processedLength > 0)
|
||||
SDL_MixAudioFormat(stream, converted, sAudioFormat.format, processedLength,
|
||||
static_cast<int>(Settings::getInstance()->
|
||||
getInt("SoundVolumeVideos") * 1.28f));
|
||||
}
|
||||
|
||||
delete[] converted;
|
||||
SDL_PauseAudioDevice(sAudioDevice, 1);
|
||||
if (processedLength == -1) {
|
||||
LOG(LogError) << "AudioManager::mixAudio(): Failed to convert sound chunk:";
|
||||
LOG(LogError) << SDL_GetError();
|
||||
return;
|
||||
}
|
||||
|
||||
// We have processed all samples. check if some will still be playing.
|
||||
if (!stillPlaying) {
|
||||
// Nothing is playing, pause the audio until Sound::play() wakes us up.
|
||||
// Enable only when needed, as this generates a lot of debug output.
|
||||
// LOG(LogDebug) << "AudioManager::mixAudio(): chunkLength"
|
||||
// "/ processedLength: " << chunkLength << " / " <<
|
||||
// " / " << processedLength;
|
||||
|
||||
SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength,
|
||||
static_cast<int>(Settings::getInstance()->
|
||||
getInt("SoundVolumeVideos") * 1.28f));
|
||||
|
||||
if (SDL_AudioStreamAvailable(sConversionStream) == 0)
|
||||
SDL_PauseAudioDevice(sAudioDevice, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioManager::registerSound(std::shared_ptr<Sound>& sound)
|
||||
|
@ -255,7 +244,20 @@ void AudioManager::stop()
|
|||
SDL_PauseAudioDevice(sAudioDevice, 1);
|
||||
}
|
||||
|
||||
void AudioManager::processStream(const void *samples, unsigned count)
|
||||
void AudioManager::setupAudioStream(int sampleRate)
|
||||
{
|
||||
SDL_FreeAudioStream(sConversionStream);
|
||||
|
||||
// Used for streaming audio from videos.
|
||||
sConversionStream = SDL_NewAudioStream(AUDIO_F32, 2, sampleRate, sAudioFormat.format,
|
||||
sAudioFormat.channels, sAudioFormat.freq);
|
||||
if (sConversionStream == nullptr) {
|
||||
LOG(LogError) << "Failed to create audio conversion stream:";
|
||||
LOG(LogError) << SDL_GetError();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioManager::processStream(const void* samples, unsigned count)
|
||||
{
|
||||
if (SDL_AudioStreamPut(sConversionStream, samples, count * sizeof(Uint8)) == -1) {
|
||||
LOG(LogError) << "Failed to put samples in the conversion stream:";
|
||||
|
@ -263,5 +265,11 @@ void AudioManager::processStream(const void *samples, unsigned count)
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_PauseAudioDevice(sAudioDevice, 0);
|
||||
if (count > 0)
|
||||
SDL_PauseAudioDevice(sAudioDevice, 0);
|
||||
}
|
||||
|
||||
void AudioManager::clearStream()
|
||||
{
|
||||
SDL_AudioStreamClear(sConversionStream);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,9 @@ public:
|
|||
void stop();
|
||||
|
||||
// Used for streaming audio from videos.
|
||||
void processStream(const void *samples, unsigned count);
|
||||
void setupAudioStream(int sampleRate);
|
||||
void processStream(const void* samples, unsigned count);
|
||||
void clearStream();
|
||||
|
||||
bool getHasAudioDevice() { return sHasAudioDevice; };
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// EmulationStation Desktop Edition
|
||||
// VideoVlcComponent.cpp
|
||||
//
|
||||
// Video playing using libVLC.
|
||||
// Video player based on libVLC.
|
||||
//
|
||||
|
||||
#include "components/VideoVlcComponent.h"
|
||||
|
@ -380,12 +380,11 @@ void VideoVlcComponent::startVideo()
|
|||
|
||||
// The code below enables the libVLC audio output to be processed inside ES-DE.
|
||||
// Unfortunately this causes excessive stuttering for some reason that I still
|
||||
// don't understand, so at the moment this code is disabled. A proper mixer
|
||||
// such as SDL_mixer would be needed anyway to fully support this.
|
||||
// don't understand, so at the moment this code is disabled.
|
||||
// auto audioFormatCallback = [](void **data, char *format,
|
||||
// unsigned *rate, unsigned *channels) -> int {
|
||||
// format = const_cast<char*>("S16N");
|
||||
// *rate = 44100;
|
||||
// format = const_cast<char*>("F32L");
|
||||
// *rate = 48000;
|
||||
// *channels = 2;
|
||||
// return 0;
|
||||
// };
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// EmulationStation Desktop Edition
|
||||
// VideoVlcComponent.h
|
||||
//
|
||||
// Video playing using libVLC.
|
||||
// Video player based on libVLC.
|
||||
//
|
||||
|
||||
#ifndef ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H
|
||||
|
|
Loading…
Reference in a new issue