Skip to content
Snippets Groups Projects
Commit eb1c687b authored by Fabrice Bellard's avatar Fabrice Bellard Committed by Benjamin Larsson
Browse files

Use the ffmpeg mdct function, patch by Fabrice Bellard. Thread: [FFmpeg-devel]...

Use the ffmpeg mdct function, patch by Fabrice Bellard. Thread: [FFmpeg-devel] NellyMoser transform bug, 10/25/2007 12:24 PM

Originally committed as revision 10909 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent c6dcd0d7
No related merge requests found
......@@ -46,7 +46,7 @@
#define NELLY_BIT_CAP 6
#define NELLY_BASE_OFF 4228
#define NELLY_BASE_SHIFT 19
#define NELLY_SAMPLES 256
#define NELLY_SAMPLES (2 * NELLY_BUF_LEN)
static const float dequantization_table[127] = {
0.0000000000,-0.8472560048, 0.7224709988, -1.5247479677, -0.4531480074, 0.3753609955, 1.4717899561,
......@@ -98,14 +98,12 @@ typedef struct NellyMoserDecodeContext {
int add_bias;
int scale_bias;
DSPContext dsp;
FFTContext fftc;
MDCTContext imdct_ctx;
DECLARE_ALIGNED_16(float,imdct_tmp[NELLY_BUF_LEN]);
DECLARE_ALIGNED_16(float,imdct_out[NELLY_BUF_LEN * 2]);
} NellyMoserDecodeContext;
DECLARE_ALIGNED_16(float,sine_window[128]);
DECLARE_ALIGNED_16(float,tcos[64]);
DECLARE_ALIGNED_16(float,tsin[64]);
DECLARE_ALIGNED_16(float,cos_tab[64]);
static inline int signed_shift(int i, int shift) {
if (shift > 0)
......@@ -113,69 +111,6 @@ static inline int signed_shift(int i, int shift) {
return i >> -shift;
}
static void antialias(float *buf, float *audio)
{
int i, end, mid_hi, mid_lo;
end = NELLY_BUF_LEN-1;
mid_hi = NELLY_BUF_LEN/2;
mid_lo = mid_hi-1;
for (i = 0; i < NELLY_BUF_LEN/4; i++) {
audio[2*i] = buf[2*i ]*tcos[i ] - buf[end-2*i]*tsin[i];
audio[2*i+1] = -(buf[end-2*i ]*tcos[i ] + buf[2*i ]*tsin[i]);
audio[end-2*i-1]= buf[end-2*i-1]*tcos[mid_lo-i] - buf[2*i+1 ]*tsin[mid_lo-i];
audio[end-2*i ]= -(buf[2*i+1 ]*tcos[mid_lo-i] + buf[end-2*i]*tsin[mid_lo-i]);
}
}
static void complex2signal(float *audio)
{
int i, end, mid_hi, mid_lo;
float *aptr, *sigptr, a, b, c, d, e, f, g;
end = NELLY_BUF_LEN-1;
mid_hi = NELLY_BUF_LEN/2;
mid_lo = mid_hi-1;
a = -audio[end];
b = audio[end-1];
c = -audio[1];
d = cos_tab[0];
e = audio[0];
f = cos_tab[mid_lo];
g = cos_tab[1];
audio[0] = d*e;
audio[1] = b*g-a*f;
audio[end-1] = a*g+b*f;
audio[end] = c*(-d);
aptr = audio+end-2;
sigptr = cos_tab+mid_hi-1;
for (i = 3; i < NELLY_BUF_LEN/2; i += 2) {
a = audio[i-1];
b = -audio[i];
c = cos_tab[i/2];
d = *sigptr;
e = *(aptr-1);
f = -(*aptr);
audio[i-1] = a*c+b*d;
*aptr = a*d-b*c;
a = cos_tab[(i/2)+1];
b = *(sigptr-1);
*(aptr-1) = b*e+a*f;
audio[i] = a*e-b*f;
sigptr--;
aptr -= 2;
}
}
static void overlap_and_window(NellyMoserDecodeContext *s, float *state, float *audio)
{
int bot, mid_up, mid_down, top;
......@@ -229,7 +164,7 @@ static int headroom(int *la)
}
static void get_sample_bits(float *buf, int *bits)
static void get_sample_bits(const float *buf, int *bits)
{
int i, j;
short sbuf[128];
......@@ -342,10 +277,11 @@ static void get_sample_bits(float *buf, int *bits)
void nelly_decode_block(NellyMoserDecodeContext *s, unsigned char block[NELLY_BLOCK_LEN], float audio[NELLY_SAMPLES])
{
int i,j;
float buf[NELLY_BUF_LEN], pows[NELLY_BUF_LEN];
float buf[NELLY_FILL_LEN], pows[NELLY_FILL_LEN];
float *aptr, *bptr, *pptr, val, pval;
int bits[NELLY_BUF_LEN];
unsigned char v;
float a;
init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8);
......@@ -363,31 +299,36 @@ void nelly_decode_block(NellyMoserDecodeContext *s, unsigned char block[NELLY_BL
}
memset(&buf[NELLY_FILL_LEN],0,4*sizeof(float));
memset(&pows[NELLY_FILL_LEN],0,4*sizeof(float));
get_sample_bits(buf, bits);
for (i = 0; i < 2; i++) {
aptr = audio+i*128;
aptr = audio + i * NELLY_BUF_LEN;
init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8);
skip_bits(&s->gb, NELLY_HEADER_BITS + i*NELLY_DETAIL_BITS);
for (j = 0; j < NELLY_FILL_LEN; j++) {
if (bits[j] <= 0) {
buf[j] = M_SQRT1_2*pows[j];
aptr[j] = M_SQRT1_2*pows[j];
if (av_random(&s->random_state) & 1)
buf[j] *= -1.0;
aptr[j] *= -1.0;
} else {
v = get_bits(&s->gb, bits[j]);
buf[j] = dequantization_table[(1<<bits[j])-1+v]*pows[j];
aptr[j] = dequantization_table[(1<<bits[j])-1+v]*pows[j];
}
}
antialias(buf, aptr);
ff_fft_permute(&s->fftc, (FFTComplex*)aptr);
ff_fft_calc(&s->fftc, (FFTComplex*)aptr);
complex2signal(aptr);
memset(&aptr[NELLY_FILL_LEN], 0,
(NELLY_BUF_LEN - NELLY_FILL_LEN) * sizeof(float));
s->imdct_ctx.fft.imdct_calc(&s->imdct_ctx, s->imdct_out,
aptr, s->imdct_tmp);
/* XXX: overlapping and windowing should be part of a more
generic imdct function */
a = 1.0 / 8.0;
for(j = 0; j < NELLY_BUF_LEN / 2; j++) {
aptr[j] = s->imdct_out[j + NELLY_BUF_LEN + NELLY_BUF_LEN / 2] * a;
aptr[j + NELLY_BUF_LEN / 2] = -s->imdct_out[j] * a;
}
overlap_and_window(s, s->state, aptr);
}
}
......@@ -399,7 +340,8 @@ static int decode_init(AVCodecContext * avctx) {
s->avctx = avctx;
av_init_random(0, &s->random_state);
ff_fft_init(&s->fftc, 6, 1);
ff_mdct_init(&s->imdct_ctx, 8, 1);
dsputil_init(&s->dsp, avctx);
if(s->dsp.float_to_int16 == ff_float_to_int16_c) {
......@@ -416,15 +358,6 @@ static int decode_init(AVCodecContext * avctx) {
sine_window[i] = sin((i + 0.5) / 256.0 * M_PI);
}
/* Generate tables */
if (!tcos[0])
for(i=0;i<64;i++) {
alpha = 2*M_PI * (i + 1.0 / 4.0) / 256;
tcos[i] = cos(alpha);
tsin[i] = -sin(alpha);
cos_tab[i] = cos(i/128.0*M_PI)/8.0;
}
return 0;
}
......@@ -464,7 +397,7 @@ static int decode_tag(AVCodecContext * avctx,
static int decode_end(AVCodecContext * avctx) {
NellyMoserDecodeContext *s = avctx->priv_data;
ff_fft_end(&s->fftc);
ff_mdct_end(&s->imdct_ctx);
return 0;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment