Instead of using fixed coefficients, the correct way is to calculate the coefficients using the highpass cutoff frequency from the ADX stream header and the sample rate.tags/n0.9
| @@ -489,7 +489,7 @@ OBJS-$(CONFIG_PCM_U32LE_ENCODER) += pcm.o | |||
| OBJS-$(CONFIG_PCM_ZORK_DECODER) += pcm.o | |||
| OBJS-$(CONFIG_ADPCM_4XM_DECODER) += adpcm.o adpcm_data.o | |||
| OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o | |||
| OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o adx.o | |||
| OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adxenc.o | |||
| OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o | |||
| OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o | |||
| @@ -0,0 +1,34 @@ | |||
| /* | |||
| * Copyright (c) 2011 Justin Ruggles | |||
| * | |||
| * This file is part of Libav. | |||
| * | |||
| * Libav is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * Libav is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with Libav; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "libavutil/mathematics.h" | |||
| #include "adx.h" | |||
| void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff) | |||
| { | |||
| double a, b, c; | |||
| a = M_SQRT2 - cos(2.0 * M_PI * cutoff / sample_rate); | |||
| b = M_SQRT2 - 1.0; | |||
| c = (a - sqrt((a + b) * (a - b))) / b; | |||
| coeff[0] = lrintf(c * 2.0 * (1 << bits)); | |||
| coeff[1] = lrintf(-(c * c) * (1 << bits)); | |||
| } | |||
| @@ -41,10 +41,20 @@ typedef struct { | |||
| int header_parsed; | |||
| unsigned char dec_temp[18*2]; | |||
| int in_temp; | |||
| int cutoff; | |||
| int coeff[2]; | |||
| } ADXContext; | |||
| #define COEFF_BITS 12 | |||
| #define COEFF1 0x1CA6 | |||
| #define COEFF2 0x0CD4 | |||
| /** | |||
| * Calculate LPC coefficients based on cutoff frequency and sample rate. | |||
| * | |||
| * @param cutoff cutoff frequency | |||
| * @param sample_rate sample rate | |||
| * @param bits number of bits used to quantize coefficients | |||
| * @param[out] coeff 2 quantized LPC coefficients | |||
| */ | |||
| void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff); | |||
| #endif /* AVCODEC_ADX_H */ | |||
| @@ -59,7 +59,7 @@ static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) | |||
| s2 = prev->s2; | |||
| for (i = 0; i < 32; i++) { | |||
| d = get_sbits(&gb, 4); | |||
| s0 = ((d << COEFF_BITS) * scale + COEFF1 * s1 - COEFF2 * s2) >> COEFF_BITS; | |||
| s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS; | |||
| s2 = s1; | |||
| s1 = av_clip_int16(s0); | |||
| *out = s1; | |||
| @@ -81,7 +81,7 @@ static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, | |||
| int bufsize) | |||
| { | |||
| ADXContext *c = avctx->priv_data; | |||
| int offset; | |||
| int offset, cutoff; | |||
| if (AV_RB16(buf) != 0x8000) | |||
| return AVERROR_INVALIDDATA; | |||
| @@ -98,6 +98,9 @@ static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, | |||
| return AVERROR_INVALIDDATA; | |||
| avctx->bit_rate = avctx->sample_rate * avctx->channels * 18 * 8 / 32; | |||
| cutoff = AV_RB16(buf + 16); | |||
| ff_adx_calculate_coeffs(cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); | |||
| return offset; | |||
| } | |||
| @@ -34,7 +34,7 @@ | |||
| /* 18 bytes <-> 32 samples */ | |||
| static void adx_encode(unsigned char *adx,const short *wav, | |||
| static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, | |||
| ADXChannelState *prev) | |||
| { | |||
| int scale; | |||
| @@ -48,7 +48,7 @@ static void adx_encode(unsigned char *adx,const short *wav, | |||
| s2 = prev->s2; | |||
| for(i=0;i<32;i++) { | |||
| s0 = wav[i]; | |||
| d = ((s0 << COEFF_BITS) - COEFF1 * s1 + COEFF2 * s2) >> COEFF_BITS; | |||
| d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; | |||
| data[i]=d; | |||
| if (max<d) max=d; | |||
| if (min>d) min=d; | |||
| @@ -102,19 +102,24 @@ static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t buf | |||
| } adxhdr; /* big endian */ | |||
| /* offset-6 "(c)CRI" */ | |||
| #endif | |||
| ADXContext *c = avctx->priv_data; | |||
| AV_WB32(buf+0x00,0x80000000|0x20); | |||
| AV_WB32(buf+0x04,0x03120400|avctx->channels); | |||
| AV_WB32(buf+0x08,avctx->sample_rate); | |||
| AV_WB32(buf+0x0c,0); /* FIXME: set after */ | |||
| AV_WB32(buf+0x10,0x01040300); | |||
| AV_WB32(buf+0x14,0x00000000); | |||
| AV_WB32(buf+0x18,0x00000000); | |||
| memcpy(buf+0x1c,"\0\0(c)CRI",8); | |||
| AV_WB16(buf + 0x10, c->cutoff); | |||
| AV_WB32(buf + 0x12, 0x03000000); | |||
| AV_WB32(buf + 0x16, 0x00000000); | |||
| AV_WB32(buf + 0x1a, 0x00000000); | |||
| memcpy (buf + 0x1e, "(c)CRI", 6); | |||
| return 0x20+4; | |||
| } | |||
| static av_cold int adx_encode_init(AVCodecContext *avctx) | |||
| { | |||
| ADXContext *c = avctx->priv_data; | |||
| if (avctx->channels > 2) | |||
| return -1; /* only stereo or mono =) */ | |||
| avctx->frame_size = 32; | |||
| @@ -124,6 +129,10 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) | |||
| // avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; | |||
| /* the cutoff can be adjusted, but this seems to work pretty well */ | |||
| c->cutoff = 500; | |||
| ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); | |||
| av_log(avctx, AV_LOG_DEBUG, "adx encode init\n"); | |||
| return 0; | |||
| @@ -159,7 +168,7 @@ static int adx_encode_frame(AVCodecContext *avctx, | |||
| if (avctx->channels==1) { | |||
| while(rest>=32) { | |||
| adx_encode(dst,samples,c->prev); | |||
| adx_encode(c, dst, samples, c->prev); | |||
| dst+=18; | |||
| samples+=32; | |||
| rest-=32; | |||
| @@ -174,8 +183,8 @@ static int adx_encode_frame(AVCodecContext *avctx, | |||
| tmpbuf[i+32] = samples[i*2+1]; | |||
| } | |||
| adx_encode(dst,tmpbuf,c->prev); | |||
| adx_encode(dst+18,tmpbuf+32,c->prev+1); | |||
| adx_encode(c, dst, tmpbuf, c->prev); | |||
| adx_encode(c, dst + 18, tmpbuf + 32, c->prev + 1); | |||
| dst+=18*2; | |||
| samples+=32*2; | |||
| rest-=32*2; | |||