Files
RetroArch/audio/audio_driver.h
T
libretroadmin 137d495ab1 Remove eleven write-only state fields
Each of these is assigned and never read anywhere in the tree, so the
work that feeds them is spent for nothing: content_label_len on the
thumbnail path data, sink_discarded on the audio state,
runahead_save_state_size, task_count and msg_queue_regular_padding_x on
the widgets, pipeline_active on the display draw struct,
resolution_hd_enable on the D3D8 and D3D9 states,
memory_search_initialized on the cheat manager, window_title_len and
video_frame_delay_auto_t::frame_time_avg on the video state, and
input_dialog_kb_type on the menu state. Where a write captured a
strlcpy() or fill_pathname() result the call stays and only the
assignment goes.

Two of them were holding up more than themselves.
gfx_widgets_update_icon_layout() branched on whether icons are loaded
solely to pick a padding value, so that conditional computed nothing
and is gone with the field. memory_search_initialized sat beside
memory_initialized, which is read, leaving two near-identical names for
the next reader to tell apart.
2026-09-14 19:06:30 +02:00

1389 lines
61 KiB
C

/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AUDIO_DRIVER__H
#define __AUDIO_DRIVER__H
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/types.h>
#include <boolean.h>
#include <retro_common_api.h>
#include <retro_spsc.h>
#include <retro_atomic.h>
/* Outside the HAVE_THREADS guard below: its struct is a value member of
* the state, needs only retro_atomic, and a build without threads never
* calls into it - so the type has to exist there even though nothing
* uses it. */
#include <rthreads/retro_eventcount.h>
#ifdef HAVE_THREADS
#include <rthreads/rthreads.h>
#else
typedef struct slock slock_t;
typedef struct scond scond_t;
#endif
#include <retro_inline.h>
#include <libretro.h>
#include <retro_miscellaneous.h>
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_DSP_FILTER
#include <audio/dsp_filter.h>
#endif
#ifdef HAVE_AUDIOMIXER
#include <audio/audio_mixer.h>
#endif
#include <audio/audio_resampler.h>
#include <audio/sinc_resampler_int16.h>
#include "audio_defines.h"
#include "audio_upmix.h"
#include "audio_binaural.h"
#include "audio_pipeline_layout.h"
#define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024)
RETRO_BEGIN_DECLS
#ifdef HAVE_AUDIOMIXER
typedef struct audio_mixer_stream
{
audio_mixer_sound_t *handle;
audio_mixer_voice_t *voice;
audio_mixer_stop_cb_t stop_cb;
void *buf;
char *name;
size_t bufsize;
float volume;
enum audio_mixer_stream_type stream_type;
enum audio_mixer_type type;
enum audio_mixer_state state;
} audio_mixer_stream_t;
typedef struct audio_mixer_stream_params
{
void *buf;
char *basename;
audio_mixer_stop_cb_t cb;
size_t bufsize;
unsigned slot_selection_idx;
float volume;
enum audio_mixer_slot_selection_type slot_selection_type;
enum audio_mixer_stream_type stream_type;
enum audio_mixer_type type;
enum audio_mixer_state state;
/* Optional ownership transfer: when buf_owner is non-NULL,
* add_stream borrows 'buf' from it instead of copying, and
* buf_owner_free(buf_owner) runs when the stream's sound is
* destroyed - or immediately on any failure path, or after the
* conversion for WAV. Ownership transfers on the call in every
* outcome; 'buf' must stay valid inside the owner until release.
* Callers with no owned object set both to NULL and keep today's
* copy semantics. */
void *buf_owner;
void (*buf_owner_free)(void *owner);
/* Optional: receives the slot index the stream landed in (or -1 on
* failure). NULL when the caller does not need it. */
int *out_slot;
/* Optional (windowed Ogg-Opus only): the stream's last-page granule,
* found by the feeder from a bounded tail peek so the decoder need
* not scan the whole file for it. 0 means not supplied - the
* decoder does its normal full end-granule scan. */
int64_t end_granule;
/* Windowed sources: bytes resident from the start of buf when the
* stream is added, bounding the decoder's container header parse.
* 0 means the whole buffer is there. */
size_t avail;
} audio_mixer_stream_params_t;
#endif
typedef struct audio_driver
{
/* Creates and initializes handle to audio driver.
*
* latency is the user's audio latency setting, in milliseconds. It
* is the amount of audio the driver should be able to hold between
* write() returning and the device consuming it - the buffering the
* driver itself controls, sized to that much of the output format
* at the rate the device ends up at. A driver that can learn the
* device's own latency beyond that may subtract it, so the total the
* user hears approaches the setting; one that cannot reports what it
* has and leaves the rest to buffer_size() below. The frontend has
* already applied the policy minimum before calling; a driver only
* raises latency further for a hardware minimum of its own.
*
* Returns: audio driver handle on success, otherwise NULL.
**/
void *(*init)(const char *device, unsigned rate,
unsigned latency, unsigned *new_rate);
/*
* @data : Pointer to audio data handle.
* @buf : Audio buffer data.
* @size : Size of audio buffer in bytes.
*
* Write samples to audio driver.
*
* Write data in buffer to audio driver.
* A frame here is defined as one combined sample of left and right
* channels. (I.e. 44.1kHz, 16-bit stereo has 88.2k samples/s, and
* 44.1k frames/s.)
*
* Samples are interleaved in format LRLRLRLRLR ...
* If the driver returns true in use_float(), a floating point
* format will be used, with range [-1.0, 1.0].
* If not, signed 16-bit samples in native byte ordering will be used.
*
* This function returns the number of input bytes successfully written.
* If an error occurs, -1 should be returned.
* Note that non-blocking behavior that cannot write at this time
* should return 0 as returning -1 will terminate the driver.
*
* Unless said otherwise with set_nonblock_state(), all writes
* are blocking, and it should block till it has written all input bytes.
*/
ssize_t (*write)(void *data, const void *s, size_t len);
/**
* Temporarily pauses the audio driver.
*
* Reports the resulting state, not the work done: a driver that is
* already stopped returns \c true, because it is stopped. Whether
* the hardware offers a pause primitive is an implementation detail
* - a driver with none simply stops consuming samples - so it must
* not leak into the return value or into \c alive.
*
* @param data Opaque handle to the audio driver context
* that was returned by \c init.
* @return \c true if the audio driver is now paused,
* \c false if it could not be.
**/
bool (*stop)(void *data);
/**
* Resumes audio driver from the paused state.
*
* Reports the resulting state, as \c stop does: a driver that is
* already running returns \c true.
*
* Returning \c false is not a soft failure. audio_driver_start()
* clears AUDIO_FLAG_ACTIVE on it, which disables audio for the rest
* of the session, so it is reserved for a stream that genuinely
* cannot be resumed. A driver that can recover by other means -
* reinitialising the stream, falling back to a restart when a pause
* primitive it advertised turns out not to work - should do that and
* return \c true.
**/
bool (*start)(void *data, bool is_shutdown);
/**
* Is the audio driver currently running?
*
* Must agree with the last successful \c stop or \c start. Drivers
* that track this with a flag have to maintain it on every path
* through both, including the ones where the hardware call was
* skipped; a flag updated only inside the branch that talks to the
* hardware leaves \c alive reporting the opposite of the truth.
**/
bool (*alive)(void *data);
/* Should we care about blocking in audio thread? Fast forwarding.
*
* If state is true, nonblocking operation is assumed.
* This is typically used for fast-forwarding. If driver cannot
* implement nonblocking writes, this can be disregarded, but should
* log a message to stderr.
* */
void (*set_nonblock_state)(void *data, bool toggle);
/* Stops and frees driver. */
void (*free)(void *data);
/* Defines if driver will take standard floating point samples,
* or int16_t samples.
*
* If true is returned, the audio driver is capable of using
* floating point data. This will likely increase performance as the
* resampler unit uses floating point. The sample range is
* [-1.0, 1.0].
* */
bool (*use_float)(void *data);
/* Human-readable identifier. */
const char *ident;
/* Optional. Get audio device list (allocates, caller has to free this).
*
* data is the driver context and MAY BE NULL. Enumeration must not
* require an initialised driver: the frontend builds this list
* whether or not init succeeded, so the user can pick a device when
* the current one failed, and refreshes it from the menu. A driver
* that caches a list at init may return the cache when given its
* context and must still enumerate when given NULL. */
void *(*device_list_new)(void *data);
/* Optional. Frees audio device list. data MAY BE NULL. */
void (*device_list_free)(void *data, void *data2);
/**
* Optional. How much the driver will take right now without
* blocking, in bytes of the driver's output format - int16 or
* float stereo frames as use_float() decides. Counts every stage
* the driver controls that has room: its own fifo or ring, and the
* device-side buffer where the device reports its fill, so that a
* device with room and a fifo with room add up. Never more than
* buffer_size() reports. The rate control samples this once per
* frame and steers it toward half of buffer_size(); fast-forward
* bounds the resampler's input by it; the threaded pipeline sizes
* its passes from it. A driver that cannot measure its fill should
* leave this NULL rather than report a constant, which reads as a
* device that never drains.
*/
size_t (*write_avail)(void *data);
/**
* Optional. The most the driver can hold between write() returning
* and the device consuming it, in the same bytes write_avail()
* counts: every stage the driver controls, summed - fifo plus
* engine buffer plus queued blocks. Read once at init, so it is a
* property of the opened device; a driver whose server renegotiates
* it afterwards pushes the new size through
* audio_driver_set_buffer_size(), as pulse does. Half of it is the
* rate control's setpoint, so half of it, in time, is the latency
* the user hears from this driver at steady state; a stage the
* driver cannot see (the hardware's own DMA, a mixing daemon's sink)
* adds to that and is not reported here. Zero disables rate
* control for the session, which the frontend logs; a driver that
* has a buffer reports it rather than zero.
*/
size_t (*buffer_size)(void *data);
/**
* Optional. Write raw int16 samples with resampling handled by driver.
* If non-NULL, audio_driver will call this instead of doing software
* resampling. The driver is responsible for resampling from input_rate
* to its output rate, applying the rate_adjust factor for A/V sync,
* and applying the volume gain to the output.
* All frame counts here are input stereo frames, never output frames or
* bytes. Return 0..frames for the accepted prefix; return -1 only when
* an error occurs before accepting any input. A later error must return
* the accepted prefix. Zero frames is a no-op returning 0. The driver
* must consume or copy accepted samples before returning; it cannot
* retain the caller's pointer. Unaccepted input remains caller-owned.
* The frontend may discard that suffix under its nonblocking policy.
* Acceptance does not mean playback: conversion/device consumption may
* happen later. Output-frame accounting is a separate estimate.
* A nonempty request requires samples, a positive representable input
* rate, a finite positive rate_adjust and a finite nonnegative volume.
* Unsupported parameters or failed control changes must not silently
* accept input using stale settings.
*
* @param data Driver context
* @param samples Interleaved int16 stereo samples (LRLRLR...)
* @param frames Number of frames (pairs of samples)
* @param input_rate Source sample rate in Hz
* @param rate_adjust Output-duration multiplier for A/V sync and playback speed (1.0 = normal)
* @param volume Volume gain to apply (0.0 = muted, 1.0 = full volume)
* @return Number of input frames accepted, or -1 on error
*/
ssize_t (*write_raw)(void *data, const int16_t *samples, size_t frames,
unsigned input_rate, double rate_adjust, float volume);
/**
* Optional. Sleeps until the device can accept at least len bytes
* without blocking, then returns how many it will take, as
* write_avail() would. The sleep must be bounded: 0 means no space
* is coming from this call - the device is gone, the stream has
* failed, or nothing drained within the driver's bounded wait - and
* the caller skips the pass and retries on a later wake, so a
* stalled device costs dropped audio rather than a parked audio
* thread. The threaded pipeline calls it with the size of the chunk
* it is about to write, so the write itself never blocks and the
* device fill it measures for rate control beforehand is the real
* one. Drivers without it cannot host the threaded pipeline and
* keep the inline path.
*/
size_t (*wait_writable)(void *data, size_t len);
/**
* Optional. Frames the device has consumed since start(), in output
* frames, monotonic and free-running on the device's own clock: a
* driver with a callback counts what each callback took, one with a
* queue counts what it released less what the device still holds.
* Compared over time with the frames the frontend wrote, it gives
* the device's real sample rate against the host's clock, and the
* frontend trims its resampling ratio by that - slowly, by parts per
* million - so a buffer no longer drifts to an underrun or overrun
* on the difference between two crystals. NULL leaves the frontend
* without the estimate, as before.
*/
size_t (*frames_consumed)(void *data);
/* Optional. Periods the device played silence for want of audio
* since init: the callback found less than one period in the
* buffer and zero-filled it. Counted where it happens, one atomic
* add on that path only; never logged from there. Read by the
* frontend for the statistics overlay each frame, and once at
* driver teardown for the log. NULL when the driver cannot tell. */
size_t (*underruns)(void *data);
/* Optional. The speaker layout the device was opened with, as a
* mask of AUDIO_SPEAKER_ positions (audio_upmix.h), interleaved in
* ascending bit order. A driver that can open more than stereo
* asks audio_driver_requested_layout() at init for the layout the
* frontend wants, opens what the device grants, and reports here
* what it actually opened - the positions, not a count: a device
* that drives the rear pair from the sides reports SIDE_LEFT and
* SIDE_RIGHT, whatever was asked. The frontend upmixes its stereo
* mix to that layout at the last step before write(). NULL, or
* AUDIO_LAYOUT_STEREO, means stereo and the pipeline as it always
* was. Every byte the driver reports - write_avail(),
* buffer_size(), what write() accepts - is in frames of that
* layout's channels. */
uint32_t (*layout)(void *data);
/**
* Optional, and only for drivers whose frames_consumed() reads a
* clock the hardware provides: the same count as this driver would
* have produced without one, on the same terms - monotonic, in
* output frames, from start(). WASAPI's is its service events
* counted and multiplied by a period, which is what it used to
* return outright.
*
* It exists to be disagreed with. The two are compared over the
* same window and the difference reported in parts per million,
* which says on real hardware what the approximation costs -
* whether a device's events really do arrive one per period, and
* where they do not, by how much. Nothing is controlled from it;
* the estimate the frontend acts on is frames_consumed() alone.
* NULL where a driver has only the one number, which is most of
* them.
*
* Last in this structure deliberately. Most drivers initialise it
* positionally and name nothing, so an entry added anywhere but
* the end silently moves every one after it - which is how this
* one first went in, giving three drivers a layout function where
* their underrun counter should have been.
*/
size_t (*frames_consumed_fallback)(void *data);
/* The device's clock against the rate the driver asked for, in
* parts per million, where the driver can measure one: fitted from
* whatever pairing of position and time its API provides - the
* ASIO time information, CoreAudio's callback timestamp, ALSA's
* audio or system timestamp, PipeWire's time report, JACK's cycle
* times.
*
* This is a measurement and nothing acts on it. It exists so the
* figure can be watched live beside the sink estimate that does
* drive rate control, on real hardware, before anyone decides
* whether it should be preferred.
*
* Returns false, leaving *ppm alone, until there is an estimate -
* which takes a second of window at least, and never arrives on a
* device that reports nothing usable. NULL where a driver has no
* clock to read, which is most of them.
*
* ADD NEW MEMBERS AT THE END. A member inserted above this line
* shifts every driver's initialiser by one and the compiler will
* not always say so; that has broken the Android build before. */
bool (*device_clock_ppm)(void *data, double *ppm);
} audio_driver_t;
/* The layout the user asked for, one of the AUDIO_LAYOUT_ masks. A
* driver opening a device reads this; a driver without the layout
* hook is not asked. */
uint32_t audio_driver_requested_layout(void);
/* Netplay's gate on the float batch entry; see
* audio_driver_set_float_gate(). */
typedef bool (*audio_driver_float_gate_t)(void);
/* A snapshot of the sink estimate's counts, taken when a window opens. */
typedef struct
{
double offered; /* sink_offered */
uint64_t consumed; /* frames_consumed() */
uint64_t consumed_alt; /* frames_consumed_fallback(), where there is one */
double pipe; /* what the pipe ring held, in nominal device frames */
double device; /* what the device's buffer held, in device frames */
} audio_sink_mark_t;
/* A sum of windows: their time, and what the source and the device did. */
typedef struct
{
int64_t usec;
double offered;
double consumed;
} audio_sink_sum_t;
typedef struct
{
double src_ratio_orig;
double src_ratio_curr;
uint64_t free_samples_count;
struct string_list *devices_list;
/* The driver whose device_list_new built devices_list, so that its
* device_list_free is the one that releases it - not whichever
* driver is configured or running when the list is next rebuilt. */
const audio_driver_t *devices_list_driver;
/**
* A scratch buffer for audio output to be processed,
* up to (but excluding) the point where it's converted to 16-bit audio
* to give to the driver.
*/
float *output_samples_buf;
size_t output_samples_buf_length;
#ifdef HAVE_REWIND
int16_t *rewind_buf;
/* The same reverse buffer for a float core: its frames as it gave
* them, no round trip through int16 on the way in or out. Indexed
* by rewind_ptr like rewind_buf; which one holds the audio follows
* core_float. */
float *rewind_buf_f;
#endif
/**
* The driver's int16 output staging buffer. Holds the final 16-bit samples
* that are sent to the audio driver and to recording, from whichever source
* produced them: the float->s16 conversion of the float resampler's output,
* or the integer s16 resampler writing here directly.
*/
int16_t *output_samples_int16;
size_t output_samples_int16_length;
/**
* Accumulator for the single-sample core callback
* (audio_driver_sample). Holds AUDIO_SAMPLE_ACCUM_INT16S int16 samples;
* data_ptr is the write index. Emptied by audio_driver_frame_end() once
* the core has returned from retro_run(), or by the overflow guard in
* audio_driver_sample() when a single frame delivers more than it holds.
* Separate from output_samples_int16 so a flush never resamples in place
* over its own input.
*/
int16_t *sample_accum;
#ifdef HAVE_DSP_FILTER
retro_dsp_filter_t *dsp;
#endif
const retro_resampler_t *resampler;
void *resampler_data;
/* Optional deterministic integer (s16) resampler, used by the s16 path
* in audio_driver_flush() when the selected resampler has an int16
* implementation ("sinc", "nearest", "CC") and no float-domain stage is
* active. NULL otherwise. The process/free entry points are selected
* alongside the handle so the s16 path is backend-agnostic. */
void *resampler_data_int16;
void (*resampler_int16_process)(void *, struct resampler_data_int16 *);
void (*resampler_int16_free)(void *);
/**
* The current audio driver.
*/
const audio_driver_t *current_audio;
void *context_audio_data;
/**
* Scratch buffer for preparing data for the resampler
*/
float *input_data;
float *synth_buf;
/* int16 scratch for the s16 path: running a fully-int16 DSP chain
* and/or summing an in-process synth without an int16<->float round-trip.
* Allocated only when an int16 resampler exists, since that path cannot
* run without one; NULL otherwise. */
int16_t *input_data_int16;
size_t input_data_length;
#ifdef HAVE_AUDIOMIXER
struct audio_mixer_stream mixer_streams[AUDIO_MIXER_MAX_SYSTEM_STREAMS];
#endif
struct retro_audio_callback callback; /* ptr alignment */
/**
* Backing storage for every int16 and every float scratch buffer the
* driver owns. The named buffer pointers below (output_samples_int16,
* sample_accum, rewind_buf, input_data_int16; input_data, synth_buf,
* output_samples_buf) all point into one of these two blocks and are
* never freed individually. See audio_driver_init_internal() for the
* layout.
*/
int16_t *arena_int16; /* ptr alignment */
float *arena_float; /* ptr alignment */
/* Native-format frames from one producer to the audio consumer.
* pipe_scratch is the consumer bounce buffer; pipe_conv is producer
* conversion staging. Both live in pipe_arena. */
retro_spsc_t pipe_ring;
uint8_t *pipe_scratch;
uint8_t *pipe_conv;
/* Both in pipe_arena, each a pass at the widest frame the ring can carry. */
void *pipe_arena;
/* Written once by the wrapper thread as it leaves its loop, read by
* the producer's wait. Its own field, not a bit in flags: the main
* thread read-modify-writes flags and a second writer would lose
* bits. */
volatile bool pipe_consumer_gone;
/* Throttle channel for audio_sync without vsync: the consumer bumps
* pipe_gen after every pass and notifies pipe_space; a producer that
* found the ring full waits for the generation to change. No lock:
* the generation is an atomic, the eventcount is only how the
* producer parks, and a pass that completes with nobody parked pays
* a read-modify-write and a load rather than a lock acquisition.
*
* Once per pass is the whole cadence. The consumer notifies where a
* pass ends and nowhere else, so the count of notifies is the count
* of passes however finely the producer publishes. */
/**
* Held across a pipeline pass, and by the main thread whenever it
* changes something a pass reads: the DSP filter pointer and the
* mixer's voices. With the threaded pipeline a pass runs on the
* audio thread, so a menu action that swaps the DSP filter or
* starts a sound would otherwise race it - the filter free is a
* use-after-free window, the mixer a torn voice. Uncontended on
* the frame-synchronous path, where both are the same thread.
* Never held across a device write.
*/
slock_t *state_lock;
retro_eventcount_t pipe_space;
retro_atomic_int_t pipe_gen;
/* Data channel the other way: the producer bumps pipe_data_gen and
* notifies pipe_data, and the consumer sleeps on it while the ring
* holds less than it wants.
*
* Normally once per frame, not once per publish. A core may hand over its audio
* a scanline at a time; a notify per retro_spsc_write() would turn
* one frame into hundreds of consumer passes, each a scanline wide.
* The ring carries the data, so ordinary publishes need no announcement.
* A blocking full-ring wait must also wake the consumer: the producer
* cannot reach frame end until space is released. All producer data
* notifications go through audio_driver_pipeline_signal(). */
retro_eventcount_t pipe_data;
retro_atomic_int_t pipe_data_gen;
/* Set by audio_driver_pipeline_wake() and cleared by the consumer
* when it acts on it. Sticky, unlike the notify beside it, so a wake
* raised before the consumer reaches its wait is not lost. One
* setter and one clearer, so an atomic is the whole of it. */
retro_atomic_int_t pipe_wake;
/* Whether the two parking objects above have been brought up.
* audio_driver_pipeline_wake() is reachable before they have been
* and must do nothing then; it used to ask whether pipe_lock had
* been created, and there is no lock left to ask about. */
bool pipe_park_ready;
/* Set by the producer when a full ring did not drain within its
* bounded wait, cleared by the consumer when a pass completes. While
* set, the producer drops rather than waits, so a device that has
* stopped draining costs the frame nothing beyond the one wait that
* found it out.
*
* One writer each way and neither cares which of them won a race -
* a lost clear is one more frame of dropping, a lost set is one more
* bounded wait - so it is an atomic rather than lock-held state. */
retro_atomic_int_t pipe_stalled;
/**
* What the audio thread needs to know about the runloop and the
* menu, published by the main thread with
* audio_driver_publish_runloop() at every frame end and on every
* start and stop, so the audio thread never reads
* runloop_state.flags, menu state or settings directly. A frame of
* staleness in "paused" or "fast-forward" is harmless; a torn or
* racing read of the runloop's flag word is not.
*/
retro_atomic_int_t runloop_snapshot;
/* The ring's unit: bytes per stereo frame of what the core
* published - int16 or, for a float core, float. Every count on
* the pipe is in frames; bytes appear only at the ring's edge. */
size_t pipe_frame_bytes;
/* The ring's frame width: stereo, or - for a core that negotiated
* the multi-channel batch entry before the driver came up - the
* canonical frame of every position, AUDIO_PIPE_CANON_CHANNELS
* wide, a slot per speaker bit, the ones the batch lacks zero. A
* fixed width, so the ring is never switched under the consumer;
* layout boundaries travel through pipe_layouts before audio publication.
* pipe_wide is the consumer's bounce for a pass of the
* frame. Producers construct frames directly in writable ring spans. */
unsigned pipe_channels;
unsigned pipe_layout; /* producer-only requested layout */
uint8_t *pipe_wide;
size_t pipe_wide_bytes;
bool core_multi; /* the multi-channel entry was negotiated */
/* Whether the ring carries float frames - the core negotiated float
* output - or int16. Decided before any audio flows: at pipe init
* from core_float, or when the negotiation lands on an empty ring. */
bool pipe_float;
/* The core negotiated float audio output; set by the runloop when
* it hands the float batch entry out, cleared when the core goes. */
bool core_float;
audio_driver_float_gate_t float_gate;
/* Upper bound on frames per consumer pass: one video frame's worth,
* capped to a slice. */
size_t pipe_pass_frames;
/* Rate control's fill on the threaded pipeline, as free space in
* device bytes, sampled by the producer before each publish and
* read by the consumer's controller; -1 before the first sample.
*
* The device's own fill cannot be the control variable here: the
* consumer waits for half the device's buffer and writes half, so
* that fill sits between half and full whatever the clocks do, and a
* controller reading it - at any point of the pass - sees a constant
* error and pins the ratio at a bound. What the clocks move is the
* pipe ring in front of the device: a production surplus collects
* there, a deficit empties it. So the fill is the two together, the
* pipe's frames counted at the device's rate, and it is read where
* the frame-synchronous path read it, once a frame on the core's
* thread before the frame is published - the pipe at its low point,
* the device wherever it is. The device's mean free space over the
* pass is a quarter of its buffer, the controller's setpoint is
* half, and the difference is added so a balanced pipe reads as no
* error. */
retro_atomic_int_t pipe_ctrl_avail;
/* The driver's underrun count as the consumer last saw it; a change
* means the device played silence since, and what the pipe holds
* past its target is late audio, discarded. Consumer thread only. */
size_t pipe_underruns_seen;
/* Whether the consumer's next pass is its first: it waits for the
* pipe's target then, not just a frame. Consumer thread only after
* init. */
bool pipe_priming;
/* The audio thread's own copy of AUDIO_FLAG_PIPELINE_THREADED. Set
* before the wrapper thread is released and cleared after it is
* joined, so the thread never reads the flags word - which the main
* thread read-modify-writes at will - just to know it is running. */
bool pipe_threaded;
/* The fast-forward speedup multiplier, measured by the producer on
* the core's thread and read by the consumer, as a Q16 fixed-point
* value. The consumer's own cadence is the device's, so it cannot
* measure how fast the core is running; only the producer can. */
retro_atomic_int_t pipe_ff_mult_q16;
#ifdef HAVE_REWIND
size_t rewind_ptr;
size_t rewind_size;
#endif
size_t buffer_size;
/* The device stage behind the driver's buffer, in frames at the
* output rate, as the driver reports it: what ASIOGetLatencies gives
* for output, say. 0 when the driver reports none. Set by the driver
* through audio_driver_set_device_latency(); shown in the statistics
* overlay next to the buffer, since it is the part of the path the
* setting cannot reach and the part that differs most between
* devices. */
size_t device_latency_frames;
size_t data_ptr;
unsigned free_samples_buf[AUDIO_BUFFER_FREE_SAMPLES_COUNT];
#ifdef HAVE_AUDIOMIXER
float mixer_volume_gain;
#endif
float rate_control_delta;
float input;
float volume_gain;
enum resampler_quality resampler_quality;
/**
* AUDIO_FLAG_* word. Read-modify-written by the main thread and
* read by the audio thread (core audio callbacks, the threaded
* pipeline), so it is an atomic int accessed only through
* AUDIO_FLAGS_GET / AUDIO_FLAGS_SET / AUDIO_FLAGS_CLEAR: the RMWs
* cannot lose bits against each other and a reader always sees a
* whole word. Individual bits are still only meaningful together
* with the ordering their setters already establish (driver start
* before the thread runs, init before start, and so on).
*/
retro_atomic_int_t flags;
char resampler_ident[64];
/* A driver's request to be reinitialised - a device change or an
* unplug, set from its notification thread. Taken by the runloop
* once a frame on the main thread with no audio lock held; see
* audio_driver_take_reinit_request(). */
retro_atomic_int_t reinit_request;
bool mute_enable;
#ifdef HAVE_AUDIOMIXER
bool mixer_mute_enable;
uint8_t mixer_streams_playing; /* Count of currently playing mixer streams */
#endif
/* Sample the flush delta-time when fast forwarding to find the correct ratio. */
retro_time_t last_flush_time;
/* Exponential moving average */
retro_time_t avg_flush_delta;
/* Rate-limit state for the DRC compute.
*
* The DRC ratio is updated approximately once per game-frame's worth
* of submitted samples rather than once per audio_driver_sample_batch
* call. Cores that submit a single batch per retro_run see DRC fire
* once per frame as before. Cores that submit N sub-frame batches
* per retro_run see DRC fire approximately once per frame (when the
* cumulative samples cross the threshold) instead of N times per
* frame. This:
* - removes (N-1) per-call audio->write_avail calls (a syscall on
* ALSA/WASAPI/Pulse/PipeWire backends; cheap on CoreAudio)
* - stabilises the resampler ratio (the DRC was designed around
* a once-per-frame time constant; per-batch updates sample
* write_avail at sub-frame phase, adding noise to the loop)
*
* drc_threshold_int16s is recomputed by audio_driver_update_drc_threshold
* from the current input sample rate and av_info.timing.fps whenever
* audio_driver_init_internal runs (which is also where the input
* rate gets set, and where SET_SYSTEM_AV_INFO drives reinit). This
* keeps the "one frame's worth" target accurate at any output sample
* rate (48 kHz, 96 kHz, 192 kHz, ...) and any content fps. */
double cached_rate_adjust; /* last computed factor; default 1.0 */
/* Sink rate estimation: see audio_driver_sink_update(). Counted
* where the driver's write() is called, on the thread that flushes;
* the estimate runs there too. */
double sink_offered; /* the source's count, in frames at the nominal
ratio: what the core published into the
pipeline's ring, or off it what was offered
with the ratio in force divided out. Owned
by the thread that closes the windows. */
uint64_t sink_offered_raw; /* output frames offered, as offered */
uint64_t sink_accepted; /* output frames the driver took */
/* The estimate: windows of a few seconds, each read as a change in
* the counts above and in the device's consumption, kept when it
* measures the clocks and summed; the bias is the summed ratio.
* See audio_driver_sink_update(). */
int64_t sink_started; /* usec; 0 = not started */
int64_t sink_window_at; /* usec; when the open window closes */
double sink_alt_ppm; /* the driver's own approximation against its clock, ppm */
int64_t sink_apply_at; /* usec; the next setting of the bias */
audio_sink_mark_t sink_at_window; /* the counts when the open window opened */
/* The last windows' time and source count, for the source's band:
* a window closes at a publish, so its length carries that publish's
* lateness - a frame of the core's run time - which the next window
* carries back. Over a few windows it cancels; a stall does not. */
int64_t sink_recent_usec[4];
double sink_recent_offered[4];
double sink_recent_consumed[4];
unsigned sink_recent_head;
audio_sink_sum_t sink_kept; /* the windows summed for the bias */
audio_sink_sum_t sink_pending; /* windows since the last kept one, for the rates shown meanwhile */
bool sink_pending_broken; /* a dry spell is in it: shown, never merged into the kept sums */
unsigned sink_settled; /* kept windows in a row, up to 2, after which the sums stand */
unsigned sink_applied; /* times the bias has been set */
/* AUDIO_SINK_WARNED_* said once each, in two words because the two
* sides run on different threads: on the threaded pipeline the
* estimator runs on the core's thread, from submit, and the flush
* on the audio thread, and |= is a read-modify-write. Each word is
* written only by the thread that owns it, and no flag lives in
* both. */
unsigned sink_warned; /* the estimator's: sink_window(), sink_apply() */
unsigned sink_warned_flush; /* the flush's: sink_refused() */
double sink_bias; /* multiplied into the ratio; 1.0 = none */
/* The bias for the thread that resamples, in hundredths of a part
* per million: on the threaded pipeline the estimate runs on the
* core's thread and the resampler on the audio thread, and a double
* is not a single word. */
retro_atomic_int_t sink_bias_q;
double sink_rate_hz; /* the device's rate as measured; 0 = unknown */
double sink_source_hz; /* the source's rate at the nominal ratio, as measured */
size_t samples_since_drc; /* int16 samples submitted since last update */
size_t drc_threshold_int16s; /* one frame's worth of stereo int16 at the current rate */
/* Set by audio_driver_frame_end() so the next flush recomputes the
* DRC factor regardless of samples_since_drc. Pins the write_avail()
* measurement to the same point of every frame - the first flush the
* core makes after retro_run() returns - instead of wherever the
* sample-count gate happens to trip. */
bool drc_pending;
/* Last-flush sample-format diagnostics for the on-screen statistics
* overlay. stat_core_is_float records whether the core delivered float
* (audio_driver_sample_batch_float) or int16 (audio_driver_sample_batch)
* samples; stat_frontend_is_float records whether the frontend processed
* that audio through the float resampler path (true) or an integer path
* (false: either the write_raw raw-int16 fast path or the deterministic
* s16 resampler path). */
bool stat_core_is_float;
bool stat_frontend_is_float;
/* Unity passthrough state: set when the float path skipped the
* resampler because the ratio was exactly 1.0 (see audio_driver_flush).
* Used to re-initialise the resampler on the transition back to actual
* resampling so it does not resume from a stale ring buffer. */
bool resampler_bypassed;
bool resampler_hq; /* resolved software HQ policy for this audio instance */
/* The layout the device was opened with - AUDIO_LAYOUT_STEREO
* unless the driver reports a wider one - its channel count, and
* the stage that widens the stereo mix to it at the last step
* before write(). The buffers hold one write's frames at
* out_channels, float and int16. */
uint32_t out_layout;
unsigned out_channels;
/* The multi-channel batch entry (RETRO_ENVIRONMENT_GET_AUDIO_
* SAMPLE_BATCH_MULTI): the layout the core last delivered, and
* the stereo fold of a batch, grown to the largest batch seen. The
* pipeline carries stereo; a core's wider frame is folded here at
* the boundary, and the device's upmix widens the stereo again.
* core_layout is stereo until the core delivers something else,
* and the overlay says what it was folded from. */
uint32_t core_layout;
void *multi_fold;
size_t multi_fold_frames;
/* the recorder's frame from a batch of another layout or format */
int16_t *record_remap;
size_t record_remap_frames;
/* The discrete path: a core's channels past the front pair, kept
* apart to a device that has their positions. The front pair goes
* through the pipeline as every stereo core's does - the filters,
* the resampler, the mixer, rate control - and the others go
* beside it through their own instances of the same resampler at
* the same ratio, in pairs, so their frame count is the fronts'.
* At the write they take the device slots of their positions and
* the upmix fills what the core did not send. Stereo ring only:
* on the threaded pipeline the extras are not carried yet, and the
* entry folds instead. */
struct
{
unsigned channels; /* extras: core channels less two, 0 = none */
uint32_t positions; /* their mask, without FL and FR */
unsigned nres; /* resampler instances: (channels + 1) / 2 */
void *res[4]; /* float: resampler_data; int16: resampler_data_int16 */
bool res_int16; /* which kind res[] holds */
bool bypassed;
float *in_f; /* frames * channels, interleaved, this batch */
int16_t *in_i;
float *pair_in; /* native scratch only; all NULL for two extras */
float *pair_out;
int16_t *pair_in_i;
int16_t *pair_out_i;
float *out_f; /* the resampled extras, frames * channels */
int16_t *out_i;
size_t cap_in; /* frames the in buffers hold */
size_t cap_out; /* frames the out and pair buffers hold */
size_t in_frames; /* pending in this flush */
size_t out_frames; /* produced by the last resample */
bool pending; /* extras accompany the flush in progress */
bool is_float;
} extra;
audio_upmix_t upmix;
float *upmix_buf;
int16_t *upmix_i16;
size_t upmix_frames;
/* Headphones on a stereo device: the stereo mix is widened to a
* virtual 5.1 by the upmix and rendered back to two ears by the
* binaural stage, so the rears are behind the listener. On when
* the setting is and the device is stereo; the render lands in
* upmix_buf's second half. */
bool virtualize;
audio_binaural_t binaural;
float *virt_buf; /* frames * 6 floats, the virtual 5.1 */
/* Keep existing hot audio fields together when adding transport state. */
audio_pipeline_layout_t pipe_layouts;
/* Consumer-owned view into output scratch until a short write completes. */
const uint8_t *pipe_pending;
size_t pipe_pending_bytes;
void (*resampler_int16_reset)(void *);
#ifdef HAVE_THREADS
struct audio_pipeline_stretch *pipe_transport;
void *pipe_transport_output;
uint32_t pipe_transport_serial, pipe_transport_search;
unsigned pipe_transport_rate;
/* Producer-owned source count for the current fast-forward frame. */
size_t pipe_ff_frames;
uint8_t pipe_transport_follow;
/* Mutually exclusive with pipe_transport; shares its output storage. */
struct audio_pipeline_stretch *pipe_transport_suspended;
#endif
struct audio_inline_transport *inline_transport;
/* Frozen at audio reinitialization; SRC owns speed in filter-only mode. */
bool transport_lpf_only;
} audio_driver_state_t;
bool audio_driver_enable_callback(void);
bool audio_driver_disable_callback(void);
bool audio_driver_mixer_extension_supported(const char *ext);
void audio_driver_dsp_filter_free(void);
bool audio_driver_dsp_filter_init(const char *device);
void audio_driver_set_buffer_size(size_t bufsize);
/* The device's own transfer granularity in frames, where the platform
* knows it: Android reports the fast mixer's burst through
* OUTPUT_FRAMES_PER_BUFFER, and a buffer that is not a multiple of it
* leaves the fast path. Zero where the platform does not say, which is
* everywhere else - a driver that gets zero picks its own block from
* the latency it was asked for.
*
* This is a property of the sink, in the same class as the device
* period WASAPI reports or the period grid an ALSA card refines to.
* Those are asked of the device; this one is asked of the platform,
* because the sink cannot be asked directly. Neither is a preference. */
unsigned audio_driver_device_block_frames(void);
/* Records the device stage behind the driver's buffer, in frames at the
* output rate; 0 to say the driver reports none. Reset when a driver is
* initialised, so a driver that reports one calls this after each init
* or reinit, and again if the device changes it. */
void audio_driver_set_device_latency(size_t frames);
bool audio_driver_get_devices_list(void **ptr);
void audio_driver_setup_rewind(void);
/**
* audio_driver_set_nonblock_state:
*
* Hands the blocking state to the driver and records it in
* AUDIO_FLAG_NONBLOCK so the threaded pipeline's producer can see it.
* Every caller that used to reach current_audio->set_nonblock_state()
* directly goes through here.
**/
void audio_driver_set_nonblock_state(bool nonblock);
/**
* audio_driver_pipeline_consumer_exit:
*
* Called by the audio thread wrapper as its thread leaves the loop, so
* a producer waiting for ring space stops waiting for a consumer that
* will never run again.
**/
void audio_driver_pipeline_consumer_exit(void);
#ifdef HAVE_THREADS
struct audio_pipeline_stretch;
/* Main producer thread, without worker locks held. Prepare on an empty source
* ring with no pending device output; replacement starts a new DSP epoch.
* Prepared sessions are consumed by the audio callback. The caller supplies
* source-ordered controls; normal callbacks do not declare EOF.
* Failure preserves an existing session. Release explicitly cancels retained
* output/history. Both transactions park and restore the real wrapper.
* Empty-ring format renegotiation rebuilds the session; allocation failure
* releases it while preserving the new native ring format. */
bool audio_driver_pipeline_transport_prepare(unsigned rate, uint32_t search_channels);
/* Prepare and seed current runloop tempo/cutoff in one parked transaction.
* Empty source/no pending device output required. Failure preserves the old
* transport and metadata; unsupported speed is rejected before allocation.
* Explicit startup API: does not register an automatic update caller. */
bool audio_driver_pipeline_transport_prepare_runloop(unsigned rate,
uint32_t search_channels, bool lowpass);
/* Opt in to producer updates before the first publish of each frame.
* Unsupported speed cancels retained DSP/device output and returns to the
* legacy pipeline while retaining transport storage. Supported speed resumes
* after queued source and pending device output drain; no forced source drop
* or allocation on recovery. Metadata pressure drops that publish and retries
* at the next one. Same preparation preconditions. */
bool audio_driver_pipeline_transport_start_runloop(unsigned rate,
uint32_t search_channels, bool lowpass);
void audio_driver_pipeline_transport_release(void);
/* Main source producer only, before publishing the affected audio. Tempo is
* source frames/output frame in Q16, 0.25..32 when active (ignored when inactive).
* cutoff is core-rate Hz, or zero to disable filtering. Preserve the current
* source layout; publish layout changes before this call at the same boundary.
* A missing session, invalid tempo or full queue returns false without changing
* the request. Retry before publishing affected audio. No mode activation. */
bool audio_driver_pipeline_transport_request(uint32_t tempo_q16,
bool active, bool reset, uint32_t cutoff);
/* Same transaction, with optional speed-linked low-pass coloration.
* The cutoff uses the prepared core rate and requested Q16 speed; unity
* and slow motion are dry. Filtering is independent of active (WSOLA).
* On failure retry before publishing source. */
bool audio_driver_pipeline_transport_request_speed(uint32_t tempo_q16,
bool active, bool reset, bool lowpass);
/* Producer-only, before publishing the next source block. Compose current
* runloop slow motion and the last frame's fast-forward estimate, respecting
* audio_fastforward_speedup. Paused/normal playback requests unity. Reject
* unsupported speeds (outside 0.25..32) without changing queued controls.
* Does not prepare a transport or select a fallback on failure. */
bool audio_driver_pipeline_transport_request_runloop(bool reset, bool lowpass);
/* Consumer thread, or main thread with the wrapper parked; no worker locks
* held. Cancel owned transport/device output and reset DSP history, skipping
* exactly frames of queued native source. Zero preserves queued source.
* Invalid/oversized requests leave state untouched. Notify the producer when
* source space is released. This does not acknowledge a device underrun. */
bool audio_driver_pipeline_transport_discard(size_t frames);
/* Consumer-only bounded pass for a pitch-preserving transport session. Stage
* must own this driver's native ring/metadata and separate output storage;
* serial is caller-owned, initially zero. The caller owns source waits,
* priming, lifecycle/discontinuity discard and EOF selection. False requires
* caller intervention (invalid state, pause/inactive, underrun or stage error).
* Device backpressure/retries return true without new source consumption.
* No stage initialization or mode selection is performed here. */
bool audio_driver_pipeline_transport_step(struct audio_pipeline_stretch *stage,
uint32_t *serial, size_t input_budget, size_t output_budget,
bool finishing, bool *complete);
#endif
/**
* audio_driver_pipeline_wake:
*
* Wakes a consumer sleeping for data and a producer sleeping for room,
* without giving either. The audio thread wrapper calls it before it
* joins its thread, so a consumer parked on an empty ring returns to
* the loop and sees that it is being shut down instead of sleeping
* out its timeout.
**/
void audio_driver_pipeline_wake(void);
/**
* audio_driver_state_lock:
* audio_driver_state_unlock:
*
* Guards the DSP filter and the mixer against a pipeline pass on the
* audio thread. Cheap and safe to call before the audio driver is up:
* the lock exists for the driver's lifetime and both are no-ops
* without it.
**/
void audio_driver_state_lock(void);
void audio_driver_state_unlock(void);
/* Bits of audio_driver_state_t::runloop_snapshot. */
enum audio_runloop_snapshot_bits
{
AUDIO_SNAP_PAUSED = (1 << 0),
AUDIO_SNAP_SLOWMOTION = (1 << 1),
AUDIO_SNAP_FASTMOTION = (1 << 2),
AUDIO_SNAP_MENU_ALIVE = (1 << 3),
AUDIO_SNAP_MENU_PAUSES = (1 << 4),
AUDIO_SNAP_ALLOW_PAUSE = (1 << 5)
};
/**
* audio_driver_publish_runloop:
*
* Main thread only. Captures the runloop, menu and setting bits the
* audio thread consults into runloop_snapshot. Called from the frame
* end and from audio_driver_start()/stop(); cheap enough to call
* anywhere else those bits change.
**/
void audio_driver_publish_runloop(void);
/* Accessors for audio_driver_state_t::flags; see the field. GET is an
* acquire load, SET/CLEAR are acq_rel RMWs, all returning the whole
* word so a caller can test bits on the result. */
#define AUDIO_FLAGS_GET(st) retro_atomic_load_acquire_int(&(st)->flags)
#define AUDIO_FLAGS_SET(st, bits) retro_atomic_fetch_or_int(&(st)->flags, (bits))
#define AUDIO_FLAGS_CLEAR(st, bits) retro_atomic_fetch_and_int(&(st)->flags, ~(bits))
/**
* audio_driver_frame_end:
*
* Marks the end of one emulated frame on the thread that produced it.
* Flushes whatever the single-sample callback accumulated during
* retro_run() and arms a DRC recompute for the next flush. Must be
* called after every retro_run() of the running core, on the same
* thread. No-op when a core audio callback is registered, since that
* core delivers audio on the audio thread and audio_driver_callback()
* flushes it there.
**/
void audio_driver_frame_end(void);
/**
* audio_driver_callback:
*
* One pass of the audio thread. The threaded pipeline consumer waits
* internally. A core callback returns true after a device write or
* consuming input into bounded stretch state, which may need more source
* before it can write. False means no progress (paused, suspended or an
* empty callback); the caller parks before asking again.
**/
bool audio_driver_callback(void);
bool audio_driver_has_callback(void);
void audio_driver_frame_is_reverse(void);
void audio_set_float(enum audio_action action, float val);
float *audio_get_float_ptr(enum audio_action action);
bool *audio_get_bool_ptr(enum audio_action action);
#ifdef HAVE_AUDIOMIXER
audio_mixer_stream_t *audio_driver_mixer_get_stream(unsigned i);
bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params);
/* Compressed-byte read position of the stream in 'slot' (its
* decoder's offset within the source buffer), or -1 when the slot
* holds no live stream. The windowed-source feeder's polling
* input. */
int64_t audio_driver_mixer_stream_byte_tell(unsigned i);
/* Raise a windowed stream's resident prefix as its feeder slides the
* window forward. The mirror of audio_driver_mixer_stream_byte_tell. */
void audio_driver_mixer_stream_set_avail(unsigned i, size_t avail);
void audio_driver_mixer_play_stream(unsigned i);
void audio_driver_mixer_play_menu_sound(unsigned i);
void audio_driver_mixer_play_scroll_sound(bool direction_up);
void audio_driver_mixer_play_menu_sound_looped(unsigned i);
void audio_driver_mixer_play_stream_sequential(unsigned i);
void audio_driver_mixer_play_stream_looped(unsigned i);
void audio_driver_mixer_stop_stream(unsigned i);
float audio_driver_mixer_get_stream_volume(unsigned i);
void audio_driver_mixer_set_stream_volume(unsigned i, float vol);
void audio_driver_mixer_remove_stream(unsigned i);
enum audio_mixer_state audio_driver_mixer_get_stream_state(unsigned i);
const char *audio_driver_mixer_get_stream_name(unsigned i);
unsigned audio_driver_mixer_get_streams_playing(void);
void audio_driver_load_system_sounds(void);
#endif
bool audio_driver_start(bool is_shutdown);
bool audio_driver_stop(void);
#ifdef HAVE_TRANSLATE
/* TODO/FIXME - Doesn't currently work. Fix this. */
bool audio_driver_is_ai_service_speech_running(void);
#endif
/**
* audio_compute_buffer_statistics:
*
* Computes audio buffer statistics.
*
**/
bool audio_compute_buffer_statistics(audio_statistics_t *stats);
bool audio_driver_init_internal(void *data, bool audio_cb_inited);
bool audio_driver_deinit(void);
/* Rebuild audio_driver_st.devices_list from the driver that is, or
* would be, in use. Does not require the driver to be initialised. */
void audio_driver_refresh_devices_list(void);
bool audio_driver_find_driver(const char *audio_drv,
const char *prefix, bool verbosity_enabled);
/**
* audio_driver_sample:
* @left : value of the left audio channel.
* @right : value of the right audio channel.
*
* Audio sample render callback function.
**/
void audio_driver_sample(int16_t left, int16_t right);
/**
* audio_driver_sample_batch:
* @data : pointer to audio buffer.
* @frames : amount of audio frames to push.
*
* Batched audio sample render callback function.
*
* Returns: amount of frames sampled.
**/
size_t audio_driver_sample_batch(const int16_t *data, size_t frames);
/**
* audio_driver_sample_batch_float:
*
* Float counterpart of audio_driver_sample_batch(), handed to a core via
* RETRO_ENVIRONMENT_GET_AUDIO_SAMPLE_BATCH_FLOAT. Samples are interleaved
* stereo float normalized to [-1.0, 1.0].
*
* @return Number of frames processed.
**/
size_t audio_driver_sample_batch_float(const float *data, size_t frames);
/* The multi-channel batch entries handed to a core that negotiated
* RETRO_ENVIRONMENT_GET_AUDIO_SAMPLE_BATCH_MULTI: a frame of the
* layout's channels, folded to stereo and passed to the classic
* entry of the same sample format. 0 for a layout not taken. */
size_t audio_driver_sample_batch_multi_int16(const int16_t *data, size_t frames, unsigned channels, unsigned layout);
size_t audio_driver_sample_batch_multi_float(const float *data, size_t frames, unsigned channels, unsigned layout);
#ifdef HAVE_REWIND
/**
* audio_driver_sample_rewind:
* @left : value of the left audio channel.
* @right : value of the right audio channel.
*
* Audio sample render callback function (rewind version).
* This callback function will be used instead of
* audio_driver_sample when rewinding is activated.
**/
void audio_driver_sample_rewind(int16_t left, int16_t right);
/**
* audio_driver_sample_batch_rewind:
* @data : pointer to audio buffer.
* @frames : amount of audio frames to push.
*
* Batched audio sample render callback function (rewind version).
*
* This callback function will be used instead of
* audio_driver_sample_batch when rewinding is activated.
*
* Returns: amount of frames sampled.
**/
size_t audio_driver_sample_batch_rewind(
const int16_t *data, size_t frames);
#endif
#ifdef HAVE_MENU
void audio_driver_menu_sample(void);
#endif
extern audio_driver_t audio_rsound;
extern audio_driver_t audio_audioio;
extern audio_driver_t audio_oss;
extern audio_driver_t audio_alsa;
extern audio_driver_t audio_tinyalsa;
extern audio_driver_t audio_roar;
extern audio_driver_t audio_openal;
extern audio_driver_t audio_opensl;
extern audio_driver_t audio_jack;
extern audio_driver_t audio_sdl;
extern audio_driver_t audio_sdl3;
extern audio_driver_t audio_xa;
extern audio_driver_t audio_pulse;
extern audio_driver_t audio_pipewire;
extern audio_driver_t audio_dsound;
extern audio_driver_t audio_wasapi;
extern audio_driver_t audio_wdmks;
#ifdef HAVE_ASIO
extern audio_driver_t audio_asio;
/* Opens the running ASIO driver's control panel. False when ASIO is not
* the driver running - it was picked in the menu and audio has not
* been reinitialised since - so the caller can say so. */
bool audio_asio_open_control_panel(void);
bool audio_asio_output_channel_name(unsigned ch, char *buf, size_t len);
unsigned audio_asio_output_channel_count(void);
#endif
extern audio_driver_t audio_coreaudio;
extern audio_driver_t audio_xenon360;
extern audio_driver_t audio_ps3;
extern audio_driver_t audio_gx;
extern audio_driver_t audio_ax;
extern audio_driver_t audio_psp;
extern audio_driver_t audio_ps2;
extern audio_driver_t audio_ctr_csnd;
extern audio_driver_t audio_ctr_dsp;
#ifdef HAVE_THREADS
#endif
extern audio_driver_t audio_switch;
extern audio_driver_t audio_switch_libnx_audren;
extern audio_driver_t audio_rwebaudio;
extern audio_driver_t audio_audioworklet;
audio_driver_state_t *audio_state_get_ptr(void);
/**
* audio_driver_update_drc_threshold:
*
* Recompute drc_threshold_int16s for the current sample rate / fps.
* Called from audio_driver_init_internal whenever audio is initialized
* or reinitialised (which covers SET_SYSTEM_AV_INFO and output-rate
* setting changes), and from refresh-rate change paths in retroarch.c
* that update audio_driver_state_t::input without driving a full audio
* reinit.
**/
void audio_driver_update_drc_threshold(audio_driver_state_t *audio_st);
const char *audio_driver_get_ident(void);
/* The speaker path in effect, in a few words, for the statistics
* overlay: the layout the device opened with and how it is filled.
* Returns the length written. */
size_t audio_driver_get_layout_desc(char *s, size_t len);
/* The core negotiated float audio output, or has gone. The threaded
* pipeline's ring takes the core's format from this: float frames
* from a float core, with no round trip through int16. */
void audio_driver_set_core_float(bool core_float);
/* The core negotiated RETRO_ENVIRONMENT_GET_AUDIO_SAMPLE_BATCH_MULTI:
* a driver brought up after this carries the canonical wide frame on
* its threaded ring, so a batch's channels reach the device apart.
* Negotiated after the driver is up, the entry folds to stereo until
* the next driver init. */
void audio_driver_set_core_multi(bool core_multi);
/* A gate on the float batch entry, for netplay: the core holds that
* entry by pointer, so it cannot be swapped for an intercepting one
* as the int16 callbacks are. When set, the entry asks it whether the
* frame's audio is to be dropped - a replayed frame during rollback,
* or a stall - and returns without playing it. NULL when netplay is
* not intercepting. */
void audio_driver_set_float_gate(audio_driver_float_gate_t gate);
/* Periods the device played silence for want of audio since the driver
* was initialised, where the driver counts them; 0 otherwise. */
size_t audio_driver_get_underruns(void);
/* Whether a driver has asked to be reinitialised since the last call;
* clears the request. The runloop calls this once a frame, on the main
* thread, holding no audio lock, and acts on it there: the reinit
* tears the driver down and up, which frees the state lock and, on
* the threaded pipeline, joins the audio thread, so it can be run
* neither under the lock nor from that thread. */
bool audio_driver_take_reinit_request(void);
double audio_driver_get_buffer_latency_ms(void);
/* The device stage behind the buffer in ms, as set by
* audio_driver_set_device_latency(); 0 when the driver reports none. */
double audio_driver_get_device_latency_ms(void);
/* The device's sample rate as measured against the host clock, in Hz,
* and the ratio bias applied for it; 0 when no driver reports
* frames_consumed() or no window has completed yet. */
double audio_driver_get_sink_rate_hz(double *bias, double *source_hz);
/* Parts per million by which a driver's own approximation of the
* device's consumption differs from the clock it reads, over the last
* window; 0 where it has no second number to compare. */
double audio_driver_get_sink_alt_ppm(void);
/* The device's own clock against the rate the driver asked for, ppm.
* False where the driver has no clock or has not fitted one yet. */
bool audio_driver_get_device_clock_ppm(double *ppm);
extern audio_driver_t *audio_drivers[];
RETRO_END_DECLS
#endif /* __AUDIO_DRIVER__H */