xine-lib 1.2.13-20230125hg15249
Data Structures | Macros | Functions | Variables
audio_out.c File Reference

xine-lib audio output implementation More...

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
#include <unistd.h>
#include <pthread.h>
#include <inttypes.h>
#include <sys/time.h>
#include <xine/xine_internal.h>
#include <xine/xineutils.h>
#include <xine/audio_out.h>
#include <xine/resample.h>
#include <xine/metronom.h>
#include "xine_private.h"

Data Structures

struct  resample_sync_t
 
struct  sIIRCoefficients
 
struct  audio_fifo_s
 
struct  aos_t
 

Macros

#define XINE_ENABLE_EXPERIMENTAL_FEATURES
 
#define LOG_MODULE   "audio_out"
 
#define LOG_VERBOSE
 
#define LOG_RESAMPLE_SYNC   0
 
#define NUM_AUDIO_BUFFERS   32
 
#define AUDIO_BUF_SIZE   32768
 
#define SYNC_TIME_INTERVAL   (1 * 90000)
 
#define SYNC_BUF_INTERVAL   NUM_AUDIO_BUFFERS / 2
 
#define RESAMPLE_SYNC_WINDOW   50
 
#define RESAMPLE_MAX_GAP_DIFF   150
 
#define RESAMPLE_REDUCE_GAP_THRESHOLD   200
 
#define EQ_BANDS   10
 
#define EQ_CHANNELS   8
 
#define FP_FRBITS   28
 
#define EQ_REAL(x)   ((int)((x) * (1 << FP_FRBITS)))
 
#define STREAMS_DEFAULT_SIZE   32
 
#define _AO_FLAG_PAUSE   1
 
#define _AO_FLAG_SILENT_TRICK   2
 
#define EI_RING_SIZE   128 /* 2^n please */
 
#define GAP_RING_LD   3
 
#define GAP_RING_SIZE   (1 << GAP_RING_LD)
 
#define GAP_RING_MASK   (GAP_RING_SIZE - 1)
 
#define RESEND_BUF_SIZE   (1 << 20)
 
#define sat16(v)   (((v + 0x8000) & ~0xffff) ? ((v) >> 31) ^ 0x7fff : (v))
 

Functions

static void ao_dbuf_reset (aos_t *this)
 
static void ao_dbuf_set_min (aos_t *this, int32_t samples)
 
static void ao_dbuf_set_max (aos_t *this, int32_t samples)
 
static void ao_gap_ring_reset (aos_t *this)
 
static int ao_gap_ring_add (aos_t *this, int gap)
 
static uint32_t uint_sqrt (uint32_t v)
 
static void ao_eq_update (aos_t *this)
 
static void ao_resend_init (aos_t *this)
 
static int ao_update_resample_factor (aos_t *this)
 
static void ao_driver_lock (aos_t *this)
 
static void ao_new_speed_trick (aos_t *this)
 
static int ao_driver_lock_2 (aos_t *this)
 
static void ao_driver_unlock (aos_t *this)
 
static void ao_flush_driver (aos_t *this)
 
static void ao_driver_test_intr (aos_t *this)
 
static int ao_driver_test_intr_2 (aos_t *this)
 
static int ao_set_property (xine_audio_port_t *this_gen, int property, int value)
 
static void ao_streams_open (aos_t *this)
 
static void ao_streams_close (aos_t *this)
 
static void ao_streams_register (aos_t *this, xine_stream_private_t *s)
 
static int ao_streams_unregister (aos_t *this, xine_stream_private_t *s)
 
static void ao_unref_obsolete (aos_t *this)
 
static void ao_force_unref_all (aos_t *this, int lock)
 
static void ao_free_fifo_open (aos_t *this)
 
static void ao_out_fifo_open (aos_t *this)
 
static void ao_free_fifo_close (aos_t *this)
 
static void ao_out_fifo_close (aos_t *this)
 
static void ao_out_fifo_apply_vpts_step (aos_t *this, int step)
 
static void ao_out_fifo_reref_append (aos_t *this, audio_buffer_t *buf, int is_first)
 
static void ao_free_fifo_append (aos_t *this, audio_buffer_t *buf)
 
static audio_buffer_tao_out_fifo_pop_int (aos_t *this)
 
