Skip to content

Commit

Permalink
EXPERIMENT: up the OpenAlSource's MaxQueue
Browse files Browse the repository at this point in the history
Our setting is done wrong, because a) it's constants regardless of situation, b) it counts only number of buffers instead of total length (or size).
First of all, buffers may be very small, and then if OpenAlSource is used by the system that does not care about it not being able to queue, then the playback will be skipping chunks.

The low queue limit was necessary mostly to workaround effects lag, such as setting speed. This may be resolved differently.
  • Loading branch information
ivan-mogilko committed Feb 10, 2024
1 parent 8a07069 commit c14efb3
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 12 deletions.
4 changes: 3 additions & 1 deletion Engine/media/audio/audio_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ AudioCoreSlot::AudioCoreSlot(int handle, std::unique_ptr<SDLDecoder> decoder)
: handle_(handle), _decoder(std::move(decoder))
{
_source = std::make_unique<OpenAlSource>(
_decoder->GetFormat(), _decoder->GetChannels(), _decoder->GetFreq());
_decoder->GetFormat(), _decoder->GetChannels(), _decoder->GetFreq(),
2 /* TODO: make this a constant,
and add comment explaining why we keep this queue limit low for now */);
}

void AudioCoreSlot::Init()
Expand Down
7 changes: 4 additions & 3 deletions Engine/media/audio/openalsource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,13 @@ static struct
// OpenAlSource
//-----------------------------------------------------------------------------

OpenAlSource::OpenAlSource(SDL_AudioFormat format, int channels, int freq)
OpenAlSource::OpenAlSource(SDL_AudioFormat format, int channels, int freq, uint32_t max_queue)
{
_inputFmt.format = format;
_inputFmt.channels = static_cast<Uint8>(channels);
_inputFmt.rate = freq;
_alFormat = OpenAlFormatFromSDLFormat(_inputFmt, _recvFmt);;
_alFormat = OpenAlFormatFromSDLFormat(_inputFmt, _recvFmt);
_maxQueue = max_queue;
alGenSources(1, &_source);
dump_al_errors();
_resampler.Setup(_inputFmt, _recvFmt);
Expand Down Expand Up @@ -156,7 +157,7 @@ size_t OpenAlSource::PutData(const SoundBuffer &data)
{
Unqueue();
// If queue is full, bail out
if (_queued >= MaxQueue) { return 0u; }
if (_queued >= _maxQueue) { return 0u; }
// Input buffer is empty?
if (!data.Data || (data.Size == 0)) { return 0u; }
// Check for free buffers, generate more if necessary
Expand Down
13 changes: 8 additions & 5 deletions Engine/media/audio/openalsource.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ namespace Engine
class OpenAlSource
{
public:
// Max sound buffers to queue before/during processing
static const ALuint MaxQueue = 2;

// Initializes Al source for the given format; if there's no direct format equivalent
// found, setups a resampler.
OpenAlSource(SDL_AudioFormat format, int channels, int freq);
OpenAlSource(SDL_AudioFormat format, int channels, int freq, uint32_t max_queue = 1024u);
OpenAlSource(OpenAlSource&& src);
~OpenAlSource();

Expand Down Expand Up @@ -87,7 +84,13 @@ class OpenAlSource
PlaybackState _playState = PlayStateInitial;
float _speed = 1.f; // change in playback rate
float _predictTs = 0.f; // next timestamp prediction
unsigned _queued = 0u;
// Max sound buffers to queue during processing.
// TODO: replace limit of buffer count with limit of memory and/or duration.
// TODO: add a comment explaining why do we have to set very small queue limit
// for regular audio slot play (to decrease custom effects lag),
// alternatively have this logic externally to OpenALSource, somewhere in AudioCoreSlot.
uint32_t _maxQueue = 1024u;
uint32_t _queued = 0u;

// SDL resampler state, in case dynamic resampling in necessary
SDLResampler _resampler;
Expand Down
5 changes: 3 additions & 2 deletions Engine/media/video/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@
#include "gfx/ddb.h"
#include "gfx/graphicsdriver.h"
#include "main/game_run.h"
#include "util/stream.h"
#include "media/audio/audio_system.h"
#include "media/audio/openal.h"
#include "util/memory_compat.h"
#include "util/stream.h"

using namespace AGS::Common;
using namespace AGS::Engine;
Expand Down Expand Up @@ -73,7 +74,7 @@ HError VideoPlayer::Open(const String &name, int flags)
{
if ((_audioFormat > 0) && (_audioChannels > 0) && (_audioFreq > 0))
{
_audioOut.reset(new OpenAlSource(_audioFormat, _audioChannels, _audioFreq));
_audioOut = std::make_unique<OpenAlSource>(_audioFormat, _audioChannels, _audioFreq);
_audioOut->Play();
_wantAudio = true;
}
Expand Down
3 changes: 2 additions & 1 deletion Engine/plugin/agsplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "plugin/plugin_engine.h"
#include "plugin/plugin_builtin.h"
#include "util/library.h"
#include "util/memory_compat.h"
#include "util/string.h"
#include "util/wgt2allg.h"

Expand Down Expand Up @@ -879,7 +880,7 @@ IAGSAudioPlayer *IAGSEngine::OpenAudioPlayer(AGSAudioFormat *in_format, AGSAudio
int chans = in_format->Channels;
int freq = in_format->Freq;
auto *player = new AGSAudioPlayer(
std::unique_ptr<OpenAlSource>(new OpenAlSource(sdl_fmt, chans, freq)));
std::make_unique<OpenAlSource>(sdl_fmt, chans, freq));
return player; // todo: should save somewhere for safe close on exit??
}

Expand Down

0 comments on commit c14efb3

Please sign in to comment.