# HG changeset patch # User alexc # Date 1233347609 0 # Node ID d8a784fb1bbe29adb078b7716093d12c1d74438a # Parent 68fd157bab48e7019c8d46f3651172b48956367a Use the new RDFT code in the QDM2 decoder. diff -r 68fd157bab48 -r d8a784fb1bbe qdm2.c --- a/qdm2.c Fri Jan 30 20:15:48 2009 +0000 +++ b/qdm2.c Fri Jan 30 20:33:29 2009 +0000 @@ -98,9 +98,13 @@ } QDM2SubPNode; typedef struct { + float re; + float im; +} QDM2Complex; + +typedef struct { float level; - float *samples_im; - float *samples_re; + QDM2Complex *complex; const float *table; int phase; int phase_shift; @@ -118,14 +122,7 @@ } FFTCoefficient; typedef struct { - float re; - float im; -} QDM2Complex; - -typedef struct { - DECLARE_ALIGNED_16(QDM2Complex, complex[256 + 1]); - float samples_im[MPA_MAX_CHANNELS][256]; - float samples_re[MPA_MAX_CHANNELS][256]; + DECLARE_ALIGNED_16(QDM2Complex, complex[MPA_MAX_CHANNELS][256]); } QDM2FFT; /** @@ -166,8 +163,7 @@ int fft_coefs_min_index[5]; int fft_coefs_max_index[5]; int fft_level_exp[6]; - FFTContext fft_ctx; - FFTComplex exptab[128]; + RDFTContext rdft_ctx; QDM2FFT fft; /// I/O data @@ -1507,10 +1503,10 @@ /* generate FFT coefficients for tone */ if (tone->duration >= 3 || tone->cutoff >= 3) { - tone->samples_im[0] += c.im; - tone->samples_re[0] += c.re; - tone->samples_im[1] -= c.im; - tone->samples_re[1] -= c.re; + tone->complex[0].im += c.im; + tone->complex[0].re += c.re; + tone->complex[1].im -= c.im; + tone->complex[1].re -= c.re; } else { f[1] = -tone->table[4]; f[0] = tone->table[3] - tone->table[0]; @@ -1519,12 +1515,12 @@ f[4] = tone->table[0] - tone->table[1]; f[5] = tone->table[2]; for (i = 0; i < 2; i++) { - tone->samples_re[fft_cutoff_index_table[tone->cutoff][i]] += c.re * f[i]; - tone->samples_im[fft_cutoff_index_table[tone->cutoff][i]] += c.im *((tone->cutoff <= i) ? -f[i] : f[i]); + tone->complex[fft_cutoff_index_table[tone->cutoff][i]].re += c.re * f[i]; + tone->complex[fft_cutoff_index_table[tone->cutoff][i]].im += c.im *((tone->cutoff <= i) ? -f[i] : f[i]); } for (i = 0; i < 4; i++) { - tone->samples_re[i] += c.re * f[i+2]; - tone->samples_im[i] += c.im * f[i+2]; + tone->complex[i].re += c.re * f[i+2]; + tone->complex[i].im += c.im * f[i+2]; } } @@ -1542,8 +1538,7 @@ const double iscale = 0.25 * M_PI; for (ch = 0; ch < q->channels; ch++) { - memset(q->fft.samples_im[ch], 0, q->fft_size * sizeof(float)); - memset(q->fft.samples_re[ch], 0, q->fft_size * sizeof(float)); + memset(q->fft.complex[ch], 0, q->fft_size * sizeof(QDM2Complex)); } @@ -1561,10 +1556,10 @@ c.re = level * cos(q->fft_coefs[i].phase * iscale); c.im = level * sin(q->fft_coefs[i].phase * iscale); - q->fft.samples_re[ch][q->fft_coefs[i].offset + 0] += c.re; - q->fft.samples_im[ch][q->fft_coefs[i].offset + 0] += c.im; - q->fft.samples_re[ch][q->fft_coefs[i].offset + 1] -= c.re; - q->fft.samples_im[ch][q->fft_coefs[i].offset + 1] -= c.im; + q->fft.complex[ch][q->fft_coefs[i].offset + 0].re += c.re; + q->fft.complex[ch][q->fft_coefs[i].offset + 0].im += c.im; + q->fft.complex[ch][q->fft_coefs[i].offset + 1].re -= c.re; + q->fft.complex[ch][q->fft_coefs[i].offset + 1].im -= c.im; } /* generate existing FFT tones */ @@ -1594,8 +1589,7 @@ tone.cutoff = (offset >= 60) ? 3 : 2; tone.level = (q->fft_coefs[j].exp < 0) ? 0.0 : fft_tone_level_table[q->superblocktype_2_3 ? 0 : 1][q->fft_coefs[j].exp & 63]; - tone.samples_im = &q->fft.samples_im[ch][offset]; - tone.samples_re = &q->fft.samples_re[ch][offset]; + tone.complex = &q->fft.complex[ch][offset]; tone.table = fft_tone_sample_table[i][q->fft_coefs[j].offset - (offset << four_i)]; tone.phase = 64 * q->fft_coefs[j].phase - (offset << 8) - 128; tone.phase_shift = (2 * q->fft_coefs[j].offset + 1) << (7 - four_i); @@ -1612,37 +1606,14 @@ static void qdm2_calculate_fft (QDM2Context *q, int channel, int sub_packet) { - const int n = 1 << (q->fft_order - 1); - const int n2 = n >> 1; - const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.25f : 0.50f; - float c, s, f0, f1, f2, f3; - int i, j; - - /* prerotation (or something like that) */ - for (i=1; i < n2; i++) { - j = (n - i); - c = q->exptab[i].re; - s = -q->exptab[i].im; - f0 = (q->fft.samples_re[channel][i] - q->fft.samples_re[channel][j]) * gain; - f1 = (q->fft.samples_im[channel][i] + q->fft.samples_im[channel][j]) * gain; - f2 = (q->fft.samples_re[channel][i] + q->fft.samples_re[channel][j]) * gain; - f3 = (q->fft.samples_im[channel][i] - q->fft.samples_im[channel][j]) * gain; - q->fft.complex[i].re = s * f0 - c * f1 + f2; - q->fft.complex[i].im = c * f0 + s * f1 + f3; - q->fft.complex[j].re = -s * f0 + c * f1 + f2; - q->fft.complex[j].im = c * f0 + s * f1 - f3; - } - - q->fft.complex[ 0].re = q->fft.samples_re[channel][ 0] * gain * 2.0; - q->fft.complex[ 0].im = q->fft.samples_re[channel][ 0] * gain * 2.0; - q->fft.complex[n2].re = q->fft.samples_re[channel][n2] * gain * 2.0; - q->fft.complex[n2].im = -q->fft.samples_im[channel][n2] * gain * 2.0; - - ff_fft_permute(&q->fft_ctx, (FFTComplex *) q->fft.complex); - ff_fft_calc (&q->fft_ctx, (FFTComplex *) q->fft.complex); + const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.5f : 1.0f; + int i; + q->fft.complex[channel][0].re *= 2.0f; + q->fft.complex[channel][0].im = 0.0f; + ff_rdft_calc(&q->rdft_ctx, (FFTSample *)q->fft.complex[channel]); /* add samples to output buffer */ for (i = 0; i < ((q->fft_frame_size + 15) & ~15); i++) - q->output_buffer[q->channels * i + channel] += ((float *) q->fft.complex)[i]; + q->output_buffer[q->channels * i + channel] += ((float *) q->fft.complex[channel])[i] * gain; } @@ -1761,8 +1732,6 @@ uint8_t *extradata; int extradata_size; int tmp_val, tmp, size; - int i; - float alpha; /* extradata parsing @@ -1910,19 +1879,13 @@ else s->coeff_per_sb_select = 2; - // Fail on unknown fft order, if it's > 9 it can overflow s->exptab[] + // Fail on unknown fft order if ((s->fft_order < 7) || (s->fft_order > 9)) { av_log(avctx, AV_LOG_ERROR, "Unknown FFT order (%d), contact the developers!\n", s->fft_order); return -1; } - ff_fft_init(&s->fft_ctx, s->fft_order - 1, 1); - - for (i = 1; i < (1 << (s->fft_order - 2)); i++) { - alpha = 2 * M_PI * (float)i / (float)(1 << (s->fft_order - 1)); - s->exptab[i].re = cos(alpha); - s->exptab[i].im = sin(alpha); - } + ff_rdft_init(&s->rdft_ctx, s->fft_order, IRDFT); qdm2_init(s); @@ -1937,7 +1900,7 @@ { QDM2Context *s = avctx->priv_data; - ff_fft_end(&s->fft_ctx); + ff_rdft_end(&s->rdft_ctx); return 0; }