static void ao_out_fifo_signal (aos_t *this)
 
static audio_buffer_tao_out_fifo_get (aos_t *this, audio_buffer_t *buf)
 
static void ao_ticket_revoked (void *user_data, int flags)
 
static audio_buffer_tao_free_fifo_get (aos_t *this)
 
static void ao_out_fifo_manual_flush (aos_t *this)
 
static void ao_out_fifo_loop_flush (aos_t *this)
 
static void ao_resend_store (aos_t *this, audio_buffer_t *buf)
 
static int ao_fill_gap (aos_t *this, int64_t pts_len)
 
static int ao_resend_fill (aos_t *this, int64_t pts_len, int64_t end_time)
 
static void ensure_buffer_size (audio_buffer_t *buf, int bytes_per_frame, int frames)
 
static audio_buffer_tswap_frame_buffers (aos_t *this)
 
int _x_ao_mode2channels (int mode)
 
int _x_ao_channels2mode (int channels)
 
static void audio_filter_compress (aos_t *this, int16_t *mem, int num_frames)
 
static void audio_filter_amp (aos_t *this, void *buf, int num_frames)
 
static void audio_filter_equalize (aos_t *this, int16_t *data, int num_frames)
 
static audio_buffer_tprepare_samples (aos_t *this, audio_buffer_t *buf)
 
static int resample_rate_adjust (aos_t *this, int64_t gap, audio_buffer_t *buf)
 
static int ao_change_settings (aos_t *this, xine_stream_t *stream, uint32_t bits, uint32_t rate, int mode)
 
static void * ao_loop (void *this_gen)
 
int xine_get_next_audio_frame (xine_audio_port_t *this_gen, xine_audio_frame_t *frame)
 
void xine_free_audio_frame (xine_audio_port_t *this_gen, xine_audio_frame_t *frame)
 
static int ao_open (xine_audio_port_t *this_gen, xine_stream_t *s, uint32_t bits, uint32_t rate, int mode)
 
static audio_buffer_tao_get_buffer (xine_audio_port_t *this_gen)
 
static void ao_put_buffer (xine_audio_port_t *this_gen, audio_buffer_t *buf, xine_stream_t *stream)
 
static void ao_close (xine_audio_port_t *this_gen, xine_stream_t *stream)
 
static void ao_speed_change_cb (void *this_gen, int new_speed)
 
static void ao_exit (xine_audio_port_t *this_gen)
 
static uint32_t ao_get_capabilities (xine_audio_port_t *this_gen)
 
static int ao_get_property (xine_audio_port_t *this_gen, int property)
 
static int ao_control (xine_audio_port_t *this_gen, int cmd,...)
 
static void ao_flush (xine_audio_port_t *this_gen)
 
static int ao_status (xine_audio_port_t *this_gen, xine_stream_t *stream, uint32_t *bits, uint32_t *rate, int *mode)
 
static void ao_update_av_sync_method (void *this_gen, xine_cfg_entry_t *entry)
 
static void ao_update_av_fine_sync_method (void *this_gen, xine_cfg_entry_t *entry)
 
static void ao_update_ptoffs (void *this_gen, xine_cfg_entry_t *entry)
 
static void ao_update_slow_fast (void *this_gen, xine_cfg_entry_t *entry)
 
xine_audio_port_t_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only)
 Initialise the audio_out sync routines.
 

Variables

static const sIIRCoefficients iir_cf []
 

Detailed Description

xine-lib audio output implementation

Date
2001-08-20 First implementation of Audio sync and Audio driver separation. (c) 2001 James Courtier-Dutton james.nosp@m.@sup.nosp@m.erbug.nosp@m..dem.nosp@m.on.co.nosp@m..uk
2001-08-22 James imported some useful AC3 sections from the previous ALSA driver. (c) 2001 Andy Lo A Foe andy@.nosp@m.alsa.nosp@m.playe.nosp@m.r.or.nosp@m.g

General Programming Guidelines: - New concept of an "audio_frame". An audio_frame consists of all the samples required to fill every audio channel to a full amount of bits. So, it does not mater how many bits per sample, or how many audio channels are being used, the number of audio_frames is the same. E.g. 16 bit stereo is 4 bytes, but one frame. 16 bit 5.1 surround is 12 bytes, but one frame. The purpose of this is to make the audio_sync code a lot more readable, rather than having to multiply by the amount of channels all the time when dealing with audio_bytes instead of audio_frames.

