shithub: opusfile

Download patch

ref: f8222c997a25aa32d9a7929b59988745ca6b2023
parent: 94b0c98a61ec055e57802002657269dac1e0ec06
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Mon Mar 25 08:06:55 EDT 2013

Reset dither state when API path changes.

The caller can switch between the fixed/float APIs and the
 stereo/multichannel APIs on every call.
Detect this and reset the dither state to avoid potentially
 injecting noise from a very out-of-date state when switching from
 fixed to float back to fixed, or from the wrong channels when
 switching between stereo and multichannel.
Normal applications won't do this stuff, but we should be
 well-behaved if they do.

--- a/src/internal.h
+++ b/src/internal.h
@@ -209,6 +209,11 @@
   float              dither_b[OP_NCHANNELS_MAX*4];
   int                dither_mute;
   opus_uint32        dither_seed;
+  /*The number of channels represented by the internal state.
+    This gets set to 0 whenever anything that would prevent state propagation
+     occurs (switching between the float/short APIs, or between the
+     stereo/multistream APIs).*/
+  int                state_channel_count;
 #endif
 };
 
--- a/src/opusfile.c
+++ b/src/opusfile.c
@@ -2883,9 +2883,9 @@
   The attenuation is probably also helpful to prevent clipping in the DAC
    reconstruction filters or downstream resampling, in any case.*/
 
-#define OP_GAIN (32753.0F)
+# define OP_GAIN (32753.0F)
 
-#define OP_PRNG_GAIN (1.0F/0xFFFFFFFF)
+# define OP_PRNG_GAIN (1.0F/0xFFFFFFFF)
 
 /*48 kHz noise shaping filter, sd=2.34.*/
 
@@ -2904,6 +2904,7 @@
   int         i;
   mute=_of->dither_mute;
   seed=_of->dither_seed;
+  if(_of->state_channel_count!=_nchannels)mute=65;
   /*In order to avoid replacing digital silence with quiet dither noise, we
      mute if the output has been silent for a while.*/
   if(mute>64)memset(_of->dither_a,0,sizeof(*_of->dither_a)*4*_nchannels);
@@ -2953,6 +2954,7 @@
   }
   _of->dither_mute=OP_MIN(mute,65);
   _of->dither_seed=seed;
+  _of->state_channel_count=_nchannels;
 }
 
 static int op_float2short_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
@@ -2969,6 +2971,7 @@
 }
 
 int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){
+  _of->state_channel_count=0;
   return op_read_native(_of,_pcm,_buf_size,_li);
 }
 
@@ -3063,6 +3066,7 @@
 }
 
 int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){
+  _of->state_channel_count=0;
   return op_read_native_filter(_of,_pcm,_buf_size,op_stereo_filter,NULL);
 }