]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Make endian-independent. Allow users to specify only U8/S8/S16/S24/S32
authorMike Brady <mikebrady@eircom.net>
Mon, 12 Sep 2016 21:01:57 +0000 (22:01 +0100)
committerMike Brady <mikebrady@eircom.net>
Mon, 12 Sep 2016 21:01:57 +0000 (22:01 +0100)
audio_alsa.c
common.h
player.c
scripts/shairport-sync.conf
shairport.c

index 3319a7cf6a88ff76a30e97bed6d5fbdce4a2cf72..ca5a1e2f06b29559a53e8ee0f4e7c9091fe4edbd 100644 (file)
@@ -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;
 }
index 64b9b44f9880aa6ce4fb3e93ac030b8487b70881..536f24c53c3962b526cb96f9bff89903a3ee8eec 100644 (file)
--- 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 {
index 56bf83b683a0062a28c2a33cf0f2c1f99119a20d..b5a8d28d7512210e10077fc5a467c41fce8434cc 100644 (file)
--- 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;
   }
index 50d0f7978f6357442de198d4aa8522ac92c17324..cd7688bbac1fe39df3768a4742c47153f04d51fc 100644 (file)
@@ -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".
index e832623300543a48c7622f893d85597e73b5f986..4fec3541d023aa195118b8b810676791b658d92e 100644 (file)
@@ -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);