The number of samples passed to/from the audio driver is also sent in units of audio_frames.

Currently, James has tested with OSS: Standard stereo out, SPDIF PCM, SPDIF AC3 ALSA: Standard stereo out No testing has been done of ALSA SPDIF AC3 or any 4,5,5.1 channel output. Currently, I don't think resampling functions, as I cannot test it.

equalizer based on

PCM time-domain equalizer

Copyright (C) 2002 Felipe Rivera <liebremx at users sourceforge net>

heavily modified by guenter bartsch 2003 for use in libxine

Macro Definition Documentation

◆ _AO_FLAG_PAUSE

#define _AO_FLAG_PAUSE   1

Referenced by ao_loop(), and ao_new_speed_trick().

◆ _AO_FLAG_SILENT_TRICK

#define _AO_FLAG_SILENT_TRICK   2

Referenced by ao_loop(), and ao_new_speed_trick().

◆ AUDIO_BUF_SIZE

#define AUDIO_BUF_SIZE   32768

Referenced by _x_ao_new_port(), and ao_fill_gap().

◆ EI_RING_SIZE

#define EI_RING_SIZE   128 /* 2^n please */

Referenced by _x_ao_new_port(), and ao_loop().

◆ EQ_BANDS

#define EQ_BANDS   10

◆ EQ_CHANNELS

#define EQ_CHANNELS   8

◆ EQ_REAL

#define EQ_REAL ( x)    ((int)((x) * (1 << FP_FRBITS)))

Referenced by ao_eq_update().

◆ FP_FRBITS

#define FP_FRBITS   28

Referenced by audio_filter_equalize().

◆ GAP_RING_LD

#define GAP_RING_LD   3

◆ GAP_RING_MASK

#define GAP_RING_MASK   (GAP_RING_SIZE - 1)

Referenced by ao_gap_ring_add().

◆ GAP_RING_SIZE

#define GAP_RING_SIZE   (1 << GAP_RING_LD)

Referenced by ao_gap_ring_reset().

◆ LOG_MODULE

#define LOG_MODULE   "audio_out"

Referenced by ao_dbuf_set_max().

◆ LOG_RESAMPLE_SYNC

#define LOG_RESAMPLE_SYNC   0

Referenced by resample_rate_adjust().

◆ LOG_VERBOSE

#define LOG_VERBOSE

◆ NUM_AUDIO_BUFFERS

#define NUM_AUDIO_BUFFERS   32

◆ RESAMPLE_MAX_GAP_DIFF

#define RESAMPLE_MAX_GAP_DIFF   150

Referenced by resample_rate_adjust().

◆ RESAMPLE_REDUCE_GAP_THRESHOLD

#define RESAMPLE_REDUCE_GAP_THRESHOLD   200

Referenced by resample_rate_adjust().

◆ RESAMPLE_SYNC_WINDOW

#define RESAMPLE_SYNC_WINDOW   50

Referenced by resample_rate_adjust().

◆ RESEND_BUF_SIZE

#define RESEND_BUF_SIZE   (1 << 20)

Referenced by ao_resend_init().

◆ sat16

#define sat16 ( v)    (((v + 0x8000) & ~0xffff) ? ((v) >> 31) ^ 0x7fff : (v))

Referenced by audio_filter_equalize().

◆ STREAMS_DEFAULT_SIZE

#define STREAMS_DEFAULT_SIZE   32

Referenced by ao_streams_open().

◆ SYNC_BUF_INTERVAL

#define SYNC_BUF_INTERVAL   NUM_AUDIO_BUFFERS / 2

Referenced by ao_loop().

◆ SYNC_TIME_INTERVAL

#define SYNC_TIME_INTERVAL   (1 * 90000)

Referenced by ao_loop().

◆ XINE_ENABLE_EXPERIMENTAL_FEATURES

#define XINE_ENABLE_EXPERIMENTAL_FEATURES

Function Documentation

◆ _x_ao_channels2mode()

int _x_ao_channels2mode ( int channels)

