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_PCM_ZORK_DECODER) += pcm.o | ||||
| OBJS-$(CONFIG_ADPCM_4XM_DECODER) += adpcm.o adpcm_data.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_ADX_ENCODER) += adxenc.o | ||||
| OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o | OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.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; | int header_parsed; | ||||
| unsigned char dec_temp[18*2]; | unsigned char dec_temp[18*2]; | ||||
| int in_temp; | int in_temp; | ||||
| int cutoff; | |||||
| int coeff[2]; | |||||
| } ADXContext; | } ADXContext; | ||||
| #define COEFF_BITS 12 | #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 */ | #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; | s2 = prev->s2; | ||||
| for (i = 0; i < 32; i++) { | for (i = 0; i < 32; i++) { | ||||
| d = get_sbits(&gb, 4); | 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; | s2 = s1; | ||||
| s1 = av_clip_int16(s0); | s1 = av_clip_int16(s0); | ||||
| *out = s1; | *out = s1; | ||||
| @@ -81,7 +81,7 @@ static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, | |||||
| int bufsize) | int bufsize) | ||||
| { | { | ||||
| ADXContext *c = avctx->priv_data; | ADXContext *c = avctx->priv_data; | ||||
| int offset; | |||||
| int offset, cutoff; | |||||
| if (AV_RB16(buf) != 0x8000) | if (AV_RB16(buf) != 0x8000) | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| @@ -98,6 +98,9 @@ static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, | |||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| avctx->bit_rate = avctx->sample_rate * avctx->channels * 18 * 8 / 32; | 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; | return offset; | ||||
| } | } | ||||
| @@ -34,7 +34,7 @@ | |||||
| /* 18 bytes <-> 32 samples */ | /* 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) | ADXChannelState *prev) | ||||
| { | { | ||||
| int scale; | int scale; | ||||
| @@ -48,7 +48,7 @@ static void adx_encode(unsigned char *adx,const short *wav, | |||||
| s2 = prev->s2; | s2 = prev->s2; | ||||
| for(i=0;i<32;i++) { | for(i=0;i<32;i++) { | ||||
| s0 = wav[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; | data[i]=d; | ||||
| if (max<d) max=d; | if (max<d) max=d; | ||||
| if (min>d) min=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 */ | } adxhdr; /* big endian */ | ||||
| /* offset-6 "(c)CRI" */ | /* offset-6 "(c)CRI" */ | ||||
| #endif | #endif | ||||
| ADXContext *c = avctx->priv_data; | |||||
| AV_WB32(buf+0x00,0x80000000|0x20); | AV_WB32(buf+0x00,0x80000000|0x20); | ||||
| AV_WB32(buf+0x04,0x03120400|avctx->channels); | AV_WB32(buf+0x04,0x03120400|avctx->channels); | ||||
| AV_WB32(buf+0x08,avctx->sample_rate); | AV_WB32(buf+0x08,avctx->sample_rate); | ||||
| AV_WB32(buf+0x0c,0); /* FIXME: set after */ | 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; | return 0x20+4; | ||||
| } | } | ||||
| static av_cold int adx_encode_init(AVCodecContext *avctx) | static av_cold int adx_encode_init(AVCodecContext *avctx) | ||||
| { | { | ||||
| ADXContext *c = avctx->priv_data; | |||||
| if (avctx->channels > 2) | if (avctx->channels > 2) | ||||
| return -1; /* only stereo or mono =) */ | return -1; /* only stereo or mono =) */ | ||||
| avctx->frame_size = 32; | 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; | // 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"); | av_log(avctx, AV_LOG_DEBUG, "adx encode init\n"); | ||||
| return 0; | return 0; | ||||
| @@ -159,7 +168,7 @@ static int adx_encode_frame(AVCodecContext *avctx, | |||||
| if (avctx->channels==1) { | if (avctx->channels==1) { | ||||
| while(rest>=32) { | while(rest>=32) { | ||||
| adx_encode(dst,samples,c->prev); | |||||
| adx_encode(c, dst, samples, c->prev); | |||||
| dst+=18; | dst+=18; | ||||
| samples+=32; | samples+=32; | ||||
| rest-=32; | rest-=32; | ||||
| @@ -174,8 +183,8 @@ static int adx_encode_frame(AVCodecContext *avctx, | |||||
| tmpbuf[i+32] = samples[i*2+1]; | 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; | dst+=18*2; | ||||
| samples+=32*2; | samples+=32*2; | ||||
| rest-=32*2; | rest-=32*2; | ||||