comparison cook.c @ 4650:31bf54d9353d libavcodec

Replace custom modified discrete cosine transform with ffmpeg's own. This does alter the decoded output, but not by much. The new output is closer to that produced by Real's "official" decoder, and the decoder runs slightly faster. Patch by Ian Braithwaite ian at braithwaite dot dk
author banan
date Sun, 11 Mar 2007 20:30:06 +0000
parents 33fc84eae7c3
children 1d88da25349b
comparison
equal deleted inserted replaced
4649:f64adef7cde8 4650:31bf54d9353d
88 int cookversion; 88 int cookversion;
89 /* states */ 89 /* states */
90 int random_state; 90 int random_state;
91 91
92 /* transform data */ 92 /* transform data */
93 FFTContext fft_ctx; 93 MDCTContext mdct_ctx;
94 DECLARE_ALIGNED_16(FFTSample, mlt_tmp[1024]); /* temporary storage for imlt */ 94 DECLARE_ALIGNED_16(FFTSample, mdct_tmp[1024]); /* temporary storage for imlt */
95 float* mlt_window; 95 float* mlt_window;
96 float* mlt_precos;
97 float* mlt_presin;
98 float* mlt_postcos;
99 int fft_size;
100 int fft_order;
101 int mlt_size; //modulated lapped transform size
102 96
103 /* gain buffers */ 97 /* gain buffers */
104 cook_gains gains1; 98 cook_gains gains1;
105 cook_gains gains2; 99 cook_gains gains2;
106 int gain_1[9]; 100 int gain_1[9];
223 } 217 }
224 218
225 static int init_cook_mlt(COOKContext *q) { 219 static int init_cook_mlt(COOKContext *q) {
226 int j; 220 int j;
227 float alpha; 221 float alpha;
228 222 int mlt_size = q->samples_per_channel;
229 /* Allocate the buffers, could be replaced with a static [512] 223
230 array if needed. */ 224 if ((q->mlt_window = av_malloc(sizeof(float)*mlt_size)) == 0)
231 q->mlt_size = q->samples_per_channel; 225 return -1;
232 q->mlt_window = av_malloc(sizeof(float)*q->mlt_size);
233 q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2);
234 q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2);
235 q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2);
236 226
237 /* Initialize the MLT window: simple sine window. */ 227 /* Initialize the MLT window: simple sine window. */
238 alpha = M_PI / (2.0 * (float)q->mlt_size); 228 alpha = M_PI / (2.0 * (float)mlt_size);
239 for(j=0 ; j<q->mlt_size ; j++) { 229 for(j=0 ; j<mlt_size ; j++)
240 q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha); 230 q->mlt_window[j] = sin((j + 0.5) * alpha) * sqrt(2.0 / q->samples_per_channel);
241 } 231
242 232 /* Initialize the MDCT. */
243 /* pre/post twiddle factors */ 233 if (ff_mdct_init(&q->mdct_ctx, av_log2(mlt_size)+1, 1)) {
244 for (j=0 ; j<q->mlt_size/2 ; j++){ 234 av_free(q->mlt_window);
245 q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size); 235 return -1;
246 q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size); 236 }
247 q->mlt_postcos[j] = (float)sqrt(2.0/(float)q->mlt_size)*cos( ((float)j*M_PI) /q->mlt_size); //sqrt(2/MLT_size) = scalefactor 237 av_log(NULL,AV_LOG_DEBUG,"MDCT initialized, order = %d.\n",
248 } 238 av_log2(mlt_size)+1);
249 239
250 /* Initialize the FFT. */ 240 return 0;
251 ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0);
252 av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n",
253 av_log2(q->samples_per_channel)-1);
254
255 return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos);
256 } 241 }
257 242
258 /*************** init functions end ***********/ 243 /*************** init functions end ***********/
259 244
260 /** 245 /**
311 COOKContext *q = avctx->priv_data; 296 COOKContext *q = avctx->priv_data;
312 av_log(avctx,AV_LOG_DEBUG, "Deallocating memory.\n"); 297 av_log(avctx,AV_LOG_DEBUG, "Deallocating memory.\n");
313 298
314 /* Free allocated memory buffers. */ 299 /* Free allocated memory buffers. */
315 av_free(q->mlt_window); 300 av_free(q->mlt_window);
316 av_free(q->mlt_precos);
317 av_free(q->mlt_presin);
318 av_free(q->mlt_postcos);
319 av_free(q->decoded_bytes_buffer); 301 av_free(q->decoded_bytes_buffer);
320 302
321 /* Free the transform. */ 303 /* Free the transform. */
322 ff_fft_end(&q->fft_ctx); 304 ff_mdct_end(&q->mdct_ctx);
323 305
324 /* Free the VLC tables. */ 306 /* Free the VLC tables. */
325 for (i=0 ; i<13 ; i++) { 307 for (i=0 ; i<13 ; i++) {
326 free_vlc(&q->envelope_quant_index[i]); 308 free_vlc(&q->envelope_quant_index[i]);
327 } 309 }
712 * @param inbuffer pointer to the mltcoefficients 694 * @param inbuffer pointer to the mltcoefficients
713 * @param outbuffer pointer to the timedomain buffer 695 * @param outbuffer pointer to the timedomain buffer
714 * @param mlt_tmp pointer to temporary storage space 696 * @param mlt_tmp pointer to temporary storage space
715 */ 697 */
716 698
717 static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer, 699 static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer)
718 float* mlt_tmp){ 700 {
719 int i; 701 int i;
720 702
721 /* prerotation */ 703 q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, outbuffer, inbuffer, q->mdct_tmp);
722 for(i=0 ; i<q->mlt_size ; i+=2){ 704
723 outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) + 705 for(i = 0; i < q->samples_per_channel; i++){
724 (q->mlt_precos[i/2] * inbuffer[i]); 706 float tmp = outbuffer[i];
725 outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) - 707
726 (q->mlt_presin[i/2] * inbuffer[i]); 708 outbuffer[i] = q->mlt_window[i] * outbuffer[q->samples_per_channel + i];
727 } 709 outbuffer[q->samples_per_channel + i] = q->mlt_window[q->samples_per_channel - 1 - i] * -tmp;
728
729 /* FFT */
730 ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer);
731 ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer);
732
733 /* postrotation */
734 for(i=0 ; i<q->mlt_size ; i+=2){
735 mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) +
736 (q->mlt_postcos[i/2] * outbuffer[i]);
737 mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) -
738 (q->mlt_postcos[i/2] * outbuffer[i+1]);
739 }
740
741 /* window and reorder */
742 for(i=0 ; i<q->mlt_size/2 ; i++){
743 outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i];
744 outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] *
745 q->mlt_window[q->mlt_size-1-i];
746 outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] *
747 q->mlt_window[q->mlt_size-1-i];
748 outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] *
749 q->mlt_window[i]);
750 } 710 }
751 } 711 }
752 712
753 713
754 /** 714 /**
942 cook_gains *gains, float *previous_buffer, 902 cook_gains *gains, float *previous_buffer,
943 int16_t *out, int chan) 903 int16_t *out, int chan)
944 { 904 {
945 int j; 905 int j;
946 906
947 cook_imlt(q, decode_buffer, q->mono_mdct_output, q->mlt_tmp); 907 cook_imlt(q, decode_buffer, q->mono_mdct_output);
948 gain_compensate(q, gains, previous_buffer); 908 gain_compensate(q, gains, previous_buffer);
949 909
950 /* Clip and convert floats to 16 bits. 910 /* Clip and convert floats to 16 bits.
951 */ 911 */
952 for (j = 0; j < q->samples_per_channel; j++) { 912 for (j = 0; j < q->samples_per_channel; j++) {
1043 PRINT("sample_rate",q->sample_rate); 1003 PRINT("sample_rate",q->sample_rate);
1044 PRINT("samples_per_channel",q->samples_per_channel); 1004 PRINT("samples_per_channel",q->samples_per_channel);
1045 PRINT("samples_per_frame",q->samples_per_frame); 1005 PRINT("samples_per_frame",q->samples_per_frame);
1046 PRINT("subbands",q->subbands); 1006 PRINT("subbands",q->subbands);
1047 PRINT("random_state",q->random_state); 1007 PRINT("random_state",q->random_state);
1048 PRINT("mlt_size",q->mlt_size);
1049 PRINT("js_subband_start",q->js_subband_start); 1008 PRINT("js_subband_start",q->js_subband_start);
1050 PRINT("log2_numvector_size",q->log2_numvector_size); 1009 PRINT("log2_numvector_size",q->log2_numvector_size);
1051 PRINT("numvector_size",q->numvector_size); 1010 PRINT("numvector_size",q->numvector_size);
1052 PRINT("total_subbands",q->total_subbands); 1011 PRINT("total_subbands",q->total_subbands);
1053 } 1012 }
1143 return -1; 1102 return -1;
1144 break; 1103 break;
1145 } 1104 }
1146 1105
1147 /* Initialize variable relations */ 1106 /* Initialize variable relations */
1148 q->mlt_size = q->samples_per_channel;
1149 q->numvector_size = (1 << q->log2_numvector_size); 1107 q->numvector_size = (1 << q->log2_numvector_size);
1150 1108
1151 /* Generate tables */ 1109 /* Generate tables */
1152 init_rootpow2table(q); 1110 init_rootpow2table(q);
1153 init_pow2table(q); 1111 init_pow2table(q);
1181 q->gains1.previous = q->gain_2; 1139 q->gains1.previous = q->gain_2;
1182 q->gains2.now = q->gain_3; 1140 q->gains2.now = q->gain_3;
1183 q->gains2.previous = q->gain_4; 1141 q->gains2.previous = q->gain_4;
1184 1142
1185 /* Initialize transform. */ 1143 /* Initialize transform. */
1186 if ( init_cook_mlt(q) == 0 ) 1144 if ( init_cook_mlt(q) != 0 )
1187 return -1; 1145 return -1;
1188 1146
1189 /* Try to catch some obviously faulty streams, othervise it might be exploitable */ 1147 /* Try to catch some obviously faulty streams, othervise it might be exploitable */
1190 if (q->total_subbands > 53) { 1148 if (q->total_subbands > 53) {
1191 av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); 1149 av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n");