◆ _x_ao_mode2channels()

int _x_ao_mode2channels ( int mode)

◆ _x_ao_new_port()

xine_audio_port_t * _x_ao_new_port ( xine_t * xine,
ao_driver_t * driver,
int grab_only )

◆ ao_change_settings()

static int ao_change_settings ( aos_t * this,
xine_stream_t * stream,
uint32_t bits,
uint32_t rate,
int mode )
static

◆ ao_close()

static void ao_close ( xine_audio_port_t * this_gen,
xine_stream_t * stream )
static

◆ ao_control()

static int ao_control ( xine_audio_port_t * this_gen,
int cmd,
... )
static

References ao_driver_lock(), and ao_driver_unlock().

Referenced by _x_ao_new_port().

◆ ao_dbuf_reset()

static void ao_dbuf_reset ( aos_t * this)
static

References aos_t::dbuf_max.

Referenced by ao_loop(), and ao_open().

◆ ao_dbuf_set_max()

static void ao_dbuf_set_max ( aos_t * this,
int32_t samples )
static

References LOG_MODULE, XINE_VERBOSITY_DEBUG, and xprintf.

Referenced by ao_loop().

◆ ao_dbuf_set_min()

static void ao_dbuf_set_min ( aos_t * this,
int32_t samples )
static

Referenced by ao_loop().

◆ ao_driver_lock()

static void ao_driver_lock ( aos_t * this)
static

◆ ao_driver_lock_2()

static int ao_driver_lock_2 ( aos_t * this)
inlinestatic

References ao_new_speed_trick().

Referenced by ao_loop().

◆ ao_driver_test_intr()

static void ao_driver_test_intr ( aos_t * this)
static

Referenced by ao_loop().

◆ ao_driver_test_intr_2()

static int ao_driver_test_intr_2 ( aos_t * this)
static

Referenced by ao_fill_gap(), and ao_resend_fill().

◆ ao_driver_unlock()

static void ao_driver_unlock ( aos_t * this)
static

◆ ao_eq_update()

static void ao_eq_update ( aos_t * this)
static

References EQ_BANDS, EQ_REAL, and input().

Referenced by ao_set_property(), and ao_update_resample_factor().

◆ ao_exit()

static void ao_exit ( xine_audio_port_t * this_gen)
static

◆ ao_fill_gap()

static int ao_fill_gap ( aos_t * this,
int64_t pts_len )
static

◆ ao_flush()

static void ao_flush ( xine_audio_port_t * this_gen)
static

◆ ao_flush_driver()

static void ao_flush_driver ( aos_t * this)
static

◆ ao_force_unref_all()

static void ao_force_unref_all ( aos_t * this,
int lock )
static

◆ ao_free_fifo_append()

static void ao_free_fifo_append ( aos_t * this,
audio_buffer_t * buf )
static

◆ ao_free_fifo_close()

static void ao_free_fifo_close ( aos_t * this)
static

References NULL.

Referenced by ao_exit().

◆ ao_free_fifo_get()

static audio_buffer_t * ao_free_fifo_get ( aos_t * this)
static

◆ ao_free_fifo_open()

static void ao_free_fifo_open ( aos_t * this)
static

References NULL.

Referenced by _x_ao_new_port().

◆ ao_gap_ring_add()

static int ao_gap_ring_add ( aos_t * this,
int gap )
static

References GAP_RING_LD, and GAP_RING_MASK.

Referenced by ao_loop().

◆ ao_gap_ring_reset()

static void ao_gap_ring_reset ( aos_t * this)
static

References GAP_RING_SIZE.

Referenced by _x_ao_new_port(), and ao_loop().

◆ ao_get_buffer()

static audio_buffer_t * ao_get_buffer ( xine_audio_port_t * this_gen)
static

◆ ao_get_capabilities()

static uint32_t ao_get_capabilities ( xine_audio_port_t * this_gen)
static

◆ ao_get_property()

static int ao_get_property ( xine_audio_port_t * this_gen,
int property )
static

◆ ao_loop()

static void * ao_loop ( void * this_gen)
static

◆ ao_new_speed_trick()

static void ao_new_speed_trick ( aos_t * this)
static

◆ ao_open()

