Skip to content

Commit

Permalink
Add ability to set output format and output rate
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebrady committed Aug 19, 2016
1 parent 5ddaec1 commit 01e5128
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 18 deletions.
2 changes: 1 addition & 1 deletion audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ typedef struct {
// at end of program
void (*deinit)(void);

void (*start)(int sample_rate);
void (*start)(int sample_rate, int sample_format);

// block of samples
void (*play)(short buf[], int samples);
Expand Down
54 changes: 45 additions & 9 deletions audio_alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
static void help(void);
static int init(int argc, char **argv);
static void deinit(void);
static void start(int sample_rate);
static void start(int i_sample_rate, int i_sample_format);
static void play(short buf[], int samples);
static void stop(void);
static void flush(void);
Expand Down Expand Up @@ -68,6 +68,7 @@ audio_output audio_alsa = {
static pthread_mutex_t alsa_mutex = PTHREAD_MUTEX_INITIALIZER;

static unsigned int desired_sample_rate;
static snd_pcm_format_t sample_format;

static snd_pcm_t *alsa_handle = NULL;
static snd_pcm_hw_params_t *alsa_params = NULL;
Expand Down Expand Up @@ -205,6 +206,35 @@ static int init(int argc, char **argv) {
die("Invalid disable_synchronization option choice \"%s\". It should be \"yes\" or \"no\"");
}

/* Get the output format, using the same names as aplay does -- S16_LE, S32_LE to begin with*/
if (config_lookup_string(config.cfg, "alsa.output_format", &str)) {
if (strcasecmp(str, "S16_LE") == 0)
config.output_format = SND_PCM_FORMAT_S16_LE;
else if (strcasecmp(str, "S24_LE") == 0)
config.output_format = SND_PCM_FORMAT_S24_LE;
else if (strcasecmp(str, "S32_LE") == 0)
config.output_format = SND_PCM_FORMAT_S32_LE;
else
die("Invalid output format \"%s\". It should be \"S16_LE\", \"S24_LE\" or \"S32_LE\"",str);
}

/* Get the output rate, which must be a multiple of 44,100*/
if (config_lookup_int(config.cfg, "alsa.output_rate",
&value)) {
debug(1,"Value read for output rate is %d.",value);
switch(value) {
case 44100:
case 88200:
case 176400:
case 352800:
config.output_rate = value;
break;
default :
die("Invalid output rate \"%d\". It should be a multiple of 44,100 up to 352,800",value);
}
}


/* Get the use_mmap_if_available setting. */
if (config_lookup_string(config.cfg, "alsa.use_mmap_if_available", &str)) {
if (strcasecmp(str, "no") == 0)
Expand Down Expand Up @@ -424,11 +454,10 @@ int open_alsa_device(void) {
alsa_out_dev, snd_strerror(ret));
}

ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params,
SND_PCM_FORMAT_S16);
ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sample_format);
if (ret < 0) {
die("audio_alsa: Sample format not available for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
die("audio_alsa: Sample format %d not available for device \"%s\": %s",
sample_format, alsa_out_dev, snd_strerror(ret));
}

ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
Expand Down Expand Up @@ -640,11 +669,18 @@ int open_alsa_device(void) {
return (0);
}

static void start(int sample_rate) {
static void start(int i_sample_rate, int i_sample_format) {
// debug(2,"audio_alsa start called.");
if (sample_rate != 44100)
die("Unexpected sample rate %d -- only 44,100 supported!", sample_rate);
desired_sample_rate = sample_rate; // must be a variable
if (i_sample_rate==0)
desired_sample_rate = 44100; // default
else
desired_sample_rate = i_sample_rate; // must be a variable

if (i_sample_format==0)
sample_format = SND_PCM_FORMAT_S16_LE; // default
else
sample_format = i_sample_format;

}

int delay(long* the_delay) {
Expand Down
6 changes: 4 additions & 2 deletions audio_ao.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,11 @@ static void deinit(void) {
ao_shutdown();
}

static void start(int sample_rate) {
if (sample_rate != 44100)
static void start(int sample_rate, int sample_format) {
if (sample_rate != 0)
die("unexpected sample rate!");
if (sample_format != 0)
die("unexpected sample format!");
}

static void play(short buf[], int samples) { ao_play(dev, (char *)buf, samples * 4); }
Expand Down
2 changes: 1 addition & 1 deletion audio_dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static int init(int argc, char **argv) { return 0; }

static void deinit(void) {}

static void start(int sample_rate) {
static void start(int sample_rate, int sample_format) {
Fs = sample_rate;
starttime = 0;
samples_played = 0;
Expand Down
2 changes: 1 addition & 1 deletion audio_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static int fd = -1;

char *pipename = NULL;

static void start(int sample_rate) {
static void start(int sample_rate, int sample_format) {
// this will leave fd as -1 if a reader hasn't been attached
fd = open(pipename, O_WRONLY | O_NONBLOCK);
}
Expand Down
6 changes: 4 additions & 2 deletions audio_pulse.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@ static void deinit(void) {
pa_dev = NULL;
}

static void start(int sample_rate) {
if (sample_rate != 44100)
static void start(int sample_rate, int sample_format) {
if (sample_rate != 0)
die("unexpected sample rate!");
if (sample_format != 0)
die("unexpected sample format!");
}

static void play(short buf[], int samples) {
Expand Down
2 changes: 2 additions & 0 deletions audio_sndio.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ static void deinit(void) { sio_close(sio); }
static void start(int sample_rate) {
if (sample_rate != par.rate)
die("unexpected sample rate!");
if (sample_format != 0)
die("unexpected sample format!");
sio_start(sio);
}

Expand Down
2 changes: 1 addition & 1 deletion audio_stdout.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

static int fd = -1;

static void start(int sample_rate) {
static void start(int sample_rate int sample_format) {
fd = STDOUT_FILENO;
}

Expand Down
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ typedef struct {
// audio backend buffer -- the DAC buffer for ALSA
long audio_backend_latency_offset; // this will be the offset to compensate for any fixed latency there might be in the audio path
uint32_t volume_range_db; // the range, in dB, from max dB to min dB. Zero means use the mixer's native range.
int output_format;
int output_rate;
} shairport_cfg;

// true if Shairport Sync is supposed to be sending output to the output device, false otherwise
Expand Down
2 changes: 1 addition & 1 deletion player.c
Original file line number Diff line number Diff line change
Expand Up @@ -1716,7 +1716,7 @@ int player_play(stream_cfg *stream, pthread_t *player_thread) {
#endif
if (rc)
debug(1, "Error initialising condition variable.");
config.output->start(sampling_rate);
config.output->start(config.output_rate,config.output_format);
size_t size = (PTHREAD_STACK_MIN + 256 * 1024);
pthread_attr_t tattr;
pthread_attr_init(&tattr);
Expand Down
2 changes: 2 additions & 0 deletions shairport.c
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,8 @@ int main(int argc, char **argv) {
debug(1, "playback_mode is %d (0-stereo, 1-mono).", config.playback_mode);
debug(1, "disable_synchronization is %d.", config.no_sync);
debug(1, "use_mmap_if_available is %d.", config.no_mmap ? 0 : 1);
debug(1, "output_rate is %d (0 means 44,100).", config.output_rate);
debug(1, "output_format is %d (0 means S16_LE).", config.output_format);
debug(1, "audio backend desired buffer length is %d.",
config.audio_backend_buffer_desired_length);
debug(1, "audio backend latency offset is %d.", config.audio_backend_latency_offset);
Expand Down

0 comments on commit 01e5128

Please sign in to comment.