[FFmpeg-devel] AMR-NB decoder

Colin McQuillan m.niloc
Mon Aug 10 22:54:53 CEST 2009


2009/8/6 Michael Niedermayer <michaelni at gmx.at>:
> On Wed, Aug 05, 2009 at 05:51:36PM +0100, Colin McQuillan wrote:
>> Attached is a patch for an AMR-NB decoder.
>>
>> It is not bit-exact. This makes it tricky to verify, but I have been
>> checking that internal parameters match the 3GPP decoder for the AMR
>> test sequences. The PSNR between the input and output is 3.90 to 8.42
>> which is about the same as the reference decoder. The PSNR between the
>> two outputs is between 8.50 and 18.16, which seems quite good.
>
[...]

>> +
>> +
>> +// The following order* tables are used to convert AMR frame parameters to and
>> +// from a bitstream. See 3GPP TS 26.101 for more information.
>> +
>> +#define AMR_BIT(field, bit) ? ? ? ? ? ? ? ? ?{offsetof(AMRNBFrame, field) >> 1, bit}
>
>> +/** Specify an LSF parameter bit */
>> +#define AMR_LSF(variable, bit) ? ? ? ? ? ? ? AMR_BIT(lsf[variable], bit)
>> +/** Specify a subframe-specific bit */
>> +#define AMR_OF(frame_num, variable, bit) ? ? AMR_BIT(info.subframe[frame_num].variable, bit)
>> +/** Specify a pitch gain bit */
>> +#define AMR_PGAIN(frame_num, bit) ? ? ? ? ? ?AMR_OF(frame_num, p_gain, bit)
>> +/** Specify a fixed gain bit */
>> +#define AMR_FIXED_GAIN(frame_num, bit) ? ? ? AMR_OF(frame_num, fixed_gain, bit)
>> +/** Specify a pitch lag bit */
>> +#define AMR_PLAG(frame_num, bit) ? ? ? ? ? ? AMR_OF(frame_num, p_lag, bit)
>> +/** Specify a pulse bit */
>> +#define AMR_PULSES(frame_num, pulse_id, bit) AMR_OF(frame_num, pulses[pulse_id], bit)
>> +/** Specify an SID reference vector bit */
>> +#define AMR_SVECTOR(bit) ? ? ? ? ? ? ? ? ? ? AMR_BIT(info.sid.ref_vector, bit)
>> +/** Specify an SID energy index bit */
>> +#define AMR_SENERGY(bit) ? ? ? ? ? ? ? ? ? ? AMR_BIT(info.sid.energy, bit)
>
> are these macros really useful?

Yes, very useful for the bit order tables. They allow four bits per
line instead of just two if I used offsetof.

[...]

>> +{
>> + ? ?enum Mode mode;
>> +
>> + ? ?init_get_bits(&p->gb, buf, buf_size * 8);
>> +
>> + ? ?// Decode the first octet.
>> + ? ?skip_bits(&p->gb, 1); ? ? ? ? ? ? ? ? ? ? ? ?// padding bit
>> + ? ?mode = get_bits(&p->gb, 4); ? ? ? ? ? ? ? ? ?// frame type
>> + ? ?p->bad_frame_indicator = !get_bits1(&p->gb); // quality bit
>> + ? ?skip_bits(&p->gb, 2); ? ? ? ? ? ? ? ? ? ? ? ?// two padding bits
>> +
>> + ? ?if (mode <= MODE_DTX) {
>> + ? ? ? ?uint16_t *data = (uint16_t *)&p->frame;
>> + ? ? ? ?const AMROrder *order = amr_unpacking_bitmaps_per_mode[mode];
>> + ? ? ? ?int i;
>> +
>> + ? ? ? ?memset(&p->frame, 0, sizeof(AMRNBFrame));
>
>> + ? ? ? ?for (i = 0; i < mode_bits[mode]; i++)
>> + ? ? ? ? ? ?data[order[i].index] += get_bits1(&p->gb) << order[i].bit;
>
> it might reduce code size and improve speed if more than 1 bit would
> be read where possible

The bits are very scattered. (I guess because it's not really designed
as a file format - it's just a wire protocol dumped to a file.) There
are 1240 bits overall, and 874 sequences of consecutive bits (about
two hundred runs in either direction). I've tried reading more than
one bit at a time and it was slower.

I have tried to address every other comment made in the thread. The
main changes are cosmetics, using fixed point tables to save space,
and keeping the algebraic codebook vector sparse until
anti_sparseness.

amrnb-decoder-r2.patch uses high-pass-filterf.patch, agc-3.patch, and
circ-addf.patch.

> [...]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: circ-addf.patch
Type: text/x-diff
Size: 1590 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090810/c54ac743/attachment.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: amrnb-decoder-r2.patch
Type: text/x-diff
Size: 169840 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090810/c54ac743/attachment-0001.patch>



More information about the ffmpeg-devel mailing list