static int ao_open ( xine_audio_port_t * this_gen,
xine_stream_t * s,
uint32_t bits,
uint32_t rate,
int mode )
static

◆ ao_out_fifo_apply_vpts_step()

static void ao_out_fifo_apply_vpts_step ( aos_t * this,
int step )
static

References audio_buffer_s::next, and audio_buffer_s::vpts.

Referenced by ao_loop().

◆ ao_out_fifo_close()

static void ao_out_fifo_close ( aos_t * this)
static

References NULL, and NUM_AUDIO_BUFFERS.

Referenced by ao_exit().

◆ ao_out_fifo_get()

static audio_buffer_t * ao_out_fifo_get ( aos_t * this,
audio_buffer_t * buf )
static

◆ ao_out_fifo_loop_flush()

static void ao_out_fifo_loop_flush ( aos_t * this)
static

References ao_flush_driver().

Referenced by ao_flush(), and ao_open().

◆ ao_out_fifo_manual_flush()

static void ao_out_fifo_manual_flush ( aos_t * this)
static

References NULL.

Referenced by ao_set_property().

◆ ao_out_fifo_open()

static void ao_out_fifo_open ( aos_t * this)
static

References NULL, and NUM_AUDIO_BUFFERS.

Referenced by _x_ao_new_port().

◆ ao_out_fifo_pop_int()

static audio_buffer_t * ao_out_fifo_pop_int ( aos_t * this)
static

◆ ao_out_fifo_reref_append()

static void ao_out_fifo_reref_append ( aos_t * this,
audio_buffer_t * buf,
int is_first )
static

◆ ao_out_fifo_signal()

static void ao_out_fifo_signal ( aos_t * this)
static

◆ ao_put_buffer()

static void ao_put_buffer ( xine_audio_port_t * this_gen,
audio_buffer_t * buf,
xine_stream_t * stream )
static

◆ ao_resend_fill()

static int ao_resend_fill ( aos_t * this,
int64_t pts_len,
int64_t end_time )
static

◆ ao_resend_init()

static void ao_resend_init ( aos_t * this)
static

◆ ao_resend_store()

static void ao_resend_store ( aos_t * this,
audio_buffer_t * buf )
static

◆ ao_set_property()

static int ao_set_property ( xine_audio_port_t * this_gen,
int property,
int value )
static

◆ ao_speed_change_cb()

static void ao_speed_change_cb ( void * this_gen,
int new_speed )
static

◆ ao_status()

static int ao_status ( xine_audio_port_t * this_gen,
xine_stream_t * stream,
uint32_t * bits,
uint32_t * rate,
int * mode )
static

◆ ao_streams_close()

static void ao_streams_close ( aos_t * this)
static

References _x_freep(), and xine_rwlock_destroy.

Referenced by ao_exit().

◆ ao_streams_open()

static void ao_streams_open ( aos_t * this)
static

◆ ao_streams_register()

static void ao_streams_register ( aos_t * this,
xine_stream_private_t * s )
static

◆ ao_streams_unregister()

static int ao_streams_unregister ( aos_t * this,
xine_stream_private_t * s )
static

◆ ao_ticket_revoked()

static void ao_ticket_revoked ( void * user_data,
int flags )
static

References user_data(), XINE_VERBOSITY_DEBUG, and xprintf.

Referenced by _x_ao_new_port(), and ao_exit().

◆ ao_unref_obsolete()

static void ao_unref_obsolete ( aos_t * this)
static

◆ ao_update_av_fine_sync_method()

static void ao_update_av_fine_sync_method ( void * this_gen,
xine_cfg_entry_t * entry )
static

References xine_cfg_entry_s::num_value.

Referenced by _x_ao_new_port().

◆ ao_update_av_sync_method()

static void ao_update_av_sync_method ( void * this_gen,
xine_cfg_entry_t * entry )
static

References lprintf, and xine_cfg_entry_s::num_value.

Referenced by _x_ao_new_port().

◆ ao_update_ptoffs()

static void ao_update_ptoffs ( void * this_gen,
xine_cfg_entry_t * entry )
static

◆ ao_update_resample_factor()

static int ao_update_resample_factor ( aos_t * this)
static

◆ ao_update_slow_fast()

