Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(655622)

Side by Side Diff: src/opusdec.c

Issue 1358: Dithering improvement
Patch Set: oops Created 2 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2002-2007 Jean-Marc Valin 1 /* Copyright (c) 2002-2007 Jean-Marc Valin
2 Copyright (c) 2008 CSIRO 2 Copyright (c) 2008 CSIRO
3 Copyright (c) 2007-2013 Xiph.Org Foundation 3 Copyright (c) 2007-2013 Xiph.Org Foundation
4 File: opusdec.c 4 File: opusdec.c
5 5
6 Redistribution and use in source and binary forms, with or without 6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions 7 modification, are permitted provided that the following conditions
8 are met: 8 are met:
9 9
10 - Redistributions of source code must retain the above copyright 10 - Redistributions of source code must retain the above copyright
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 114
115 #ifdef HAVE_LIBSNDIO 115 #ifdef HAVE_LIBSNDIO
116 struct sio_hdl *hdl; 116 struct sio_hdl *hdl;
117 #endif 117 #endif
118 118
119 typedef struct shapestate shapestate; 119 typedef struct shapestate shapestate;
120 struct shapestate { 120 struct shapestate {
121 float * b_buf; 121 float * b_buf;
122 float * a_buf; 122 float * a_buf;
123 int fs; 123 int fs;
124 int mute;
125 }; 124 };
126 125
127 static unsigned int rngseed = 22222; 126 static unsigned int rngseed = 22222;
128 static inline unsigned int fast_rand(void) { 127 static inline unsigned int fast_rand(void) {
129 rngseed = (rngseed * 96314165) + 907633515; 128 rngseed = (rngseed * 96314165) + 907633515;
130 return rngseed; 129 return rngseed;
131 } 130 }
132 131
133 #ifndef HAVE_FMINF 132 #ifndef HAVE_FMINF
134 # define fminf(_x,_y) ((_x)<(_y)?(_x):(_y)) 133 # define fminf(_x,_y) ((_x)<(_y)?(_x):(_y))
(...skipping 24 matching lines...) Expand all
159 by the peak error of 1.5 +20 dB though this much is unobservable rare) 158 by the peak error of 1.5 +20 dB though this much is unobservable rare)
160 so to avoid clipping the signal is attenuated by a couple thousandths 159 so to avoid clipping the signal is attenuated by a couple thousandths
161 of a dB. Initially the approach taken here was to only attenuate by 160 of a dB. Initially the approach taken here was to only attenuate by
162 the 99.9th percentile, making clipping rare but not impossible (like 161 the 99.9th percentile, making clipping rare but not impossible (like
163 SoX) but the limited gain of the filter means that the worst case was 162 SoX) but the limited gain of the filter means that the worst case was
164 only two thousandths of a dB more, so this just uses the worst case. 163 only two thousandths of a dB more, so this just uses the worst case.
165 The attenuation is probably also helpful to prevent clipping in the DAC 164 The attenuation is probably also helpful to prevent clipping in the DAC
166 reconstruction filters or downstream resampling in any case.*/ 165 reconstruction filters or downstream resampling in any case.*/
167 static inline void shape_dither_toshort(shapestate *_ss, short *_o, float *_i, i nt _n, int _CC) 166 static inline void shape_dither_toshort(shapestate *_ss, short *_o, float *_i, i nt _n, int _CC)
168 { 167 {
169 const float gains[3]={32768.f-15.f,32768.f-15.f,32768.f-3.f}; 168 const float fcoef[2][8] =
170 const float fcoef[3][8] =
171 { 169 {
172 {2.2374f, -.7339f, -.1251f, -.6033f, 0.9030f, .0116f, -.5853f, -.2571f}, /* 48.0kHz noise shaping filter sd=2.34*/ 170 {2.2374f, -.7339f, -.1251f, -.6033f, 0.9030f, .0116f, -.5853f, -.2571f}, /* 48.0kHz noise shaping filter sd=2.34*/
173 {2.2061f, -.4706f, -.2534f, -.6214f, 1.0587f, .0676f, -.6054f, -.2738f}, /* 44.1kHz noise shaping filter sd=2.51*/ 171 {2.2061f, -.4706f, -.2534f, -.6214f, 1.0587f, .0676f, -.6054f, -.2738f}, /* 44.1kHz noise shaping filter sd=2.51*/
174 {1.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f,0.0000f, 0.0000f, 0.0000f}, /* lowpass noise shaping filter sd=0.65*/
175 }; 172 };
173 float coef[8]={0};
176 int i; 174 int i;
177 int rate=_ss->fs==44100?1:(_ss->fs==48000?0:2);
178 float gain=gains[rate];
179 float *b_buf; 175 float *b_buf;
180 float *a_buf; 176 float *a_buf;
181 int mute=_ss->mute; 177 float fs = _ss->fs;
178 int dither=0;
179 if (fs>46000)
180 memcpy(coef, fcoef[0], 8*sizeof(*coef));
181 else if (fs>43000)
182 memcpy(coef, fcoef[1], 8*sizeof(*coef));
183 else
184 {
185 float radius, theta, alpha;
186 radius = 0.7;
187 theta = 2*M_PI*3000/fs;
188 alpha = .5 - 3000*2/fs;
189 coef[0] = 2*radius*cos(theta) - alpha;
190 coef[1] = 2*alpha*radius*cos(theta) - radius*radius;
191 coef[2] = -alpha*radius*radius;
192 dither = 1;
193 }
182 b_buf=_ss->b_buf; 194 b_buf=_ss->b_buf;
183 a_buf=_ss->a_buf; 195 a_buf=_ss->a_buf;
184 /*In order to avoid replacing digital silence with quiet dither noise
185 we mute if the output has been silent for a while*/
186 if(mute>64)
187 memset(a_buf,0,sizeof(float)*_CC*4);
188 for(i=0;i<_n;i++) 196 for(i=0;i<_n;i++)
189 { 197 {
190 int c; 198 int c;
191 int pos = i*_CC; 199 int pos = i*_CC;
192 int silent=1;
193 for(c=0;c<_CC;c++) 200 for(c=0;c<_CC;c++)
194 { 201 {
195 int j, si; 202 int j, si;
196 float r,s,err=0; 203 float r,s,err=0;
197 silent&=_i[pos+c]==0; 204 s=_i[pos+c];
198 s=_i[pos+c]*gain;
199 for(j=0;j<4;j++) 205 for(j=0;j<4;j++)
200 err += fcoef[rate][j]*b_buf[c*4+j] - fcoef[rate][j+4]*a_buf[c*4+j]; 206 err += coef[j]*b_buf[c*4+j] - coef[j+4]*a_buf[c*4+j];
201 memmove(&a_buf[c*4+1],&a_buf[c*4],sizeof(float)*3); 207 memmove(&a_buf[c*4+1],&a_buf[c*4],sizeof(float)*3);
202 memmove(&b_buf[c*4+1],&b_buf[c*4],sizeof(float)*3); 208 memmove(&b_buf[c*4+1],&b_buf[c*4],sizeof(float)*3);
203 a_buf[c*4]=err; 209 a_buf[c*4]=err;
204 s = s - err; 210 s = s - err;
205 r=(float)fast_rand()*(1/(float)UINT_MAX) - (float)fast_rand()*(1/(float)UI NT_MAX); 211 if (dither)
206 if (mute>16)r=0; 212 r=(float)fast_rand()*(1/(float)UINT_MAX) - .5;
213 else
214 r = 0;
207 /*Clamp in float out of paranoia that the input will be >96 dBFS and wrap if the 215 /*Clamp in float out of paranoia that the input will be >96 dBFS and wrap if the
208 integer is clamped.*/ 216 integer is clamped.*/
209 _o[pos+c] = si = float2int(fmaxf(-32768,fminf(s + r,32767))); 217 _o[pos+c] = si = float2int(fmaxf(-32768,fminf(s + r,32767)));
210 /*Including clipping in the noise shaping is generally disastrous: 218 /*Including clipping in the noise shaping is generally disastrous:
211 the futile effort to restore the clipped energy results in more clipping . 219 the futile effort to restore the clipped energy results in more clipping .
212 However, small amounts-- at the level which could normally be created by 220 However, small amounts-- at the level which could normally be created by
213 dither and rounding-- are harmless and can even reduce clipping somewhat 221 dither and rounding-- are harmless and can even reduce clipping somewhat
214 due to the clipping sometimes reducing the dither+rounding error.*/ 222 due to the clipping sometimes reducing the dither+rounding error.*/
215 b_buf[c*4] = (mute>16)?0:fmaxf(-1.5f,fminf(si - s,1.5f)); 223 b_buf[c*4] = fmaxf(-1.5f,fminf(si - s,1.5f));
216 } 224 }
217 mute++;
218 if(!silent)mute=0;
219 } 225 }
220 _ss->mute=MINI(mute,960);
221 } 226 }
222 227
223 static void print_comments(char *comments, int length) 228 static void print_comments(char *comments, int length)
224 { 229 {
225 char *c=comments; 230 char *c=comments;
226 int len, i, nb_fields, err=0; 231 int len, i, nb_fields, err=0;
227 232
228 if (length<(8+4+4)) 233 if (length<(8+4+4))
229 { 234 {
230 fprintf (stderr, "Invalid/corrupted comments\n"); 235 fprintf (stderr, "Invalid/corrupted comments\n");
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 (void)argc; 705 (void)argc;
701 (void)argv; 706 (void)argv;
702 707
703 init_console_utf8(); 708 init_console_utf8();
704 init_commandline_arguments_utf8(&argc_utf8, &argv_utf8); 709 init_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
705 #endif 710 #endif
706 711
707 output=0; 712 output=0;
708 shapemem.a_buf=0; 713 shapemem.a_buf=0;
709 shapemem.b_buf=0; 714 shapemem.b_buf=0;
710 shapemem.mute=960;
711 shapemem.fs=0; 715 shapemem.fs=0;
712 716
713 /*Process options*/ 717 /*Process options*/
714 while(1) 718 while(1)
715 { 719 {
716 c = getopt_long (argc_utf8, argv_utf8, "hV", 720 c = getopt_long (argc_utf8, argv_utf8, "hV",
717 long_options, &option_index); 721 long_options, &option_index);
718 if (c==-1) 722 if (c==-1)
719 break; 723 break;
720 724
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 if (fout != NULL) 1150 if (fout != NULL)
1147 fclose(fout); 1151 fclose(fout);
1148 1152
1149 #ifdef WIN_UNICODE 1153 #ifdef WIN_UNICODE
1150 free_commandline_arguments_utf8(&argc_utf8, &argv_utf8); 1154 free_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
1151 uninit_console_utf8(); 1155 uninit_console_utf8();
1152 #endif 1156 #endif
1153 1157
1154 return 0; 1158 return 0;
1155 } 1159 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld