# HG changeset patch # User banan # Date 1173645006 0 # Node ID 31bf54d9353d1aa2074e9ec88bb24845e46d9ff7 # Parent f64adef7cde887f5b36d18302a33127dcf3bef34 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 diff -r f64adef7cde8 -r 31bf54d9353d cook.c --- a/cook.c Sun Mar 11 16:57:05 2007 +0000 +++ b/cook.c Sun Mar 11 20:30:06 2007 +0000 @@ -90,15 +90,9 @@ int random_state; /* transform data */ - FFTContext fft_ctx; - DECLARE_ALIGNED_16(FFTSample, mlt_tmp[1024]); /* temporary storage for imlt */ + MDCTContext mdct_ctx; + DECLARE_ALIGNED_16(FFTSample, mdct_tmp[1024]); /* temporary storage for imlt */ float* mlt_window; - float* mlt_precos; - float* mlt_presin; - float* mlt_postcos; - int fft_size; - int fft_order; - int mlt_size; //modulated lapped transform size /* gain buffers */ cook_gains gains1; @@ -225,34 +219,25 @@ static int init_cook_mlt(COOKContext *q) { int j; float alpha; + int mlt_size = q->samples_per_channel; - /* Allocate the buffers, could be replaced with a static [512] - array if needed. */ - q->mlt_size = q->samples_per_channel; - q->mlt_window = av_malloc(sizeof(float)*q->mlt_size); - q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2); - q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2); - q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2); + if ((q->mlt_window = av_malloc(sizeof(float)*mlt_size)) == 0) + return -1; /* Initialize the MLT window: simple sine window. */ - alpha = M_PI / (2.0 * (float)q->mlt_size); - for(j=0 ; jmlt_size ; j++) { - q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha); - } + alpha = M_PI / (2.0 * (float)mlt_size); + for(j=0 ; jmlt_window[j] = sin((j + 0.5) * alpha) * sqrt(2.0 / q->samples_per_channel); - /* pre/post twiddle factors */ - for (j=0 ; jmlt_size/2 ; j++){ - q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size); - q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size); - 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 + /* Initialize the MDCT. */ + if (ff_mdct_init(&q->mdct_ctx, av_log2(mlt_size)+1, 1)) { + av_free(q->mlt_window); + return -1; } + av_log(NULL,AV_LOG_DEBUG,"MDCT initialized, order = %d.\n", + av_log2(mlt_size)+1); - /* Initialize the FFT. */ - ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0); - av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n", - av_log2(q->samples_per_channel)-1); - - return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos); + return 0; } /*************** init functions end ***********/ @@ -313,13 +298,10 @@ /* Free allocated memory buffers. */ av_free(q->mlt_window); - av_free(q->mlt_precos); - av_free(q->mlt_presin); - av_free(q->mlt_postcos); av_free(q->decoded_bytes_buffer); /* Free the transform. */ - ff_fft_end(&q->fft_ctx); + ff_mdct_end(&q->mdct_ctx); /* Free the VLC tables. */ for (i=0 ; i<13 ; i++) { @@ -714,39 +696,17 @@ * @param mlt_tmp pointer to temporary storage space */ -static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer, - float* mlt_tmp){ +static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer) +{ int i; - /* prerotation */ - for(i=0 ; imlt_size ; i+=2){ - outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) + - (q->mlt_precos[i/2] * inbuffer[i]); - outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) - - (q->mlt_presin[i/2] * inbuffer[i]); - } - - /* FFT */ - ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer); - ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer); + q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, outbuffer, inbuffer, q->mdct_tmp); - /* postrotation */ - for(i=0 ; imlt_size ; i+=2){ - mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) + - (q->mlt_postcos[i/2] * outbuffer[i]); - mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) - - (q->mlt_postcos[i/2] * outbuffer[i+1]); - } + for(i = 0; i < q->samples_per_channel; i++){ + float tmp = outbuffer[i]; - /* window and reorder */ - for(i=0 ; imlt_size/2 ; i++){ - outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i]; - outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] * - q->mlt_window[q->mlt_size-1-i]; - outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] * - q->mlt_window[q->mlt_size-1-i]; - outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] * - q->mlt_window[i]); + outbuffer[i] = q->mlt_window[i] * outbuffer[q->samples_per_channel + i]; + outbuffer[q->samples_per_channel + i] = q->mlt_window[q->samples_per_channel - 1 - i] * -tmp; } } @@ -944,7 +904,7 @@ { int j; - cook_imlt(q, decode_buffer, q->mono_mdct_output, q->mlt_tmp); + cook_imlt(q, decode_buffer, q->mono_mdct_output); gain_compensate(q, gains, previous_buffer); /* Clip and convert floats to 16 bits. @@ -1045,7 +1005,6 @@ PRINT("samples_per_frame",q->samples_per_frame); PRINT("subbands",q->subbands); PRINT("random_state",q->random_state); - PRINT("mlt_size",q->mlt_size); PRINT("js_subband_start",q->js_subband_start); PRINT("log2_numvector_size",q->log2_numvector_size); PRINT("numvector_size",q->numvector_size); @@ -1145,7 +1104,6 @@ } /* Initialize variable relations */ - q->mlt_size = q->samples_per_channel; q->numvector_size = (1 << q->log2_numvector_size); /* Generate tables */ @@ -1183,7 +1141,7 @@ q->gains2.previous = q->gain_4; /* Initialize transform. */ - if ( init_cook_mlt(q) == 0 ) + if ( init_cook_mlt(q) != 0 ) return -1; /* Try to catch some obviously faulty streams, othervise it might be exploitable */