static void ao_update_slow_fast ( void * this_gen,
xine_cfg_entry_t * entry )
static

◆ audio_filter_amp()

static void audio_filter_amp ( aos_t * this,
void * buf,
int num_frames )
static

References input(), INT16_MAX, INT16_MIN, INT8_MAX, and INT8_MIN.

Referenced by prepare_samples().

◆ audio_filter_compress()

static void audio_filter_compress ( aos_t * this,
int16_t * mem,
int num_frames )
static

References abs, and lprintf.

Referenced by prepare_samples().

◆ audio_filter_equalize()

static void audio_filter_equalize ( aos_t * this,
int16_t * data,
int num_frames )
static

◆ ensure_buffer_size()

static void ensure_buffer_size ( audio_buffer_t * buf,
int bytes_per_frame,
int frames )
static

◆ prepare_samples()

static audio_buffer_t * prepare_samples ( aos_t * this,
audio_buffer_t * buf )
static

◆ resample_rate_adjust()

static int resample_rate_adjust ( aos_t * this,
int64_t gap,
audio_buffer_t * buf )
static

◆ swap_frame_buffers()

static audio_buffer_t * swap_frame_buffers ( aos_t * this)
static

Referenced by prepare_samples().

◆ uint_sqrt()

static uint32_t uint_sqrt ( uint32_t v)
static

References v.

Referenced by ao_update_resample_factor().

◆ xine_free_audio_frame()

void xine_free_audio_frame ( xine_audio_port_t * this_gen,
xine_audio_frame_t * frame )

References ao_free_fifo_append().

◆ xine_get_next_audio_frame()

int xine_get_next_audio_frame ( xine_audio_port_t * this_gen,
xine_audio_frame_t * frame )

Variable Documentation

◆ iir_cf

const sIIRCoefficients iir_cf[]
static
Initial value:
= {
{ ((int)(( 9.9691562441e-01 ) * (1 << 28 ))), ((int)(( 1.5421877947e-03 ) * (1 << 28 ))), ((int)(( 1.9968961468e+00 ) * (1 << 28 ))) },
{ ((int)(( 9.9384077546e-01 ) * (1 << 28 ))), ((int)(( 3.0796122698e-03 ) * (1 << 28 ))), ((int)(( 1.9937629855e+00 ) * (1 << 28 ))) },
{ ((int)(( 9.8774277725e-01 ) * (1 << 28 ))), ((int)(( 6.1286113769e-03 ) * (1 << 28 ))), ((int)(( 1.9874275518e+00 ) * (1 << 28 ))) },
{ ((int)(( 9.7522112569e-01 ) * (1 << 28 ))), ((int)(( 1.2389437156e-02 ) * (1 << 28 ))), ((int)(( 1.9739682661e+00 ) * (1 << 28 ))) },
{ ((int)(( 9.5105628526e-01 ) * (1 << 28 ))), ((int)(( 2.4471857368e-02 ) * (1 << 28 ))), ((int)(( 1.9461077269e+00 ) * (1 << 28 ))) },
{ ((int)(( 9.0450844499e-01 ) * (1 << 28 ))), ((int)(( 4.7745777504e-02 ) * (1 << 28 ))), ((int)(( 1.8852109613e+00 ) * (1 << 28 ))) },
{ ((int)(( 8.1778971701e-01 ) * (1 << 28 ))), ((int)(( 9.1105141497e-02 ) * (1 << 28 ))), ((int)(( 1.7444877599e+00 ) * (1 << 28 ))) },
{ ((int)(( 6.6857185264e-01 ) * (1 << 28 ))), ((int)(( 1.6571407368e-01 ) * (1 << 28 ))), ((int)(( 1.4048592171e+00 ) * (1 << 28 ))) },
{ ((int)(( 4.4861333678e-01 ) * (1 << 28 ))), ((int)(( 2.7569333161e-01 ) * (1 << 28 ))), ((int)(( 6.0518718075e-01 ) * (1 << 28 ))) },
{ ((int)(( 2.4201241845e-01 ) * (1 << 28 ))), ((int)(( 3.7899379077e-01 ) * (1 << 28 ))), ((int)(( -8.0847117831e-01 ) * (1 << 28 ))) },
}

Referenced by audio_filter_equalize().