nCine::AudioDeviceBase class

Backend-independent part of an audio device.

Owns the pool of free sources, the list of active players and the stream decoding thread (not where NCINE_HAS_NATIVE_AUDIO is defined, since nothing is decoded there) - everything an IAudioDevice has to do that does not depend on the sound hardware. A backend derives from this, hands over the source ids it created with setSourcePool() and only implements the buffer and source operations of IAudioDevice.

Base classes

class IAudioDevice
Interface for an audio device backend.

Derived classes

class ALAudioDevice
OpenAL implementation of IAudioDevice.
class AicaAudioDevice
Dreamcast implementation of IAudioDevice on top of the AICA.
class AmigaAudioDevice
Classic Amiga implementation of IAudioDevice on top of ahi.device.
class AsndAudioDevice
Wii/GameCube implementation of IAudioDevice on top of libogc's ASND.
class N64AudioDevice
Nintendo 64 implementation of IAudioDevice on top of libdragon's RSP mixer.
class NdspAudioDevice
Implementation of IAudioDevice on top of the Nintendo 3DS's NDSP.
class Ps2AudioDevice
PlayStation 2 implementation of IAudioDevice on top of audsrv.
class Ps3AudioDevice
PlayStation 3 implementation of IAudioDevice on top of PSL1GHT's libaudio.
class PspAudioDevice
Implementation of IAudioDevice on top of the PSP's sceAudio hardware channel.
class SdlAudioDevice
Implementation of IAudioDevice on top of SDL2's audio queue.

Constructors, destructors, conversion operators

~AudioDeviceBase() override
AudioDeviceBase(const AudioDeviceBase&) deleted
AudioDeviceBase() protected

Public functions

auto operator=(const AudioDeviceBase&) -> AudioDeviceBase& deleted
auto gain() const -> float override
Returns the listener gain (master volume).
auto maxNumPlayers() const -> std::uint32_t override
Returns the maximum number of players that can be active at once.
auto numPlayers() const -> std::uint32_t override
Returns the number of currently active players.
auto player(std::uint32_t index) const -> const IAudioPlayer* override
Returns the active player at the specified index.
auto player(std::uint32_t index) -> IAudioPlayer* override
void stopPlayers() override
Stops every player currently playing.
void pausePlayers() override
Pauses every player currently playing.
void stopPlayers(PlayerType playerType) override
Stops every player of the specified type.
void pausePlayers(PlayerType playerType) override
Pauses every player of the specified type.
void freezePlayers() override
Pauses every player currently playing while keeping it registered.
void unfreezePlayers() override
Resumes every player previously paused by freezePlayers().
auto registerPlayer(IAudioPlayer* player) -> std::uint32_t override
Registers a player so it receives state and buffer queue updates, returning its source id.
void unregisterPlayer(IAudioPlayer* player) override
Unregisters a previously registered player.
void updatePlayers() override
Updates the state of every registered player, including the buffer queue of stream players.
auto submitStreamDecode(const std::shared_ptr<StreamDecodeRequest>& request) -> bool override
Submits a decode request to be executed asynchronously on the decoding thread.
void drainStreamDecode(const std::shared_ptr<StreamDecodeRequest>& request) override
Ensures the specified request is neither queued nor being executed when this method returns.
auto getListenerPosition() const -> const Vector3f& override
Returns the 3D position of the listener.
void beginBlockingOperation() override
Tells the device the caller is about to stop feeding it for a long time.
void endBlockingOperation() override
Ends what beginBlockingOperation() started, and resumes playback.

Protected functions

void onBlockingOperationBegan() virtual
Called when the outermost blocking operation begins, for a backend that has to react.
void onBlockingOperationEnded() virtual
Called when the last outstanding blocking operation ends (see onBlockingOperationBegan()).
void setSourcePool(ArrayView<const std::uint32_t> sourceIds)
Hands the source ids created by the backend over to the pool.
void reportNoAvailableSources()
Reports that registerPlayer() had to refuse for lack of a free source.
void checkForStalledSources()
Releases every source when the backend has stopped advancing them.
void shutdownDecodeThread()
Stops the decoding thread and releases every request still queued.

Protected static variables

static std::size_t TypicalNumSources constexpr
Typical number of sources a backend creates, only the inline capacity of the pools.
static std::int32_t StalledCheckInterval constexpr
Number of frames between two looks at the playback positions while no source is free.
static float StalledTimeoutSecs constexpr
How long every source may read as playing without advancing before the device is given up on.
static float SourceWarningIntervalSecs constexpr
Shortest interval in seconds between two reports of an exhausted source pool.

Protected variables

float _gain
Listener gain (master volume).
Vector3f _listenerPos
Listener position.
SmallVector<std::uint32_t, TypicalNumSources> _sourcePool
Pool of currently inactive source ids.
SmallVector<IAudioPlayer*, TypicalNumSources> _players
Currently active audio players.

Function documentation

IAudioPlayer* nCine::AudioDeviceBase::player(std::uint32_t index) override

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool nCine::AudioDeviceBase::submitStreamDecode(const std::shared_ptr<StreamDecodeRequest>& request) override

Submits a decode request to be executed asynchronously on the decoding thread.

Returns false when no decoding thread is available and the caller has to decode synchronously

The request state must be StreamDecodeRequest::State::Pending when submitted.

void nCine::AudioDeviceBase::drainStreamDecode(const std::shared_ptr<StreamDecodeRequest>& request) override

Ensures the specified request is neither queued nor being executed when this method returns.

Required before the caller touches the request's reader (rewinding, changing looping or replacing it). A request removed from the queue before execution is reset to StreamDecodeRequest::State::Idle, a request already being executed is waited for.

void nCine::AudioDeviceBase::beginBlockingOperation() override

Tells the device the caller is about to stop feeding it for a long time.

A device that mixes on the main thread is fed once per frame, so an operation that blocks that thread for longer than it has queued ahead - a level load, above all - starves it. What starving sounds like is the hardware's business and not always silence: the PlayStation 2's audsrv repeats its last buffer for as long as nothing replaces it (measured), which turns a two second load into two seconds of the same fragment of music over and over. A device that has something better to do with the gap says so here and puts itself back together in endBlockingOperation().

A no-op for every device that mixes on a thread of its own or hands whole sounds to hardware, which is all of them but one - they carry on playing through the block and should.

void nCine::AudioDeviceBase::onBlockingOperationBegan() virtual protected

Called when the outermost blocking operation begins, for a backend that has to react.

The counting half of beginBlockingOperation() is done here so that no backend has to: two independent owners already open these windows (a level load and the episode scan), and a backend whose "stopped" state is a flag rather than a count would have the inner end reopen its stream in the middle of the outer block. Overridden instead of beginBlockingOperation() itself.

void nCine::AudioDeviceBase::reportNoAvailableSources() protected

Reports that registerPlayer() had to refuse for lack of a free source.

Rate-limited, because the callers that keep a sound around retry it every frame for as long as the condition lasts. Describes what is holding the sources, so a leaked looping sound can be told apart from a scene that simply asks for more at once than the device has.

void nCine::AudioDeviceBase::checkForStalledSources() protected

Releases every source when the backend has stopped advancing them.

A backend that stops mixing without reporting it keeps every source reading as playing, which no player can recover from on its own - the pool empties and stays empty for the rest of the session. Looks only at the frames where nothing is free anyway, so a healthy device never pays for it.

void nCine::AudioDeviceBase::shutdownDecodeThread() protected

Stops the decoding thread and releases every request still queued.

Has to be called by the backend destructor before it tears down anything the readers could still touch, the base destructor is too late for that.