mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
The driver stage of a staged content load leaves the audio driver out when its init would open the same device the same way for the next core - same driver, device, output rate, latency, resampler and threading, no DSP filter, time stretch or core audio callback, and the core's float and multi-channel entries as they were. The device, pipeline and mixer keep running through the rebuild of the rest; once the video driver has settled the rates, the new core's rate is set in place and the stream reset a core swap needs is done. When the rate cannot be taken in place, the driver is opened again, the device kept across as before. The driver lookup of the stage leaves a carried driver's table alone. The content_load harness's close keeps its tone playing with the device never stopped, and a load with time stretch on sets the device aside and takes it back.
1780 lines
81 KiB
C
1780 lines
81 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>
|
|
/* Declarations only, with or without threads: the state holds lock and
|
|
* condition pointers either way. Declaring the types here instead would
|
|
* repeat typedefs a C89 compiler refuses once a file includes both. */
|
|
#include <rthreads/rthreads.h>
|
|
#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)
|
|
|
|
/* Output frames of played audio kept for the pause tail. Must hold the
|
|
* longest period the tail search may pick plus the window it is matched
|
|
* over, which at 48kHz is about 21ms and 3ms respectively. */
|
|
#define AUDIO_PAUSE_HIST_FRAMES 2048
|
|
|
|
RETRO_BEGIN_DECLS
|
|
|
|
/* The DSP filter and the record tap are published with pointer atomics
|
|
* and retired once no pass that could have read them is still running:
|
|
* a holder of the state lock counts itself in and out of pass_seq. A
|
|
* backend without pointer atomics changes them under the lock. */
|
|
#if defined(HAVE_THREADS) && defined(RETRO_ATOMIC_HAS_PTR)
|
|
#define AUDIO_DRIVER_PASS_EPOCH
|
|
typedef retro_atomic_ptr_t audio_driver_ptr_t;
|
|
#define AUDIO_DRIVER_PTR_GET(p) retro_atomic_load_acquire_ptr(p)
|
|
#define AUDIO_DRIVER_PTR_SET(p, v) retro_atomic_store_release_ptr(p, v)
|
|
#else
|
|
typedef void *audio_driver_ptr_t;
|
|
#define AUDIO_DRIVER_PTR_GET(p) (*(p))
|
|
#define AUDIO_DRIVER_PTR_SET(p, v) (*(p) = (v))
|
|
#endif
|
|
|
|
#ifdef HAVE_AUDIOMIXER
|
|
typedef struct audio_mixer_stream
|
|
{
|
|
audio_mixer_sound_t *handle;
|
|
audio_mixer_voice_t *voice;
|
|
/* What the table does once the play has finished; run by the table's
|
|
* holder, never by the mix. */
|
|
audio_mixer_stop_cb_t stop_cb;
|
|
void *buf;
|
|
char *name;
|
|
size_t bufsize;
|
|
size_t play_serial; /* the voice's play, for a stop to recognise it */
|
|
float volume;
|
|
unsigned play_tag; /* the sound's tag while it plays, 0 when not */
|
|
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
|
|
|
|
/* What a driver's own device thread was scheduled under */
|
|
enum audio_thread_grant
|
|
{
|
|
AUDIO_THREAD_GRANT_NONE = 0, /* no such thread */
|
|
AUDIO_THREAD_GRANT_NORMAL, /* not raised */
|
|
AUDIO_THREAD_GRANT_REFUSED, /* asked, refused */
|
|
AUDIO_THREAD_GRANT_RAISED, /* a higher priority */
|
|
AUDIO_THREAD_GRANT_MMCSS /* the MMCSS Pro Audio class */
|
|
};
|
|
|
|
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);
|
|
|
|
/* What the driver's own device thread was scheduled under, for the
|
|
* statistics overlay; read from any thread. NULL where a driver
|
|
* runs no thread of its own. */
|
|
enum audio_thread_grant (*thread_grant)(void *data);
|
|
|
|
/* Optional pair, for a driver whose write() front is a buffer the
|
|
* frontend can produce into directly. write_begin lends the
|
|
* contiguous writable span at that buffer's head - up to len bytes
|
|
* of the driver's output format, possibly fewer, 0 when nothing is
|
|
* free or the driver cannot lend right now - without blocking and
|
|
* without publishing anything. The span is the frontend's until
|
|
* the matching write_end, which publishes its first len bytes (0
|
|
* abandons the lend) and returns them. At most one lend may be
|
|
* outstanding, and write() must not be called between the two.
|
|
* The threaded pipeline takes the pair after wait_writable() has
|
|
* reported the room, so the resampler and the format conversion
|
|
* land their output in the driver's own buffer instead of being
|
|
* copied into it; a driver without a lendable front leaves both
|
|
* NULL and keeps the copy inside write(). */
|
|
size_t (*write_begin)(void *data, size_t len, void **region);
|
|
ssize_t (*write_end)(void *data, size_t len);
|
|
} audio_driver_t;
|
|
|
|
/* What a driver's device-clock word holds until it has an estimate.
|
|
* Every estimate is kept inside +-100000 ppm, so the estimate and
|
|
* whether there is one share one int: one store publishes, one load
|
|
* reads, and no reader can pair a flag with a stale value. */
|
|
#define AUDIO_CLOCK_PPM_NONE (-0x7FFFFFFF - 1)
|
|
|
|
/* 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 audio_record_source *record_source;
|
|
#if defined(HAVE_RECORD_MEDIACODEC) || defined(RECORD_AUDIO_TAP_TEST)
|
|
audio_driver_ptr_t record_tap; /* struct record_audio_tap */
|
|
/* Taken out of record_tap, not yet past the passes that saw it. */
|
|
struct record_audio_tap *record_tap_detached;
|
|
#endif
|
|
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
|
|
audio_driver_ptr_t dsp; /* retro_dsp_filter_t */
|
|
/* Filters swapped out while a pass may still run them; the main
|
|
* thread's, each freed once pass_seq has moved off dsp_retired_seq. */
|
|
retro_dsp_filter_t *dsp_retired[4];
|
|
#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. An atomic and not a volatile bool: volatile orders nothing
|
|
* between the two, so the producer had no guarantee of seeing the
|
|
* consumer's last word at all. */
|
|
retro_atomic_int_t 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. */
|
|
/**
|
|
* Made only where the atomics have no pointer operations, which
|
|
* holds the DSP filter, the record tap and the mixer's table under
|
|
* it; see audio_driver_state_lock().
|
|
*/
|
|
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 slowmotion ratio setting, published alongside
|
|
* runloop_snapshot as the float's bit pattern, so the value the
|
|
* consumer applies is bit-for-bit the one the main thread read.
|
|
* Meaningful only when AUDIO_SNAP_SLOWMOTION is set, like the
|
|
* setting itself. */
|
|
retro_atomic_int_t runloop_slowmotion_bits;
|
|
/* The fast-forward ratio the main thread last published, override
|
|
* already resolved against the setting; the seed of the speed
|
|
* estimate reads it on the submit path. Bit pattern of a float. */
|
|
retro_atomic_int_t runloop_ffratio_bits;
|
|
/* 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.
|
|
* Producers construct frames directly in writable ring spans, and
|
|
* the consumer renders them where they lie. */
|
|
unsigned pipe_channels;
|
|
unsigned pipe_layout; /* producer-only requested layout */
|
|
/* The output rate setting as of the driver's init - what the device
|
|
* was asked to open at. The flush's sink accounting divides by it,
|
|
* and the flush runs on the pipeline consumer, so it is latched
|
|
* here rather than read from settings there; a changed setting
|
|
* reaches it through the reinit that makes it real. */
|
|
unsigned out_rate;
|
|
/* The latency, in ms, the threaded pipeline's ring was sized with;
|
|
* an input rate change resizes it with the same. */
|
|
unsigned pipe_latency;
|
|
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;
|
|
bool pipe_menu_active;
|
|
bool pipe_menu_reset;
|
|
/* Main thread: the publish waited for room since the last
|
|
* audio_driver_publish_runloop(), which takes it into the snapshot */
|
|
bool writer_held;
|
|
/* How the consumer fared against the core after priming, said once
|
|
* at teardown beside the driver's silence count: the passes that
|
|
* found the pipe short and had to wait for the core, the longest
|
|
* such wait, and the least the pipe held at the start of a pass
|
|
* (kept as frames + 1, so zero is no pass yet). Consumer writes,
|
|
* the main thread reads at teardown. */
|
|
retro_atomic_size_t pipe_source_waits;
|
|
retro_atomic_size_t pipe_source_wait_max_us;
|
|
retro_atomic_size_t pipe_held_min1;
|
|
/* 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;
|
|
/* Odd while a holder of the state lock - a pass - runs. */
|
|
retro_atomic_int_t pass_seq;
|
|
/* The last flush's core format, for the mixer off the flush's thread. */
|
|
retro_atomic_int_t core_float_seen;
|
|
#ifdef HAVE_DSP_FILTER
|
|
/* What the filter allows, for readers outside a pass: 0 none, 1 a
|
|
* float-only filter, 2 one with an int16 path. */
|
|
retro_atomic_int_t dsp_caps;
|
|
int dsp_retired_seq;
|
|
#endif
|
|
#ifdef HAVE_AUDIOMIXER
|
|
/* mixer_streams[] is changed by the main and task threads holding
|
|
* mixer_table_owner (AUDIO_MIXER_TABLE_*), and never by the mix: a
|
|
* play the mix finishes leaves its tag in mixer_finished[] and bumps
|
|
* mixer_finish_seq, and the table's next holder settles it. */
|
|
retro_eventcount_t mixer_table_ec;
|
|
retro_atomic_int_t mixer_table_owner;
|
|
retro_atomic_int_t mixer_finished[AUDIO_MIXER_MAX_SYSTEM_STREAMS];
|
|
retro_atomic_int_t mixer_finish_seq;
|
|
retro_atomic_int_t mixer_finish_seen;
|
|
retro_atomic_int_t mixer_streams_playing; /* written by the holder */
|
|
unsigned mixer_install_seq;
|
|
bool mixer_table_ec_ok;
|
|
#endif
|
|
bool mute_enable;
|
|
#ifdef HAVE_AUDIOMIXER
|
|
bool mixer_mute_enable;
|
|
#endif
|
|
|
|
/* Sample the flush delta-time when fast forwarding to find the correct ratio. */
|
|
retro_time_t last_flush_time;
|
|
/* Exponential moving averages of the flush interval and of the
|
|
* interval its audio takes at 1.0x */
|
|
retro_time_t avg_flush_delta;
|
|
double avg_expected_delta;
|
|
|
|
/* The menu's silence at Menu Frame Rate 'Display Rate' is measured
|
|
* out by the clock rather than by the content's frame: when it was
|
|
* last fed (0 = not feeding by the clock), and the fraction of a
|
|
* frame the last feed left owing. */
|
|
retro_time_t menu_feed_last;
|
|
double menu_feed_frac;
|
|
bool menu_source_enabled;
|
|
|
|
/* 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 */
|
|
/* Windows left out in a row. Not read by the frontend - it is read
|
|
* by samples/audio/sink_rate, which asserts that a stalled device
|
|
* leaves its window out rather than folding a frozen clock into the
|
|
* estimate. That is a behaviour with no other observable, so the
|
|
* counter is what makes it testable. */
|
|
unsigned sink_discarded;
|
|
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 */
|
|
|
|
/* Last stereo frame handed to the device, and how many frames of the
|
|
* next flush still have the resume ramp to apply. See
|
|
* audio_driver_pause_fade(). */
|
|
float last_out[2];
|
|
unsigned fade_in_frames;
|
|
/* A resume ramp owed to the core's first audio after the pause; the
|
|
* menu's silence in between must not spend it. */
|
|
bool fade_in_pending;
|
|
/* Rolling copy of the most recent output frames, and how much of it is
|
|
* valid. A copy of what has already gone to the device, never a delay
|
|
* line, so it costs nothing on the fast-forward path. Lets a pause be
|
|
* concealed with a continuation of the waveform rather than a decaying
|
|
* DC level. See audio_driver_pause_fade(). */
|
|
float pause_hist[AUDIO_PAUSE_HIST_FRAMES * 2];
|
|
unsigned pause_hist_pos;
|
|
unsigned pause_hist_fill;
|
|
/* Output frames still to be dropped after a pause tail has been written.
|
|
* The tail goes straight to the device, ahead of whatever the resampler
|
|
* still holds, so without this its leftovers are spliced in behind it. */
|
|
unsigned pause_mute_frames;
|
|
/* Non-zero between the pause tail and the resume ramp. Read from
|
|
* whichever thread the core hands its audio over on, hence atomic. See
|
|
* audio_driver_core_silenced(). */
|
|
retro_atomic_int_t core_silenced;
|
|
/* Set by a resume in audio_driver_pause_fade(); the first flush after it
|
|
* fills the device with silence before writing. See
|
|
* audio_driver_resume_topup(). */
|
|
bool resume_topup_pending;
|
|
|
|
/* 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 slice, a fixed region of arena_float. 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 */
|
|
/* The driver res[] was made with, on the float path. Kept here
|
|
* rather than reached for through audio_st->resampler at the
|
|
* free: these are this struct's own allocations, and the main
|
|
* resampler is a different object that need not still be there
|
|
* - when it was not, res[] was leaked. NULL on the int16 path,
|
|
* which frees through resampler_int16_free. */
|
|
const retro_resampler_t *res_drv;
|
|
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 *);
|
|
void *(*resampler_int16_sibling)(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;
|
|
/* A pause and a resume as ring positions, in the ring's own byte
|
|
* count, published by the main thread and read by the consumer. What
|
|
* the ring held at a pause is stale behind its tail: the consumer
|
|
* takes it out unplayed up to pipe_discard_to, and pipe_discard_gen
|
|
* against pipe_discard_seen, the consumer's own record, says a pause
|
|
* has been published since. The core's first audio after a resume
|
|
* starts at pipe_fade_in_at: the consumer never takes a chunk across
|
|
* it and arms the resume ramp on reaching it, through pipe_arm_fade,
|
|
* consumer thread only. pipe_fade_in_mark is (sequence << 1) | armed,
|
|
* written by the main thread alone; the consumer records the sequence
|
|
* it has acted on in pipe_fade_in_seen instead of clearing the mark,
|
|
* so a mark published while it reads is never cleared unseen. */
|
|
retro_atomic_size_t pipe_discard_to;
|
|
/* Later core publishes must survive the menu handover. */
|
|
retro_atomic_size_t pipe_menu_to;
|
|
retro_atomic_int_t pipe_discard_gen;
|
|
int pipe_discard_seen;
|
|
/* A pause's tail and a resume's reset, asked for by the main thread
|
|
* and carried out by the consumer, the only thread that writes to
|
|
* the device. Each request takes the next pipe_pause_seq into its
|
|
* own word; the consumer acts on what is newer than the pipe_*_seen
|
|
* it keeps, oldest first, and stores each once it is done.
|
|
* pipe_resume_topup says the resume's stream was down. */
|
|
retro_atomic_int_t pipe_pause_seq;
|
|
retro_atomic_int_t pipe_tail_seq;
|
|
retro_atomic_int_t pipe_resume_seq;
|
|
retro_atomic_int_t pipe_resume_topup;
|
|
retro_atomic_int_t pipe_tail_seen; /* stored by the consumer */
|
|
retro_atomic_int_t pipe_resume_seen;
|
|
/* A rate change for the consumer to install, numbered as the pause
|
|
* requests are; the producer writes nothing into the ring until it
|
|
* has (audio_driver_set_input_rate()). */
|
|
retro_atomic_int_t pipe_rate_seq;
|
|
retro_atomic_int_t pipe_rate_seen; /* stored by the consumer */
|
|
/* A transport change for the consumer to install, numbered likewise.
|
|
* pipe_transport_mode is the transport as the producer has decided
|
|
* it, which the consumer's pointers follow once it has. */
|
|
retro_atomic_int_t pipe_transport_seq;
|
|
retro_atomic_int_t pipe_transport_seen;
|
|
uint8_t pipe_transport_mode;
|
|
/* A source format change for the consumer to install, likewise; the
|
|
* producer writes nothing into the ring until it has. */
|
|
retro_atomic_int_t pipe_format_seq;
|
|
retro_atomic_int_t pipe_format_seen;
|
|
/* Without the threaded pipeline the same requests, and a format
|
|
* change and a stop's reset besides, are carried out by the thread
|
|
* that submits the core's audio (inline_owner), or by the main
|
|
* thread at once when that is the one. Whoever carries them out
|
|
* holds inline_busy, which a submit takes too; a submit that finds
|
|
* the main thread holding it drops its batch rather than wait.
|
|
* inline_req_done is the last pipe_pause_seq carried out. */
|
|
retro_atomic_int_t inline_format_seq;
|
|
retro_atomic_int_t inline_format_seen;
|
|
retro_atomic_int_t inline_format; /* (multi << 1) | floating */
|
|
retro_atomic_int_t inline_reset_seq;
|
|
retro_atomic_int_t inline_reset_seen;
|
|
retro_atomic_int_t inline_req_done;
|
|
retro_atomic_int_t inline_busy;
|
|
retro_atomic_size_t inline_owner; /* thread id */
|
|
retro_atomic_size_t inline_holder; /* thread id, 0 when free */
|
|
unsigned inline_depth; /* the holder's */
|
|
retro_atomic_size_t pipe_fade_in_at;
|
|
retro_atomic_int_t pipe_fade_in_mark;
|
|
unsigned pipe_fade_in_seen;
|
|
bool pipe_arm_fade;
|
|
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_pause_fade:
|
|
* @paused : true when the runloop has just paused, false when it has just
|
|
* resumed.
|
|
*
|
|
* Ramps the audio down when the core stops and back up when it starts,
|
|
* instead of ending and restarting the stream mid-waveform. The ramp down
|
|
* is written onto audio already at the device; the ramp up is applied by
|
|
* audio_driver_flush() to the first frames the core produces afterwards.
|
|
**/
|
|
void audio_driver_pause_fade(bool paused);
|
|
|
|
/**
|
|
* audio_driver_core_silenced:
|
|
*
|
|
* True between the pause tail and the resume ramp, while the frontend has
|
|
* deliberately ended the core's audio. Lets a caller that would ramp out for
|
|
* its own reasons - a state load - leave an already-down stream alone rather
|
|
* than bring it back up on the way out.
|
|
**/
|
|
bool audio_driver_core_silenced(void);
|
|
|
|
/**
|
|
* audio_driver_jump_fade_begin:
|
|
* audio_driver_jump_fade_end:
|
|
* @ramped : what _begin returned.
|
|
*
|
|
* Bracket a jump the frontend makes in the game's state - a state load, an
|
|
* undo, a core reset - with the pause tail and the resume ramp, so both the
|
|
* splice and whatever gap the work leaves behind land in silence.
|
|
*
|
|
* A stream already down - the jump was made from the menu, or while paused -
|
|
* is left alone: _begin returns false and _end then does nothing, so the ramp
|
|
* back up stays with whatever took the stream down.
|
|
**/
|
|
bool audio_driver_jump_fade_begin(void);
|
|
|
|
void audio_driver_jump_fade_end(bool ramped);
|
|
|
|
/**
|
|
* 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:
|
|
*
|
|
* Brackets a pass over the DSP filter, the record tap and the device;
|
|
* a mutex only where the atomics have no pointer operations. Cheap and
|
|
* safe to call before the audio driver is up.
|
|
**/
|
|
void audio_driver_state_lock(void);
|
|
void audio_driver_state_unlock(void);
|
|
struct record_audio_tap;
|
|
int audio_driver_record_tap_install(struct record_audio_tap *tap);
|
|
bool audio_driver_record_tap_remove(struct record_audio_tap *tap);
|
|
|
|
/* 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),
|
|
/* Settings the pipeline consumer and the flush consult, published
|
|
* with the rest so they are never read from settings off the main
|
|
* thread: Audio Sync, and Fast-Forward Frameskip's audio speedup. */
|
|
AUDIO_SNAP_SYNC = (1 << 6),
|
|
AUDIO_SNAP_FF_SPEEDUP = (1 << 7),
|
|
AUDIO_SNAP_SINK_EST = (1 << 8),
|
|
AUDIO_SNAP_FASTPATH_S16 = (1 << 9),
|
|
AUDIO_SNAP_STRETCH_LPF = (1 << 10),
|
|
/* audio_pipeline_fill_cap: see audio_driver_pipe_cap_frames() */
|
|
AUDIO_SNAP_PIPE_CAP = (1 << 11),
|
|
/* The last iteration's pace had a display source: vsync, Scanline
|
|
* Sync or the display pacing hold */
|
|
AUDIO_SNAP_DISPLAY_PACED = (1 << 12),
|
|
/* The last iteration was held by audio alone, and the threaded
|
|
* pipeline's publish waited for room in it: see
|
|
* audio_driver_compute_rate_adjust() */
|
|
AUDIO_SNAP_AUDIO_PACED = (1 << 13),
|
|
AUDIO_SNAP_WRITER_HELD = (1 << 14),
|
|
AUDIO_SNAP_MENU_SOURCE = (1 << 15)
|
|
};
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/* Main thread, once a frame: settles the plays the mix has finished. */
|
|
void audio_driver_mixer_reap(void);
|
|
|
|
/* Main-thread transport setup: snapshot initialized mixer output format.
|
|
* False with rate0/s16false when audio is unavailable. */
|
|
bool audio_driver_mixer_prepare_format(unsigned *rate, bool *s16);
|
|
|
|
bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params);
|
|
|
|
/* As add_stream, with a clock binding captured before the existing
|
|
* state lock is released. The static-pool voice stays addressable;
|
|
* compare its serial before using a later clock snapshot. Outputs
|
|
* are NULL/0 when no live voice was created. Ownership is unchanged. */
|
|
bool audio_driver_mixer_add_stream_clocked(audio_mixer_stream_params_t *params,
|
|
audio_mixer_voice_t **voice, size_t *serial);
|
|
|
|
/* Install a worker-prepared sound without reopening its decoder. Takes
|
|
* sound ownership on every outcome; params buffer/owner fields are ignored.
|
|
* Only playing states are accepted. Outputs are cleared on failure. Call
|
|
* on the main thread, as for add_stream_clocked. */
|
|
bool audio_driver_mixer_add_prepared_stream(audio_mixer_stream_params_t *params,
|
|
audio_mixer_sound_t *sound, audio_mixer_voice_t **voice, size_t *serial);
|
|
|
|
/* Session teardown: remove only the play captured at add_stream_clocked.
|
|
* Uses the existing stream-removal state lock, on the main thread. */
|
|
void audio_driver_mixer_remove_stream_clocked(unsigned i,
|
|
audio_mixer_voice_t *voice, size_t serial);
|
|
|
|
/* 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);
|
|
|
|
/* Main-thread transport request; retains queued PCM and decoder state.
|
|
* The mixer applies it at the next block boundary without waiting. */
|
|
void audio_driver_mixer_stream_set_repeat(unsigned i, bool repeat);
|
|
void audio_driver_mixer_stream_set_paused(unsigned i, bool paused);
|
|
|
|
|
|
/* 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);
|
|
|
|
/* Retain mixer voices while replacing the core audio pipeline. */
|
|
bool audio_driver_deinit_for_reinit(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
|
|
/**
|
|
* audio_driver_menu_sample:
|
|
* @by_clock : feed the silence the clock says has played since the last
|
|
* feed, rather than one content frame of it.
|
|
*
|
|
* Feeds the device silence while the core is not running behind the
|
|
* menu, with the menu sounds, the mixer and thumbnail audio mixed in.
|
|
* One content frame per call holds a blocking writer to the content's
|
|
* rate; by the clock, with a non-blocking writer, the device is kept fed
|
|
* at whatever rate the menu runs.
|
|
**/
|
|
void audio_driver_menu_sample(bool by_clock);
|
|
#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_aaudio;
|
|
extern audio_driver_t audio_jack;
|
|
extern audio_driver_t audio_sdl1;
|
|
extern audio_driver_t audio_sdl2;
|
|
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_waveout;
|
|
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_psp2;
|
|
extern audio_driver_t audio_ps4;
|
|
extern audio_driver_t audio_ps2;
|
|
extern audio_driver_t audio_ctr_csnd;
|
|
extern audio_driver_t audio_ctr_dsp;
|
|
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);
|
|
|
|
/**
|
|
* audio_driver_set_input_rate:
|
|
* @input : the core's audio rate, as driver_adjust_system_rates
|
|
* derives it.
|
|
*
|
|
* Moves the running driver to a new input rate without reopening the
|
|
* device: a resampler for the new ratio, the threaded pipeline's pass
|
|
* and ring, and the rate control threshold. The consumer is parked
|
|
* while the state changes hands.
|
|
*
|
|
* Returns: false when the configuration needs the full reinit instead
|
|
* (a DSP filter, time stretch, a core audio callback or discrete extra
|
|
* channels); nothing is changed then.
|
|
**/
|
|
bool audio_driver_set_input_rate(double input);
|
|
|
|
/* Asked before a teardown: keep the device for the next init to take
|
|
* back, when that teardown is a content switch. A device the next init
|
|
* would open differently, or that nobody takes, is freed. Off with
|
|
* RETROARCH_AUDIO_KEEP=0 in the environment. */
|
|
void audio_driver_keep_device(bool keep);
|
|
|
|
/* Frees a kept device that was not taken back. */
|
|
void audio_driver_drop_kept(void);
|
|
|
|
/* Asked before a content switch's driver stage: whether the running
|
|
* audio can be carried into the next session as it is - device,
|
|
* pipeline and mixer left up, so menu sounds play through the stage -
|
|
* because its init would open the same device the same way for the
|
|
* next core. Off with RETROARCH_AUDIO_KEEP=0, as keeping is. */
|
|
bool audio_driver_session_carry_ok(void);
|
|
|
|
/* Carries the running audio into the next session at @input Hz: the
|
|
* rate in place, and the stream reset that a core swap asks for.
|
|
* Returns false when the rate cannot be taken in place; the caller
|
|
* then reinits the audio driver. */
|
|
bool audio_driver_session_carry(double input);
|
|
|
|
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);
|
|
|
|
enum audio_thread_grant audio_driver_get_thread_grant(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[];
|
|
|
|
/* Takes a driver the platform turns out not to have out of
|
|
* audio_drivers[], before the configuration or the menu reads it. */
|
|
void audio_driver_list_remove(const audio_driver_t *drv);
|
|
|
|
RETRO_END_DECLS
|
|
|
|
#endif /* __AUDIO_DRIVER__H */
|