ref: f8222c997a25aa32d9a7929b59988745ca6b2023
parent: 94b0c98a61ec055e57802002657269dac1e0ec06
author: Timothy B. Terriberry <[email protected]>
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);
}