From: Mike Brady Date: Mon, 12 Sep 2016 21:01:57 +0000 (+0100) Subject: Make endian-independent. Allow users to specify only U8/S8/S16/S24/S32 X-Git-Tag: 3.0.d18~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0499743bd9b2660baba8a0859400c97dbcf7bcd3;p=thirdparty%2Fshairport-sync.git Make endian-independent. Allow users to specify only U8/S8/S16/S24/S32 --- diff --git a/audio_alsa.c b/audio_alsa.c index 3319a7cf..ca5a1e2f 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -204,19 +204,19 @@ static int init(int argc, char **argv) { /* Get the output format, using the same names as aplay does*/ 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; + if (strcasecmp(str, "S16") == 0) + config.output_format = SPS_FORMAT_S16; + else if (strcasecmp(str, "S24") == 0) + config.output_format = SPS_FORMAT_S24; + else if (strcasecmp(str, "S32") == 0) + config.output_format = SPS_FORMAT_S32; else if (strcasecmp(str, "U8") == 0) config.output_format = SPS_FORMAT_U8; else if (strcasecmp(str, "S8") == 0) config.output_format = SPS_FORMAT_S8; else - die("Invalid output format \"%s\". It should be \"U8\", \"S8\", \"S16_LE\", \"S24_LE\" or " - "\"S32_LE\"", + die("Invalid output format \"%s\". It should be \"U8\", \"S8\", \"S16\", \"S24\" or " + "\"S32\"", str); } @@ -445,10 +445,27 @@ int open_alsa_device(void) { die("audio_alsa: Access type not available for device \"%s\": %s", alsa_out_dev, snd_strerror(ret)); } - - ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sample_format); + snd_pcm_format_t sf; + switch (sample_format) { + case SPS_FORMAT_S8: + sf = SND_PCM_FORMAT_S8; + break; + case SPS_FORMAT_U8: + sf = SND_PCM_FORMAT_U8; + break; + case SPS_FORMAT_S16: + sf = SND_PCM_FORMAT_S16; + break; + case SPS_FORMAT_S24: + sf = SND_PCM_FORMAT_S24; + break; + case SPS_FORMAT_S32: + sf = SND_PCM_FORMAT_S32; + break; + } + ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf); if (ret < 0) { - die("audio_alsa: Sample format %d not available for device \"%s\": %s", sample_format, + die("audio_alsa: Sample format %d not available for device \"%s\": %s", sf, alsa_out_dev, snd_strerror(ret)); } @@ -678,7 +695,7 @@ static void start(int i_sample_rate, int i_sample_format) { desired_sample_rate = i_sample_rate; // must be a variable if (i_sample_format == 0) - sample_format = SND_PCM_FORMAT_S16_LE; // default + sample_format = SPS_FORMAT_S16; // default else sample_format = i_sample_format; } diff --git a/common.h b/common.h index 64b9b44f..536f24c5 100644 --- a/common.h +++ b/common.h @@ -59,64 +59,12 @@ enum decoders_supported_type { // the following enum must _exactly match the snd_pcm_format_t definition in the alsa pcm.h file. enum sps_format_t { - SPS_FORMAT_UNKNOWN = -1, - SPS_FORMAT_S8 = 0, + SPS_FORMAT_UNKNOWN = 0, + SPS_FORMAT_S8, SPS_FORMAT_U8, - SPS_FORMAT_S16_LE, - SPS_FORMAT_S16_BE, - SPS_FORMAT_U16_LE, - SPS_FORMAT_U16_BE, - SPS_FORMAT_S24_LE, - SPS_FORMAT_S24_BE, - SPS_FORMAT_U24_LE, - SPS_FORMAT_U24_BE, - SPS_FORMAT_S32_LE, - SPS_FORMAT_S32_BE, - SPS_FORMAT_U32_LE, - SPS_FORMAT_U32_BE, - SPS_FORMAT_FLOAT_LE, - SPS_FORMAT_FLOAT_BE, - SPS_FORMAT_FLOAT64_LE, - SPS_FORMAT_FLOAT64_BE, - SPS_FORMAT_IEC958_SUBFRAME_LE, - SPS_FORMAT_IEC958_SUBFRAME_BE, - SPS_FORMAT_MU_LAW, - SPS_FORMAT_A_LAW, - SPS_FORMAT_IMA_ADPCM, - SPS_FORMAT_MPEG, - SPS_FORMAT_GSM, - SPS_FORMAT_SPECIAL = 31, - SPS_FORMAT_S24_3LE = 32, - SPS_FORMAT_S24_3BE, - SPS_FORMAT_U24_3LE, - SPS_FORMAT_U24_3BE, - SPS_FORMAT_S20_3LE, - SPS_FORMAT_S20_3BE, - SPS_FORMAT_U20_3LE, - SPS_FORMAT_U20_3BE, - SPS_FORMAT_S18_3LE, - SPS_FORMAT_S18_3BE, - SPS_FORMAT_U18_3LE, - SPS_FORMAT_U18_3BE, - SPS_FORMAT_G723_24, - SPS_FORMAT_G723_24_1B, - SPS_FORMAT_G723_40, - SPS_FORMAT_G723_40_1B, - SPS_FORMAT_DSD_U8, - SPS_FORMAT_DSD_U16_LE, - SPS_FORMAT_DSD_U32_LE, - SPS_FORMAT_DSD_U16_BE, - SPS_FORMAT_DSD_U32_BE, - SPS_FORMAT_LAST = SPS_FORMAT_DSD_U32_BE, - SPS_FORMAT_S16 = SPS_FORMAT_S16_LE, - SPS_FORMAT_U16 = SPS_FORMAT_U16_LE, - SPS_FORMAT_S24 = SPS_FORMAT_S24_LE, - SPS_FORMAT_U24 = SPS_FORMAT_U24_LE, - SPS_FORMAT_S32 = SPS_FORMAT_S32_LE, - SPS_FORMAT_U32 = SPS_FORMAT_U32_LE, - SPS_FORMAT_FLOAT = SPS_FORMAT_FLOAT_LE, - SPS_FORMAT_FLOAT64 = SPS_FORMAT_FLOAT64_LE, - SPS_FORMAT_IEC958_SUBFRAME = SPS_FORMAT_IEC958_SUBFRAME_LE + SPS_FORMAT_S16, + SPS_FORMAT_S24, + SPS_FORMAT_S32, } sps_format_t; typedef struct { diff --git a/player.c b/player.c index 56bf83b6..b5a8d28d 100644 --- a/player.c +++ b/player.c @@ -647,13 +647,13 @@ static inline void process_sample(int32_t sample, char **outp, enum sps_format_t int64_t dither_mask; switch (format) { - case SPS_FORMAT_S32_LE: + case SPS_FORMAT_S32: dither_mask = (int64_t)1 << (64 + 1 - 32); break; - case SPS_FORMAT_S24_LE: + case SPS_FORMAT_S24: dither_mask = (int64_t)1 << (64 + 1 - 24); break; - case SPS_FORMAT_S16_LE: + case SPS_FORMAT_S16: dither_mask = (int64_t)1 << (64 + 1 - 16); break; case SPS_FORMAT_S8: @@ -683,29 +683,29 @@ static inline void process_sample(int32_t sample, char **outp, enum sps_format_t // move the result to the desired position in the int64_t char *op = *outp; switch (format) { - case SPS_FORMAT_S32_LE: + case SPS_FORMAT_S32: hyper_sample >>= (64 - 32); *(int32_t *)op = hyper_sample; result = 4; break; - case SPS_FORMAT_S24_LE: + case SPS_FORMAT_S24: hyper_sample >>= (64 - 24); *(int32_t *)op = hyper_sample; result = 4; break; - case SPS_FORMAT_S16_LE: + case SPS_FORMAT_S16: hyper_sample >>= (64 - 16); - *(int16_t *)op = hyper_sample; + *(int16_t *)op = (int16_t)hyper_sample; result = 2; break; case SPS_FORMAT_S8: - hyper_sample >>= (64 - 8); + hyper_sample >>= (int8_t)(64 - 8); *op = hyper_sample; result = 1; break; case SPS_FORMAT_U8: - hyper_sample >>= (64 - 8); - hyper_sample += 128; // this is just a guess! + hyper_sample >>= (uint8_t)(64 - 8); + hyper_sample += 128; *op = hyper_sample; result = 1; break; @@ -1465,10 +1465,10 @@ static void *player_thread_func(void *arg) { output_bytes_per_frame = 4; switch (config.output_format) { - case SPS_FORMAT_S24_LE: + case SPS_FORMAT_S24: output_bytes_per_frame = 8; break; - case SPS_FORMAT_S32_LE: + case SPS_FORMAT_S32: output_bytes_per_frame = 8; break; } @@ -1538,13 +1538,13 @@ static void *player_thread_func(void *arg) { case SPS_FORMAT_U8: output_bit_depth = 8; break; - case SPS_FORMAT_S16_LE: + case SPS_FORMAT_S16: output_bit_depth = 16; break; - case SPS_FORMAT_S24_LE: + case SPS_FORMAT_S24: output_bit_depth = 24; break; - case SPS_FORMAT_S32_LE: + case SPS_FORMAT_S32: output_bit_depth = 32; break; } diff --git a/scripts/shairport-sync.conf b/scripts/shairport-sync.conf index 50d0f797..cd7688bb 100644 --- a/scripts/shairport-sync.conf +++ b/scripts/shairport-sync.conf @@ -61,7 +61,7 @@ alsa = // mixer_control_name = "PCM"; // the name of the mixer to use to adjust output volume. If not specified, volume in adjusted in software. // mixer_device = "default"; // the mixer_device default is whatever the output_device is. Normally you wouldn't have to use this. // output_rate = 44100; // can be 44100, 88200, 176400, 352800, but the device must be capable of it -// output_format = "S16_LE"; // can be "S16_LE", "S24_LE" or "S32_LE", but the device must be capable of it +// output_format = "S16"; // can be "U8", "S8", "S16", "S24" or "S32", with be LE or BE depending on the processor, but the device must be capable of it // audio_backend_latency_offset = 0.0; // Set this offset in seconds to compensate for a fixed delay in the audio back end. E.g. if the output device delays by 100 ms, set this to -0.1. // audio_backend_buffer_desired_length = 0.15; // Given in seconds. If set too small, buffer underflow occurs on low-powered machines. Too long and the response times with software mixer become annoying. // disable_synchronization = "no"; // Set to "yes" to disable synchronization. Default is "no". diff --git a/shairport.c b/shairport.c index e8326233..4fec3541 100644 --- a/shairport.c +++ b/shairport.c @@ -791,7 +791,7 @@ int main(int argc, char **argv) { config.audio_backend_buffer_desired_length = 6615; // 0.15 seconds. config.udp_port_base = 6001; config.udp_port_range = 100; - config.output_format = SPS_FORMAT_S16_LE; // default + config.output_format = SPS_FORMAT_S16; // default config.output_rate = 44100; // default config.decoders_supported = 1 << decoder_hammerton; // David Hammerton's decoder supported by default @@ -1074,7 +1074,7 @@ int main(int argc, char **argv) { 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 (2 is the default SPS_FORMAT_S16_LE).", config.output_format); + debug(1, "output_format is %d (3 is the default SPS_FORMAT_S16).", config.output_format); debug(1, "audio backend desired buffer length is %f seconds.", config.audio_backend_buffer_desired_length); debug(1, "audio backend latency offset is %f seconds.", config.audio_backend_latency_offset);