]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Working reliably with all 16-bit speeds
authorMike Brady <mikebrady@eircom.net>
Sun, 4 Sep 2016 15:34:56 +0000 (16:34 +0100)
committerMike Brady <mikebrady@eircom.net>
Sun, 4 Sep 2016 15:34:56 +0000 (16:34 +0100)
player.c

index a81b4d04d9abcb33b712fd636a0a0335b557f474..532252a3356100cc70d1e7a65a5b3c350c4cb591 100644 (file)
--- a/player.c
+++ b/player.c
@@ -387,7 +387,7 @@ static int init_decoder(int32_t fmtp[12]) {
 
     field              bitDepth                uint8_t         describes the bit depth of the source PCM data (maximum value = 32)
 
-    field              pb                      uint8_t         currently unused tuning parameter. 
+    field              pb                      uint8_t         currently unused tuning parametetbugr. 
                                                          value should be set to 40
 
     field              mb                      uint8_t         currently unused tuning parameter. 
@@ -746,11 +746,11 @@ static abuf_t *buffer_get_frame(void) {
               int64_t delta = (first_packet_timestamp - reference_timestamp)+config.latency+config.audio_backend_latency_offset;
               
               if (delta>=0) {
-                int64_t delta_fp_sec = (delta << 32) / 44100; // int64_t which is positive
+                int64_t delta_fp_sec = (delta << 32) / output_sample_rate; // int64_t which is positive
                 first_packet_time_to_play=reference_timestamp_time+delta_fp_sec;
               } else {
                 int64_t abs_delta = -delta;
-                int64_t delta_fp_sec = (abs_delta << 32) / 44100; // int64_t which is positive
+                int64_t delta_fp_sec = (abs_delta << 32) / output_sample_rate; // int64_t which is positive
                 first_packet_time_to_play=reference_timestamp_time-delta_fp_sec;              
               }
 
@@ -768,22 +768,22 @@ static abuf_t *buffer_get_frame(void) {
             int64_t delta = (first_packet_timestamp - reference_timestamp)+config.latency+config.audio_backend_latency_offset;
             
             if (delta>=0) {
-              int64_t delta_fp_sec = (delta << 32) / 44100; // int64_t which is positive
+              int64_t delta_fp_sec = (delta << 32) / output_sample_rate; // int64_t which is positive
               first_packet_time_to_play=reference_timestamp_time+delta_fp_sec;
             } else {
               int64_t abs_delta = -delta;
-              int64_t delta_fp_sec = (abs_delta << 32) / 44100; // int64_t which is positive
+              int64_t delta_fp_sec = (abs_delta << 32) / output_sample_rate; // int64_t which is positive
               first_packet_time_to_play=reference_timestamp_time-delta_fp_sec;              
             }
 
-            int64_t max_dac_delay = 4410;
+            int64_t max_dac_delay = output_sample_rate/10;
             int64_t filler_size = max_dac_delay; // 0.1 second -- the maximum we'll add to the DAC
 
             if (local_time_now >= first_packet_time_to_play) {
               // we've gone past the time...
               // debug(1,"Run past the exact start time by %llu frames, with time now of %llx, fpttp
               // of %llx and dac_delay of %d and %d packets;
-              // flush.",(((tn-first_packet_time_to_play)*44100)>>32)+dac_delay,tn,first_packet_time_to_play,dac_delay,seq_diff(ab_read,
+              // flush.",(((tn-first_packet_time_to_play)*output_sample_rate)>>32)+dac_delay,tn,first_packet_time_to_play,dac_delay,seq_diff(ab_read,
               // ab_write));
 
               if (config.output->flush)
@@ -803,7 +803,7 @@ static abuf_t *buffer_get_frame(void) {
               } else
                 dac_delay = 0;
               int64_t gross_frame_gap =
-                  ((first_packet_time_to_play - local_time_now) * 44100) >> 32;
+                  ((first_packet_time_to_play - local_time_now) * output_sample_rate) >> 32;
               int64_t exact_frame_gap = gross_frame_gap - dac_delay;
               if (exact_frame_gap < 0) {
                 // we've gone past the time...
@@ -890,12 +890,12 @@ static abuf_t *buffer_get_frame(void) {
         int64_t net_offset = delta + offset; // okay
         uint64_t time_to_play = reference_timestamp_time; // type okay
         if (net_offset >= 0) {
-          uint64_t net_offset_fp_sec = (net_offset << 32) / 44100; // int64_t which is positive
+          uint64_t net_offset_fp_sec = (net_offset << 32) / output_sample_rate; // int64_t which is positive
           time_to_play += net_offset_fp_sec; // using the latency requested...
           // debug(2,"Net Offset: %lld, adjusted: %lld.",net_offset,net_offset_fp_sec);
         } else {
           int64_t abs_net_offset = -net_offset;
-          uint64_t net_offset_fp_sec = (abs_net_offset << 32) / 44100; // int64_t which is positive
+          uint64_t net_offset_fp_sec = (abs_net_offset << 32) / output_sample_rate; // int64_t which is positive
           time_to_play -= net_offset_fp_sec;
           // debug(2,"Net Offset: %lld, adjusted: -%lld.",net_offset,net_offset_fp_sec);
         }
@@ -917,7 +917,7 @@ static abuf_t *buffer_get_frame(void) {
 
     if (wait) {
       uint64_t time_to_wait_for_wakeup_fp =
-          ((uint64_t)1 << 32) / 44100;       // this is time period of one frame
+          ((uint64_t)1 << 32) / input_sample_rate;       // this is time period of one frame
       time_to_wait_for_wakeup_fp *= 4 * 352; // four full 352-frame packets
       time_to_wait_for_wakeup_fp /= 3; // four thirds of a packet time
 
@@ -993,13 +993,14 @@ static inline short shortmean(short a, short b) {
 
 // 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) {
+  int tstuff = 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;
+    tstuff = 0; // if any of these conditions hold, don't stuff anything/
   }
   int i;
   int stuffsamp = length;
-  if (stuff)
+  if (tstuff)
     //      stuffsamp = rand() % (length - 1);
     stuffsamp =
         (rand() % (length - 2)) + 1; // ensure there's always a sample before and after the item
@@ -1009,8 +1010,8 @@ static int stuff_buffer_basic(short *inptr, int length, short *outptr, int stuff
     *outptr++ = dithered_vol(*inptr++);
     *outptr++ = dithered_vol(*inptr++);
   };
-  if (stuff) {
-    if (stuff == 1) {
+  if (tstuff) {
+    if (tstuff == 1) {
       // debug(3, "+++++++++");
       // interpolate one sample
       //*outptr++ = dithered_vol(((long)inptr[-2] + (long)inptr[0]) >> 1);
@@ -1025,8 +1026,8 @@ static int stuff_buffer_basic(short *inptr, int length, short *outptr, int stuff
     
     // if you're removing, i.e. stuff < 0, copy that much less over. If you're adding, do all the rest.
     int remainder = length;
-    if (stuff<0)
-      remainder = remainder+stuff; // don't run over the correct end of the output buffer
+    if (tstuff<0)
+      remainder = remainder+tstuff; // don't run over the correct end of the output buffer
 
     for (i = stuffsamp; i < remainder; i++) {
       *outptr++ = dithered_vol(*inptr++);
@@ -1035,22 +1036,23 @@ static int stuff_buffer_basic(short *inptr, int length, short *outptr, int stuff
   }
   pthread_mutex_unlock(&vol_mutex);
 
-  return length + stuff;
+  return length + tstuff;
 }
 
 #ifdef HAVE_LIBSOXR
 // stuff: 1 means add 1; 0 means do nothing; -1 means remove 1
 static int stuff_buffer_soxr(short *inptr, int length, short *outptr, int stuff) {
-  if ((stuff > 1) || (stuff < -1) || (length < 100)) {
-    // debug(1, "Stuff argument to sox_stuff_buffer must be from -1 to +1 and length must be > 100.");
-    return length;
+  int tstuff = stuff;
+  if ((stuff > 1) || (stuff < -1) || (length <100)) {
+    // debug(1, "Stuff argument to stuff_buffer must be from -1 to +1 and length >100.");
+    tstuff = 0; // if any of these conditions hold, don't stuff anything/
   }
   int i;
   short *ip, *op;
   ip = inptr;
   op = outptr;
 
-  if (stuff) {
+  if (tstuff) {
     // debug(1,"Stuff %d.",stuff);
     soxr_io_spec_t io_spec;
     io_spec.itype = SOXR_INT16_I;
@@ -1061,9 +1063,9 @@ static int stuff_buffer_soxr(short *inptr, int length, short *outptr, int stuff)
 
     size_t odone;
 
-    soxr_error_t error = soxr_oneshot(length, length + stuff, 2, /* Rates and # of chans. */
+    soxr_error_t error = soxr_oneshot(length, length + tstuff, 2, /* Rates and # of chans. */
                                       inptr, length, NULL,           /* Input. */
-                                      outptr, length + stuff, &odone, /* Output. */
+                                      outptr, length + tstuff, &odone, /* Output. */
                                       &io_spec,    /* Input, output and transfer spec. */
                                       NULL, NULL); /* Default configuration.*/
 
@@ -1082,7 +1084,7 @@ static int stuff_buffer_soxr(short *inptr, int length, short *outptr, int stuff)
     }
 
     // keep the last (dpm) samples, to mitigate the Gibbs phenomenon
-    op = outptr + (length + stuff - gpm) * sizeof(short);
+    op = outptr + (length + tstuff - gpm) * sizeof(short);
     ip = inptr + (length - gpm) * sizeof(short);
     for (i = 0; i < gpm; i++) {
       *op++ = *ip++;
@@ -1093,7 +1095,7 @@ static int stuff_buffer_soxr(short *inptr, int length, short *outptr, int stuff)
     if (fix_volume != 65536.0) {
       // pthread_mutex_lock(&vol_mutex);
       op = outptr;
-      for (i = 0; i < length + stuff; i++) {
+      for (i = 0; i < length + tstuff; i++) {
         *op = dithered_vol(*op);
         op++;
         *op = dithered_vol(*op);
@@ -1111,7 +1113,7 @@ static int stuff_buffer_soxr(short *inptr, int length, short *outptr, int stuff)
     };
     // pthread_mutex_unlock(&vol_mutex);
   }
-  return length + stuff;
+  return length + tstuff;
 }
 #endif
 
@@ -1366,7 +1368,9 @@ static void *player_thread_func(void *arg) {
               default:
                 die("Shairport Sync only supports 16 bit input");
             }
+            
             inbuf = tbuf;
+            inbuflength*=output_sample_ratio;
           }
           
           // We have a frame of data. We need to see if we want to add or remove a frame from it to
@@ -1397,10 +1401,10 @@ static void *player_thread_func(void *arg) {
           if (local_time_now >= reference_timestamp_time) {
           // debug(1,"td is %lld.",td);
              td = local_time_now - reference_timestamp_time; // this is the positive value. Conversion is positive uint64_t to int64_t, thus okay
-            td_in_frames = (td * 44100) >> 32;
+            td_in_frames = (td * output_sample_rate) >> 32;
           } else {
             td = reference_timestamp_time - local_time_now; // this is the absolute value, which should be negated. Conversion is positive uint64_t to int64_t, thus okay.
-            td_in_frames = (td * 44100) >> 32; //use the absolute td value for the present. Types okay
+            td_in_frames = (td * output_sample_rate) >> 32; //use the absolute td value for the present. Types okay
             td_in_frames = -td_in_frames;
             td = -td; // should be okay, as the range of values should be very small w.r.t 64 bits
           }
@@ -1511,13 +1515,13 @@ static void *player_thread_func(void *arg) {
               // if no stuffing needed and no volume adjustment, then
               // don't send to stuff_buffer_* and don't copy to outbuf; just send directly to the
               // output device...
-              if (inframe->data==NULL)
+              if (inbuf==NULL)
                 debug(1,"NULL inframe->data to play -- skipping it.");
               else {
-                if (inframe->length==0)
+                if (inbuflength==0)
                   debug(1,"empty frame to play -- skipping it (2).");
                 else
-                  config.output->play(inframe->data, inframe->length);
+                  config.output->play(inbuf, inbuflength);
               }
             } else {
 
@@ -1526,16 +1530,16 @@ static void *player_thread_func(void *arg) {
               switch (config.packet_stuffing) {
               case ST_basic:
                 //                if (amount_to_stuff) debug(1,"Basic stuff...");
-                play_samples = stuff_buffer_basic(inframe->data, inframe->length, outbuf, amount_to_stuff);
+                play_samples = stuff_buffer_basic(inbuf, inbuflength, outbuf, amount_to_stuff);
                 break;
               case ST_soxr:
                 //                if (amount_to_stuff) debug(1,"Soxr stuff...");
-                play_samples = stuff_buffer_soxr(inframe->data, inframe->length, outbuf, amount_to_stuff);
+                play_samples = stuff_buffer_soxr(inbuf, inbuflength, outbuf, amount_to_stuff);
                 break;
               }
 #else
               //          if (amount_to_stuff) debug(1,"Standard stuff...");
-              play_samples = stuff_buffer_basic(inframe->data, inframe->length, outbuf, amount_to_stuff);
+              play_samples = stuff_buffer_basic(inbuf, inbuflength, outbuf, amount_to_stuff);
 #endif
 
               /*
@@ -1593,21 +1597,21 @@ static void *player_thread_func(void *arg) {
             
             if (fix_volume == 0x10000)
             
-              if (inframe->data==NULL)
-                debug(1,"NULL inframe->data to play -- skipping it.");
+              if (inbuf==NULL)
+                debug(1,"NULL inbuf to play -- skipping it.");
               else {
-                if (inframe->length==0)
+                if (inbuflength==0)
                   debug(1,"empty frame to play -- skipping it (3).");
                 else
-                  config.output->play(inframe->data, inframe->length);
+                  config.output->play(inbuf, inbuflength);
               }
             else {
-              play_samples = stuff_buffer_basic(inframe->data, inframe->length, outbuf, 0); // no stuffing, but volume adjustment
+              play_samples = stuff_buffer_basic(inbuf, inbuflength, outbuf, 0); // no stuffing, but volume adjustment
 
               if (outbuf==NULL)
                 debug(1,"NULL outbuf to play -- skipping it.");
               else {
-                if (inframe->length==0)
+                if (inbuf==0)
                   debug(1,"empty frame to play -- skipping it (4).");
                 else
                   config.output->play(outbuf, play_samples);
@@ -1692,8 +1696,8 @@ static void *player_thread_func(void *arg) {
                          "%*d,"    /* min buffer occupancy */
                          "%*d",    /* max buffer occupancy */
                          10, moving_average_sync_error,
-                         10, moving_average_correction * 1000000 / 352,
-                         10, moving_average_insertions_plus_deletions * 1000000 / 352,
+                         10, moving_average_correction * 1000000 / (352*output_sample_ratio),
+                         10, moving_average_insertions_plus_deletions * 1000000 / (352*output_sample_ratio),
                          12, play_number,
                          7, missing_packets,
                          7, late_packets,