diff --git a/audio.h b/audio.h index 4c86d7d..75abc08 100644 --- a/audio.h +++ b/audio.h @@ -22,7 +22,7 @@ typedef struct { void (*start)(int sample_rate); // block of samples - void (*play)(short buf[], int samples); + void (*play)(int buf[], int samples); void (*stop)(void); // may be null if not implemented diff --git a/audio_alsa.c b/audio_alsa.c index 0e9de51..c878fcb 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -39,7 +39,7 @@ static void help(void); static int init(int argc, char **argv); static void deinit(void); static void start(int sample_rate); -static void play(short buf[], int samples); +static void play(int buf[], int samples); static void stop(void); static void flush(void); int delay(long* the_delay); @@ -429,7 +429,7 @@ int open_alsa_device(void) { } ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, - SND_PCM_FORMAT_S16); + SND_PCM_FORMAT_S32); if (ret < 0) { die("audio_alsa: Sample format not available for device \"%s\": %s", alsa_out_dev, snd_strerror(ret)); @@ -693,7 +693,7 @@ int delay(long* the_delay) { } } -static void play(short buf[], int samples) { +static void play(int buf[], int samples) { // debug(3,"audio_alsa play called."); int ret = 0; if (alsa_handle == NULL) { diff --git a/audio_ao.c b/audio_ao.c index 41b823b..0e6cb0b 100644 --- a/audio_ao.c +++ b/audio_ao.c @@ -117,7 +117,7 @@ static int init(int argc, char **argv) { ao_sample_format fmt; memset(&fmt, 0, sizeof(fmt)); - fmt.bits = 16; + fmt.bits = 32; fmt.rate = 44100; fmt.channels = 2; fmt.byte_format = AO_FMT_NATIVE; @@ -139,7 +139,7 @@ static void start(int sample_rate) { die("unexpected sample rate!"); } -static void play(short buf[], int samples) { ao_play(dev, (char *)buf, samples * 4); } +static void play(int buf[], int samples) { ao_play(dev, (char *)buf, samples * 4); } static void stop(void) {} diff --git a/audio_dummy.c b/audio_dummy.c index 659a720..bcccfcd 100644 --- a/audio_dummy.c +++ b/audio_dummy.c @@ -48,7 +48,7 @@ static void start(int sample_rate) { debug(1, "dummy audio output started at Fs=%d Hz\n", sample_rate); } -static void play(short buf[], int samples) {} +static void play(int buf[], int samples) {} static void stop(void) { debug(1, "dummy audio stopped\n"); } diff --git a/audio_pipe.c b/audio_pipe.c index 17bf310..314a7c5 100644 --- a/audio_pipe.c +++ b/audio_pipe.c @@ -48,7 +48,7 @@ static void start(int sample_rate) { fd = open(pipename, O_WRONLY | O_NONBLOCK); } -static void play(short buf[], int samples) { +static void play(int buf[], int samples) { // if the file is not open, try to open it. if (fd == -1) { fd = open(pipename, O_WRONLY | O_NONBLOCK); diff --git a/audio_pulse.c b/audio_pulse.c index 6fa94e9..d7fce44 100644 --- a/audio_pulse.c +++ b/audio_pulse.c @@ -95,7 +95,7 @@ static int init(int argc, char **argv) { } static void pulse_connect(void) { - static const pa_sample_spec ss = {.format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2}; + static const pa_sample_spec ss = {.format = PA_SAMPLE_S32LE, .rate = 44100, .channels = 2}; pa_dev = pa_simple_new(pulse_options.server, pulse_options.service_name, PA_STREAM_PLAYBACK, pulse_options.sink, "Shairport Stream", &ss, NULL, NULL, &pa_error); @@ -115,8 +115,8 @@ static void start(int sample_rate) { die("unexpected sample rate!"); } -static void play(short buf[], int samples) { - if (pa_simple_write(pa_dev, (char *)buf, (size_t)samples * 4, &pa_error) < 0) { +static void play(int buf[], int samples) { + if (pa_simple_write(pa_dev, (char *)buf, (size_t)samples * 8, &pa_error) < 0) { fprintf(stderr, __FILE__ ": pa_simple_write() failed: %s\n", pa_strerror(pa_error)); if (pa_error == PA_ERR_CONNECTIONTERMINATED) { fprintf(stderr, __FILE__ ": reconnecting."); diff --git a/audio_sndio.c b/audio_sndio.c index 7093261..5248e47 100644 --- a/audio_sndio.c +++ b/audio_sndio.c @@ -34,7 +34,7 @@ static int init(int argc, char **argv) { sio_initpar(&par); - par.bits = 16; + par.bits = 32; par.rate = 44100; par.pchan = 2; par.le = SIO_LE_NATIVE; @@ -59,7 +59,7 @@ static void start(int sample_rate) { sio_start(sio); } -static void play(short buf[], int samples) { +static void play(int buf[], int samples) { sio_write(sio, (char *)buf, samples * par.bps * par.pchan); } diff --git a/audio_stdout.c b/audio_stdout.c index b8b0aa5..45276b0 100644 --- a/audio_stdout.c +++ b/audio_stdout.c @@ -42,8 +42,8 @@ static void start(int sample_rate) { fd = STDOUT_FILENO; } -static void play(short buf[], int samples) { - int ignore = write(fd, buf, samples * 4); +static void play(int buf[], int samples) { + int ignore = write(fd, buf, samples * 8); } static void stop(void) { diff --git a/player.c b/player.c index 97eccfb..148bb9d 100644 --- a/player.c +++ b/player.c @@ -440,7 +440,7 @@ int32_t rand_in_range(int32_t exclusive_range_limit) { return sp >> 32; } -static inline short dithered_vol(short sample) { +static inline int dithered_vol(short sample) { long out; out = (long)sample * fix_volume; @@ -469,7 +469,8 @@ static inline short dithered_vol(short sample) { out = LONG_MIN; } } - return out >> 16; + return out; + //return out >> 16; } // get the next frame, when available. return 0 if underrun/stream reset. @@ -697,16 +698,16 @@ static abuf_t *buffer_get_frame(void) { // ab_write),ab_read,ab_write); ab_buffering = 0; } - signed short *silence; + signed int *silence; //if (fs==0) // debug(2,"Zero length silence buffer needed with gross_frame_gap of %lld and dac_delay of %lld.",gross_frame_gap,dac_delay); // the fs (number of frames of silence to play) can be zero in the DAC doesn't start ouotputting frames for a while -- it could get loaded up but not start responding for many milliseconds. if (fs!=0) { - silence = malloc(bytes_per_audio_frame*fs); + silence = malloc(bytes_per_audio_frame*fs*2); if (silence==NULL) debug(1,"Failed to allocate %d byte silence buffer.",fs); else { - memset(silence, 0, bytes_per_audio_frame*fs); + memset(silence, 0, bytes_per_audio_frame*fs*2); // debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is %d, // with %d packets.",exact_frame_gap,fs,dac_delay,seq_diff(ab_read, ab_write)); config.output->play(silence, fs); @@ -857,8 +858,15 @@ static inline short shortmean(short a, short b) { return r; } +static void stuff_buffer_normal(short *inptr, int length, int *outptr){ + int i; + for (i = 0; i < length; i++) + *outptr++ = *inptr++; +} + + // stuff: 1 means add 1; 0 means do nothing; -1 means remove 1 -static int stuff_buffer_basic(short *inptr, int length, short *outptr, int stuff) { +static int stuff_buffer_basic(short *inptr, int length, int *outptr, int stuff) { if ((stuff > 1) || (stuff < -1) || (length <100)) { // debug(1, "Stuff argument to stuff_buffer must be from -1 to +1 and length >100."); return length; @@ -1033,14 +1041,15 @@ static void *player_thread_func(void *arg) { char rnstate[256]; initstate(time(NULL), rnstate, 256); - signed short *inbuf, *outbuf, *silence; + signed short *inbuf; + signed int *outbuf; outbuf = malloc(bytes_per_audio_frame*(frame_size+max_frame_size_change)); if (outbuf==NULL) debug(1,"Failed to allocate memory for an output buffer."); - silence = malloc(bytes_per_audio_frame*frame_size); - if (silence==NULL) +// silence = malloc(bytes_per_audio_frame*frame_size); +// if (silence==NULL) debug(1,"Failed to allocate memory for a silence buffer."); - memset(silence, 0, bytes_per_audio_frame*frame_size); +// memset(silence, 0, bytes_per_audio_frame*frame_size); late_packet_message_sent = 0; first_packet_timestamp = 0; missing_packets = late_packets = too_late_packets = resend_requests = 0; @@ -1100,8 +1109,10 @@ static void *player_thread_func(void *arg) { else { if (inframe->length==0) debug(1,"empty frame to play -- skipping it."); - else - config.output->play(inframe->data, inframe->length); + else {/// + stuff_buffer_normal(inframe->data, inframe->length, outbuf); + config.output->play(outbuf, inframe->length); + } } } else { // We have a frame of data. We need to see if we want to add or remove a frame from it to @@ -1251,8 +1262,10 @@ static void *player_thread_func(void *arg) { else { if (inframe->length==0) debug(1,"empty frame to play -- skipping it (2)."); - else - config.output->play(inframe->data, inframe->length); + else {/// + stuff_buffer_normal(inframe->data, inframe->length, outbuf); + config.output->play(outbuf, inframe->length); + } } } else { #ifdef HAVE_LIBSOXR @@ -1270,23 +1283,6 @@ static void *player_thread_func(void *arg) { // if (amount_to_stuff) debug(1,"Standard stuff..."); play_samples = stuff_buffer_basic(inframe->data, inframe->length, outbuf, amount_to_stuff); #endif - - /* - { - int co; - int is_silent=1; - short *p = outbuf; - for (co=0;colength==0) debug(1,"empty frame to play -- skipping it (3)."); - else - config.output->play(inframe->data, inframe->length); + else {/// + stuff_buffer_normal(inframe->data, inframe->length, outbuf); + config.output->play(outbuf, inframe->length); + } } else { play_samples = stuff_buffer_basic(inframe->data, inframe->length, outbuf, 0); // no stuffing, but volume adjustment @@ -1498,7 +1496,7 @@ static void *player_thread_func(void *arg) { config.output->stop(); usleep(100000); // allow this time to (?) allow the alsa subsystem to finish cleaning up after itself. 50 ms seems too short free(outbuf); - free(silence); +// free(silence); debug(1,"Shut down audio, control and timing threads"); itr.please_stop = 1; pthread_kill(rtp_audio_thread, SIGUSR1);