Files
shairport-sync/audio.h
T
Mike Brady 60143518c2 This squashed commit comprises a long series of improvements, bug fixes, optimizations, and new feature additions:
- 48,000 frames per second operation,
 - 48k lossless stereo, 5.1 and 7.1 surround sound
 - Multichannel and multi rate operation on ALSA, PipeWire, PulseAudio, FreeBSD, stdout and unix pipe output backends.

Automatic, flexible and controllable output format (rate, sample format and channel count) selection.

Full FFmpeg integration to support transcoding, resampling, and new audio formats.

Better operation on lower powered devices down to e.g. Raspberry Pi B.

Reduced Docker image sizes with a slimmed-down FFmpeg library.

Enhanced timestamp handling for better synchronization.

Improved the sync error calculation.

A new "vernier" resampling and interpolation method for low-power CPUs.

Bug fixes and minor enhancements.

Note -- there are many breaking changes from previous versions of Shairport Sync!
2025-02-23 13:31:17 +00:00

118 lines
4.5 KiB
C

#ifndef _AUDIO_H
#define _AUDIO_H
#include <libconfig.h>
#include <stdint.h>
// clang-format off
// Play samples provided may be from the source, in which case they will be timed
// or they may be generated by Shairport Sync, in which case they will not be timed.
// Typically these would be samples of silence, which may be dithered, sent during the lead-in to
// the start of the material, or inserted instead of a missing frame, or after a flush.
// clang-format on
typedef enum {
play_samples_are_untimed = 0, // typically the samples are (possibly dithered) silence
play_samples_are_timed, // timed and numbered.
} play_samples_type;
typedef struct {
unsigned int channels;
unsigned int rate;
unsigned int format; // this contains an sps_format_t enum but "common.h" is not imported here.
char short_description[32]; // e.g. S32/44100/8.
char channel_map[128];
} output_configuration_t;
typedef struct {
int32_t minimum_volume_dB;
int32_t maximum_volume_dB;
} volume_range_t;
typedef struct {
volume_range_t *volume_range;
} output_parameters_t;
// backend interface
typedef struct {
// may be NULL if no implemented
void (*help)(void);
char *name;
// start of program
int (*init)(int argc, char **argv);
// at end of program
void (*deinit)(void);
int (*prepare)(void); // send when a play session is about to begin
// Get an encoded configuration for the given channels, rate and depth
// The response may have a different rate, format and channel count!
// See FROM_ENCODED_FORMAL macros in common.h for the encoding scheme
// An encoded configuration will always be positive.
// 0 if not successful
// may be NULL if not implemented
// sps_format is not typed because the definition is in common.h, which can't be included here,
// sigh.
int32_t (*get_configuration)(unsigned int channels, unsigned int rate, unsigned int sps_format);
// Set the output configuration
// Returns 0 and a channel map (if available) if successful
// may be NULL if not implemented.
// Set channel_map to NULL if you don't want it.
// Otherwise, a space-separated channel map string will be returned
// and you are responsible for freeing it.
// If there isn't a channel map a NULL will be returned.
int (*configure)(int32_t encoded_output_format, char **channel_map);
void (*start)(int sample_rate, int sample_format);
// block of samples
int (*play)(void *buf, int samples, int sample_type, uint32_t timestamp, uint64_t playtime);
void (*stop)(void);
// may be NULL if no implemented
int (*is_running)(
void); // if implemented, will return 0 if everything is okay, non-zero otherwise
// may be NULL if no implemented
void (*flush)(void);
// returns the delay before the next frame to be sent to the device would actually be audible.
// almost certainly wrong if the buffer is empty, so play silent buffers to make it busy.
// will change dynamically, so keep watching it.
// returns a negative error code if there's a problem
int (*delay)(long *the_delay); // snd_pcm_sframes_t is a long
int (*stats)(uint64_t *raw_measurement_time, uint64_t *corrected_measurement_time,
uint64_t *delay,
uint64_t *frames_sent_to_dac); // use this to get the true rate of the DAC
// may be NULL, in which case soft volume is applied
void (*volume)(double vol);
// may be NULL, in which case defaults are used
output_parameters_t *(*parameters)();
// may be NULL, in which case software muting is used.
// also, will return a 1 if it is actually using the mute facility, 0 otherwise
int (*mute)(int do_mute);
} audio_output;
// this looks for a suitable configuration in the right order and checks possible
// configurations using the check_configuration method passed in.
int32_t search_for_suitable_configuration(
unsigned int channels, unsigned int rate, unsigned int format,
int (*check_configuration)(unsigned int channels, unsigned int rate, unsigned int format));
audio_output *audio_get_output(const char *name);
void audio_ls_outputs(void);
void parse_audio_options(const char *named_stanza, uint32_t default_format_set,
uint32_t default_rate_set,
uint32_t default_channel_set); // look in "general" and in the named stanza
uint32_t get_format_settings(const char *stanza_name, const char *setting_name);
uint32_t get_rate_settings(const char *stanza_name, const char *setting_name);
uint32_t get_channel_settings(const char *stanza_name, const char *setting_name);
#endif //_AUDIO_H