[FFmpeg-devel] [PATCH] QCELP decoder
Michael Niedermayer
michaelni
Mon Dec 1 22:39:58 CET 2008
On Mon, Dec 01, 2008 at 12:45:09PM -0800, Kenan Gillet wrote:
> Hi,
> On Mon, Dec 1, 2008 at 8:24 AM, Michael Niedermayer <michaelni at gmx.at> wrote:
> > On Mon, Dec 01, 2008 at 08:17:52AM -0800, Kenan Gillet wrote:
> >>
> >> On Dec 1, 2008, at 4:52 AM, Michael Niedermayer wrote:
> >>
> >> > On Sun, Nov 30, 2008 at 05:04:07PM -0800, Kenan Gillet wrote:
> >> >> Hi,
> >> >> On Nov 30, 2008, at 7:50 AM, Michael Niedermayer wrote:
> >> >>
> >> >>> On Sat, Nov 29, 2008 at 10:39:58AM -0800, Kenan Gillet wrote:
> > [...]
> >> > [...]
> >> >>>> + /**
> >> >>>> + * reserved bits on all bitrate but bitrate 1/2 packets
> >> >>>
> >> >>> this is unclear, field that is on all but ... , vs. field that
> >> >>> exists always but
> >> >>> is reserved on all but .....
> >> >>>
> >> >>
> >> >> is "reserved bits only set for bitrate 1, 1/4 and 1/8" better ?
> >> >
> >> > no, because setting them means error IIRC
> >> > also IIRC there is no indication of the existence of other fields
> >> > for the
> >> > other rates ...
> >> >
> >>
> >> reserved bits only present in bitrate 1, 1/4 and 1/8 packets
> >>
> >> ?
> >
> > ok
> >
> > [...]
>
> here is an updated round 14 of the patches,
> which is getting smaller and smaller :)
>
> Kenan
[...]
> Index: libavcodec/qcelpdec.c
> ===================================================================
> --- libavcodec/qcelpdec.c (revision 15972)
> +++ libavcodec/qcelpdec.c (working copy)
> @@ -31,7 +31,6 @@
> #include "avcodec.h"
> #include "bitstream.h"
>
> -#include "qcelp.h"
> #include "qcelpdata.h"
>
> #include "celp_math.h"
> @@ -40,6 +39,16 @@
> #undef NDEBUG
> #include <assert.h>
>
> +typedef enum
> +{
> + I_F_Q = -1, /*!< insufficient frame quality */
> + SILENCE,
> + RATE_OCTAVE,
> + RATE_QUARTER,
> + RATE_HALF,
> + RATE_FULL
> +} qcelp_packet_rate;
> +
> typedef struct {
> GetBitContext gb;
> qcelp_packet_rate bitrate;
> @@ -49,6 +58,9 @@
> float prev_lspf[10];
> float predictor_lspf[10]; /*!< LSP predictor,
> only use for RATE_OCTAVE and I_F_Q */
> + float pitch_synthesis_filter_mem[303];
> + float pitch_pre_filter_mem[303];
> + float rnd_fir_filter_mem[180];
> float formant_mem[170];
> float last_codebook_gain;
> int prev_g1[2];
> @@ -58,6 +70,13 @@
> uint16_t first16bits;
> } QCELPContext;
>
> +/**
> + * Reconstructs LPC coefficients from the line spectral pair frequencies.
> + *
> + * TIA/EIA/IS-733 2.4.3.3.5
> + */
> +void qcelp_lspf2lpc(const float *lspf, float *lpc);
> +
> static void weighted_vector_sumf(float *out, const float *in_a,
> const float *in_b, float weight_coeff_a,
> float weight_coeff_b, int length)
ok
> @@ -476,6 +495,64 @@
> }
>
> /**
> + * Apply pitch synthesis filter and pitch prefilter to the scaled codebook vector.
> + * TIA/EIA/IS-733 2.4.5.2
> + *
> + * @param q the context
> + * @param cdn_vector the scaled codebook vector
> + */
> +static void apply_pitch_filters(QCELPContext *q,
> + float *cdn_vector) {
> + int i;
> + float gain[4];
> + const float *v_synthesis_filtered, *v_pre_filtered;
> +
> + if (q->bitrate >= RATE_HALF ||
> + (q->bitrate == I_F_Q && (q->prev_bitrate >= RATE_HALF))) {
> +
> + if (q->bitrate >= RATE_HALF) {
> +
> + // Compute gain & lag for the whole frame.
> + for (i = 0; i < 4; i++) {
> + gain[i] = q->frame.plag[i] ? (q->frame.pgain[i] + 1) * 0.25 : 0.0;
> +
> + q->frame.plag[i] += 16;
> + }
> + memcpy(q->prev_pitch_lag, q->frame.plag, sizeof(q->frame.plag));
> + } else {
> + gain[3] = q->erasure_count < 3 ? 0.9 - 0.3 * (q->erasure_count - 1)
> + : 0.0;
> + for (i = 0; i < 4; i++)
> + gain[i] = FFMIN(q->prev_pitch_gain[i], gain[3]);
> +
> + memset(q->frame.pfrac, 0, sizeof(q->frame.pfrac));
> + memcpy(q->frame.plag, q->prev_pitch_lag, sizeof(q->frame.plag));
i think if prev_pitch_lag was used in the surrounding code then this memcpy
would be unneeded
> + }
> +
> + // pitch synthesis filter
> + v_synthesis_filtered = do_pitchfilter(q->pitch_synthesis_filter_mem, cdn_vector,
> + gain, q->frame.plag, q->frame.pfrac);
> +
> + // pitch prefilter update
> + for (i = 0; i < 4; i++)
> + gain[i] = 0.5 * FFMIN(gain[i], 1.0);
> +
> + v_pre_filtered = do_pitchfilter(q->pitch_pre_filter_mem, v_synthesis_filtered,
> + gain, q->frame.plag, q->frame.pfrac);
> +
> + apply_gain_ctrl(cdn_vector, v_synthesis_filtered, v_pre_filtered);
> +
> + memcpy(q->prev_pitch_gain, gain, sizeof(q->prev_pitch_gain));
cant prev_pitch_gain be directly used instead of gain that then is copied
back?
(possibly with a better var name than prev_pitch_gain)
> +
> + } else {
> + memcpy(q->pitch_synthesis_filter_mem, cdn_vector + 17, 143 * sizeof(float));
> + memcpy(q->pitch_pre_filter_mem, cdn_vector + 17, 143 * sizeof(float));
> + memset(q->prev_pitch_gain, 0, sizeof(q->prev_pitch_gain));
> + memset(q->prev_pitch_lag, 0, sizeof(q->prev_pitch_lag));
> + }
> +}
> +
> +/**
> * Interpolates LSP frequencies and computes LPC coefficients
> * for a given bitrate & pitch subframe.
> *
> @@ -527,6 +604,46 @@
> return -1;
> }
>
> +/**
> + * Determine the bitrate from the frame size and/or the first byte of the frame.
> + *
> + * @param avctx the AV codec context
> + * @param buf_size length of the buffer
> + * @param buf the bufffer
> + *
> + * @return the bitrate on success,
> + * I_F_Q if the bitrate cannot be satisfactorily determined
> + *
> + * TIA/EIA/IS-733 2.4.8.7.1
> + */
> +static int determine_bitrate(AVCodecContext *avctx,
> + const int buf_size,
> + uint8_t **buf) {
> + qcelp_packet_rate bitrate;
> +
> + if ((bitrate = buf_size2bitrate(buf_size)) >= 0) {
> + if (bitrate > **buf) {
> + av_log(avctx, AV_LOG_WARNING, "Claimed bitrate and buffer size mismatch.\n");
> + bitrate = **buf;
> + } else if (bitrate < **buf) {
> + av_log(avctx, AV_LOG_ERROR, "Buffer is too small for the claimed bitrate.\n");
> + return I_F_Q;
> + }
> + (*buf)++;
> + } else if ((bitrate = buf_size2bitrate(buf_size + 1)) >= 0) {
> + av_log(avctx, AV_LOG_WARNING,
> + "Bitrate byte is missing, guessing the bitrate from packet size.\n");
> + } else
> + return I_F_Q;
> +
> + if (bitrate == SILENCE) {
> + // FIXME: the decoder should not handle SILENCE frames as I_F_Q frames
> + av_log_missing_feature(avctx, "Blank frame", 1);
> + bitrate = I_F_Q;
> + }
> + return bitrate;
> +}
> +
> static void warn_insufficient_frame_quality(AVCodecContext *avctx,
> const char *message)
> {
ok
[...]
> Index: libavformat/mov.c
> ===================================================================
> --- libavformat/mov.c (revision 15972)
> +++ libavformat/mov.c (working copy)
> @@ -988,6 +988,10 @@
> #endif
> /* no ifdef since parameters are always those */
> case CODEC_ID_QCELP:
> + st->need_parsing = AVSTREAM_PARSE_FULL;
> + st->codec->frame_size= 160;
> + st->codec->channels= 1; /* really needed */
if this is really needed then its ok
> + break;
> case CODEC_ID_AMR_NB:
> case CODEC_ID_AMR_WB:
> st->codec->frame_size= sc->samples_per_frame;
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
No snowflake in an avalanche ever feels responsible. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20081201/e1efb743/attachment.pgp>
More information about the ffmpeg-devel
mailing list