Files
shairport-sync/player.c
T

525 lines
14 KiB
C

/*
* Slave-clocked ALAC stream player. This file is part of Shairport.
* Copyright (c) James Laird 2011, 2013
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <pthread.h>
#include <openssl/aes.h>
#include <math.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <assert.h>
#include <fcntl.h>
#include "common.h"
#include "player.h"
#include "rtp.h"
#ifdef FANCY_RESAMPLING
#include <samplerate.h>
#endif
#include "alac.h"
// parameters from the source
static unsigned char *aesiv;
static AES_KEY aes;
static int sampling_rate, frame_size;
#define FRAME_BYTES (4*frame_size)
// maximal resampling shift - conservative
#define OUTFRAME_BYTES (4*(frame_size+3))
static pthread_t player_thread;
static int please_stop;
static alac_file *decoder_info;
#ifdef FANCY_RESAMPLING
static int fancy_resampling = 1;
static SRC_STATE *src;
#endif
// interthread variables
static double volume = 1.0;
static int fix_volume = 0x10000;
static pthread_mutex_t vol_mutex = PTHREAD_MUTEX_INITIALIZER;
// default buffer size
// needs to be a power of 2 because of the way BUFIDX(seqno) works
#define BUFFER_FRAMES 512
#define MAX_PACKET 2048
typedef struct audio_buffer_entry { // decoded audio packets
int ready;
signed short *data;
} abuf_t;
static abuf_t audio_buffer[BUFFER_FRAMES];
#define BUFIDX(seqno) ((seq_t)(seqno) % BUFFER_FRAMES)
// mutex-protected variables
static seq_t ab_read, ab_write;
static int ab_buffering = 1, ab_synced = 0;
static pthread_mutex_t ab_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t ab_buffer_ready = PTHREAD_COND_INITIALIZER;
static void ab_resync(void) {
int i;
for (i=0; i<BUFFER_FRAMES; i++)
audio_buffer[i].ready = 0;
ab_synced = 0;
ab_buffering = 1;
}
// the sequence numbers will wrap pretty often.
// this returns true if the second arg is after the first
static inline int seq_order(seq_t a, seq_t b) {
signed short d = b - a;
return d > 0;
}
static void alac_decode(short *dest, uint8_t *buf, int len) {
unsigned char packet[MAX_PACKET];
assert(len<=MAX_PACKET);
unsigned char iv[16];
int aeslen = len & ~0xf;
memcpy(iv, aesiv, sizeof(iv));
AES_cbc_encrypt(buf, packet, aeslen, &aes, iv, AES_DECRYPT);
memcpy(packet+aeslen, buf+aeslen, len-aeslen);
int outsize;
alac_decode_frame(decoder_info, packet, dest, &outsize);
assert(outsize == FRAME_BYTES);
}
static int init_decoder(int32_t fmtp[12]) {
alac_file *alac;
frame_size = fmtp[1]; // stereo samples
sampling_rate = fmtp[11];
int sample_size = fmtp[3];
if (sample_size != 16)
die("only 16-bit samples supported!");
alac = alac_create(sample_size, 2);
if (!alac)
return 1;
decoder_info = alac;
alac->setinfo_max_samples_per_frame = frame_size;
alac->setinfo_7a = fmtp[2];
alac->setinfo_sample_size = sample_size;
alac->setinfo_rice_historymult = fmtp[4];
alac->setinfo_rice_initialhistory = fmtp[5];
alac->setinfo_rice_kmodifier = fmtp[6];
alac->setinfo_7f = fmtp[7];
alac->setinfo_80 = fmtp[8];
alac->setinfo_82 = fmtp[9];
alac->setinfo_86 = fmtp[10];
alac->setinfo_8a_rate = fmtp[11];
alac_allocate_buffers(alac);
return 0;
}
static void free_decoder(void) {
alac_free(decoder_info);
}
#ifdef FANCY_RESAMPLING
static int init_src(void) {
int err;
if (fancy_resampling)
src = src_new(SRC_SINC_MEDIUM_QUALITY, 2, &err);
else
src = NULL;
return err;
}
static void free_src(void) {
src_delete(src);
src = NULL;
}
#endif
static void init_buffer(void) {
int i;
for (i=0; i<BUFFER_FRAMES; i++)
audio_buffer[i].data = malloc(OUTFRAME_BYTES);
ab_resync();
}
static void free_buffer(void) {
int i;
for (i=0; i<BUFFER_FRAMES; i++)
free(audio_buffer[i].data);
}
void player_put_packet(seq_t seqno, uint8_t *data, int len) {
abuf_t *abuf = 0;
short buf_fill;
pthread_mutex_lock(&ab_mutex);
if (!ab_synced) {
ab_write = seqno;
ab_read = seqno-1;
ab_synced = 1;
}
if (seqno == ab_write+1) { // expected packet
abuf = audio_buffer + BUFIDX(seqno);
ab_write = seqno;
} else if (seq_order(ab_write, seqno)) { // newer than expected
rtp_request_resend(ab_write+1, seqno-1);
abuf = audio_buffer + BUFIDX(seqno);
ab_write = seqno;
} else if (seq_order(ab_read, seqno)) { // late but not yet played
abuf = audio_buffer + BUFIDX(seqno);
} else { // too late.
warn("late packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write);
}
buf_fill = ab_write - ab_read;
pthread_mutex_unlock(&ab_mutex);
if (abuf) {
alac_decode(abuf->data, data, len);
abuf->ready = 1;
}
pthread_mutex_lock(&ab_mutex);
if (ab_buffering && buf_fill >= config.buffer_start_fill) {
debug("buffering over. starting play\n");
ab_buffering = 0;
pthread_cond_signal(&ab_buffer_ready);
}
pthread_mutex_unlock(&ab_mutex);
}
static short lcg_rand(void) {
static unsigned long lcg_prev = 12345;
lcg_prev = lcg_prev * 69069 + 3;
return lcg_prev & 0xffff;
}
static inline short dithered_vol(short sample) {
static short rand_a, rand_b;
long out;
out = (long)sample * fix_volume;
if (fix_volume < 0x10000) {
rand_b = rand_a;
rand_a = lcg_rand();
out += rand_a;
out -= rand_b;
}
return out>>16;
}
typedef struct {
double hist[2];
double a[2];
double b[3];
} biquad_t;
static void biquad_init(biquad_t *bq, double a[], double b[]) {
bq->hist[0] = bq->hist[1] = 0.0;
memcpy(bq->a, a, 2*sizeof(double));
memcpy(bq->b, b, 3*sizeof(double));
}
static void biquad_lpf(biquad_t *bq, double freq, double Q) {
double w0 = 2.0 * M_PI * freq * frame_size / (double)sampling_rate;
double alpha = sin(w0)/(2.0*Q);
double a_0 = 1.0 + alpha;
double b[3], a[2];
b[0] = (1.0-cos(w0))/(2.0*a_0);
b[1] = (1.0-cos(w0))/a_0;
b[2] = b[0];
a[0] = -2.0*cos(w0)/a_0;
a[1] = (1-alpha)/a_0;
biquad_init(bq, a, b);
}
static double biquad_filt(biquad_t *bq, double in) {
double w = in - bq->a[0]*bq->hist[0] - bq->a[1]*bq->hist[1];
double out = bq->b[1]*bq->hist[0] + bq->b[2]*bq->hist[1] + bq->b[0]*w;
bq->hist[1] = bq->hist[0];
bq->hist[0] = w;
return out;
}
static double bf_playback_rate = 1.0;
static double bf_est_drift = 0.0; // local clock is slower by
static biquad_t bf_drift_lpf;
static double bf_est_err = 0.0, bf_last_err;
static biquad_t bf_err_lpf, bf_err_deriv_lpf;
static double desired_fill;
static int fill_count;
static void bf_est_reset(short fill) {
biquad_lpf(&bf_drift_lpf, 1.0/180.0, 0.3);
biquad_lpf(&bf_err_lpf, 1.0/10.0, 0.25);
biquad_lpf(&bf_err_deriv_lpf, 1.0/2.0, 0.2);
fill_count = 0;
bf_playback_rate = 1.0;
bf_est_err = bf_last_err = 0;
desired_fill = fill_count = 0;
}
static void bf_est_update(short fill) {
if (fill_count < 1000) {
desired_fill += (double)fill/1000.0;
fill_count++;
return;
}
#define CONTROL_A (1e-4)
#define CONTROL_B (1e-1)
double buf_delta = fill - desired_fill;
bf_est_err = biquad_filt(&bf_err_lpf, buf_delta);
double err_deriv = biquad_filt(&bf_err_deriv_lpf, bf_est_err - bf_last_err);
double adj_error = CONTROL_A * bf_est_err;
bf_est_drift = biquad_filt(&bf_drift_lpf, CONTROL_B*(adj_error + err_deriv) + bf_est_drift);
debug("bf %d err %f drift %f desiring %f ed %f estd %f\n",
fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + adj_error);
bf_playback_rate = 1.0 + adj_error + bf_est_drift;
bf_last_err = bf_est_err;
}
// get the next frame, when available. return 0 if underrun/stream reset.
static short *buffer_get_frame(void) {
short buf_fill;
seq_t read;
abuf_t *abuf = 0;
unsigned short next;
int i;
pthread_mutex_lock(&ab_mutex);
buf_fill = ab_write - ab_read;
if (buf_fill < 1 || !ab_synced || ab_buffering) { // init or underrun. stop and wait
if (ab_synced)
warn("underrun.\n");
ab_buffering = 1;
pthread_cond_wait(&ab_buffer_ready, &ab_mutex);
ab_read++;
buf_fill = ab_write - ab_read;
bf_est_reset(buf_fill);
pthread_mutex_unlock(&ab_mutex);
return 0;
}
if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance
warn("overrun.\n");
ab_read = ab_write - config.buffer_start_fill;
}
read = ab_read;
ab_read++;
buf_fill = ab_write - ab_read;
bf_est_update(buf_fill);
// check if t+16, t+32, t+64, t+128, ... (buffer_start_fill / 2)
// packets have arrived... last-chance resend
if (!ab_buffering) {
for (i = 16; i < (config.buffer_start_fill / 2); i = (i * 2)) {
next = ab_read + i;
abuf = audio_buffer + BUFIDX(next);
if (!abuf->ready) {
rtp_request_resend(next, next);
}
}
}
abuf_t *curframe = audio_buffer + BUFIDX(read);
if (!curframe->ready) {
warn("missing frame.\n");
memset(curframe->data, 0, FRAME_BYTES);
}
curframe->ready = 0;
pthread_mutex_unlock(&ab_mutex);
return curframe->data;
}
static int stuff_buffer(double playback_rate, short *inptr, short *outptr) {
int i;
int stuffsamp = frame_size;
int stuff = 0;
double p_stuff;
p_stuff = 1.0 - pow(1.0 - fabs(playback_rate-1.0), frame_size);
if (rand() < p_stuff * RAND_MAX) {
stuff = playback_rate > 1.0 ? -1 : 1;
stuffsamp = rand() % (frame_size - 1);
}
pthread_mutex_lock(&vol_mutex);
for (i=0; i<stuffsamp; i++) { // the whole frame, if no stuffing
*outptr++ = dithered_vol(*inptr++);
*outptr++ = dithered_vol(*inptr++);
};
if (stuff) {
if (stuff==1) {
debug("+++++++++\n");
// interpolate one sample
*outptr++ = dithered_vol(((long)inptr[-2] + (long)inptr[0]) >> 1);
*outptr++ = dithered_vol(((long)inptr[-1] + (long)inptr[1]) >> 1);
} else if (stuff==-1) {
debug("---------\n");
inptr++;
inptr++;
}
for (i=stuffsamp; i<frame_size + stuff; i++) {
*outptr++ = dithered_vol(*inptr++);
*outptr++ = dithered_vol(*inptr++);
}
}
pthread_mutex_unlock(&vol_mutex);
return frame_size + stuff;
}
static void *player_thread_func(void *arg) {
int play_samples;
signed short *inbuf, *outbuf, *silence;
outbuf = malloc(OUTFRAME_BYTES);
silence = malloc(OUTFRAME_BYTES);
memset(silence, 0, OUTFRAME_BYTES);
#ifdef FANCY_RESAMPLING
float *frame, *outframe;
SRC_DATA srcdat;
if (fancy_resampling) {
frame = malloc(frame_size*2*sizeof(float));
outframe = malloc(2*frame_size*2*sizeof(float));
srcdat.data_in = frame;
srcdat.data_out = outframe;
srcdat.input_frames = FRAME_BYTES;
srcdat.output_frames = 2*FRAME_BYTES;
srcdat.src_ratio = 1.0;
srcdat.end_of_input = 0;
}
#endif
while (!please_stop) {
do {
inbuf = ab_buffering ? silence : buffer_get_frame();
} while (!inbuf);
#ifdef FANCY_RESAMPLING
if (fancy_resampling) {
int i;
pthread_mutex_lock(&vol_mutex);
for (i=0; i<2*FRAME_BYTES; i++) {
frame[i] = (float)inbuf[i] / 32768.0;
frame[i] *= volume;
}
pthread_mutex_unlock(&vol_mutex);
srcdat.src_ratio = bf_playback_rate;
src_process(src, &srcdat);
assert(srcdat.input_frames_used == FRAME_BYTES);
src_float_to_short_array(outframe, outbuf, FRAME_BYTES*2);
play_samples = srcdat.output_frames_gen;
} else
#endif
play_samples = stuff_buffer(bf_playback_rate, inbuf, outbuf);
config.output->play(outbuf, play_samples);
}
return 0;
}
// takes the volume as specified by the airplay protocol
void player_volume(double f) {
double linear_volume = pow(10.0, 0.05*f);
if (config.output->volume) {
config.output->volume(linear_volume);
} else {
pthread_mutex_lock(&vol_mutex);
volume = linear_volume;
fix_volume = 65536.0 * volume;
pthread_mutex_unlock(&vol_mutex);
}
}
void player_flush(void) {
pthread_mutex_lock(&ab_mutex);
ab_resync();
pthread_mutex_unlock(&ab_mutex);
}
int player_play(stream_cfg *stream) {
if (config.buffer_start_fill > BUFFER_FRAMES)
die("specified buffer starting fill %d > buffer size %d\n",
config.buffer_start_fill, BUFFER_FRAMES);
AES_set_decrypt_key(stream->aeskey, 128, &aes);
aesiv = stream->aesiv;
init_buffer();
init_decoder(stream->fmtp);
#ifdef FANCY_RESAMPLING
init_src();
#endif
please_stop = 0;
config.output->start(sampling_rate);
pthread_create(&player_thread, NULL, player_thread_func, NULL);
return 0;
}
void player_stop(void) {
please_stop = 1;
pthread_join(player_thread, NULL);
config.output->stop();
free_buffer();
free_decoder();
#ifdef FANCY_RESAMPLING
free_src();
#endif
}