[FFmpeg-devel] [PATCH] QCELP decoder
Kenan Gillet
kenan.gillet
Sun Oct 5 18:18:32 CEST 2008
Hi,
On Oct 4, 2008, at 5:09 PM, Michael Niedermayer wrote:
> On Fri, Oct 03, 2008 at 03:48:52PM -0700, Kenan Gillet wrote:
>> Hi,
>>
>> here is a round 2 of the patch based on feedback from Vitor and
>> Diego.
>> It includes:
>> - some spelling/grammar fixes,
>> - some cosmetics,
>> - changes to output float instead of int,
>> - bug fixes uncovered from the change of output,
>> - improvements to the pitch pre/synthesis filters.
>>
>> Kenan
> [...]
>> +typedef enum
>> +{
>> + BLANK = 0,
>
> is this supposed to mean silence? if so it should be named accordingly
I suppose since if encountered the scaled codebook vector must be fill
with 0.
Should i change it to SILENCE ?
> [...]
>> +static int qcelp_find_frame_end(const uint8_t *buf, const int
>> buf_size) {
>> + // Let's try and see if this packet holds exactly one frame
>> +
>> + switch (buf_size) {
>> + case 35: // RATE_FULL
>> + case 17: // RATE_HALF
>> + case 8: // RATE_QUARTER
>> + case 4: // RATE_OCTAVE
>> +
>> + // the first byte describing the type of frame is
>> missing.
>> + // TODO: not tested, it needs samples.
>> + case 34: // RATE_FULL
>> + case 16: // RATE_HALF
>> + case 7: // RATE_QUARTER
>> + case 3: // RATE_OCTAVE
>> + return buf_size;
>> +
>> + case 2:
>> + case 1:
>> + case 0:
>> + return END_NOT_FOUND;
>> + }
>> +
>> + /*
>> + * If we reach this point it means the packet holds a multiset
>> of
>> + * frames, each one of them in codec frame format, all with
>> the same
>> + * framerate, as described in:
>> + *
>> + * http://tools.ietf.org/html/draft-mckay-qcelp-02
>> + *
>> + * TODO: not tested, it needs samples.
>> + */
>> +
>> + switch (buf[0]) {
>> + case RATE_FULL:
>> + return 35;
>> + case RATE_HALF:
>> + return 17;
>> + case RATE_QUARTER:
>> + return 8;
>> + case RATE_OCTAVE:
>> + return 4;
>> + }
>> +
>> + return END_NOT_FOUND;
>> +}
>
> The code above looks wrong and messy, either
> A. a parser is needed in which case it must function with any amount
> of data,
> that is its input may always be a single byte or random pieces of
> the
> bitstream. (above clearly can not even remotely handle these)
> B. no parser is needed (in which case this file clearly is unneeded)
> C. something else is going on, but this requires to be documented and
> explained
I don't really know for sure.
My guess is that the parser is needed when the container is RTP because
a packet can contain multiple frame
http://tools.ietf.org/html/draft-mckay-qcelp-02
but i have seen/tested such example.
I suggest we go with B. since 'no parser' is needed for the samples I
have.
>
> [...]
>> +#define QCELP_RATE_FULL_BITMAP \
>> +{62,2},{62,1},{62,0},{61,6},{61,5},{61,4},{61,3},{61,2},\
>> +{61,1},{61,0},{60,5},{60,4},{60,3},{60,2},{60,1},{60,0},\
>> +{64,5},{64,4},{64,3},{64,2},{64,1},{64,0},{63,5},{63,4},\
>> +{63,3},{63,2},{63,1},{63,0},{62,6},{62,5},{62,4},{62,3},\
>> +{ 0,0},{16,3},{16,2},{16,1},{16,0},{52,0},{48,6},{48,5},\
>> +{48,4},{48,3},{48,2},{48,1},{48,0},{56,2},{56,1},{56,0},\
>> +{33,3},{33,2},{33,1},{33,0},{ 1,0},{17,3},{17,2},{17,1},\
>> +{17,0},{32,6},{32,5},{32,4},{32,3},{32,2},{32,1},{32,0},\
>> +{19,0},{34,6},{34,5},{34,4},{34,3},{34,2},{34,1},{34,0},\
>> +{ 2,0},{18,3},{18,2},{18,1},{18,0},{33,6},{33,5},{33,4},\
>> +{49,2},{49,1},{49,0},{57,2},{57,1},{57,0},{35,6},{35,5},\
>> +{35,4},{35,3},{35,2},{35,1},{35,0},{ 3,0},{19,2},{19,1},\
>> +{36,5},{36,4},{36,3},{36,2},{36,1},{36,0},{ 4,0},{20,3},\
>> +{20,2},{20,1},{20,0},{53,0},{49,6},{49,5},{49,4},{49,3},\
>> +{22,2},{22,1},{22,0},{37,6},{37,5},{37,4},{37,3},{37,2},\
>> +{37,1},{37,0},{ 5,0},{21,3},{21,2},{21,1},{21,0},{36,6},\
>> +{39,2},{39,1},{39,0},{ 7,0},{23,2},{23,1},{23,0},{38,6},\
>> +{38,5},{38,4},{38,3},{38,2},{38,1},{38,0},{ 6,0},{22,3},\
>> +{24,0},{54,0},{50,6},{50,5},{50,4},{50,3},{50,2},{50,1},\
>> +{50,0},{58,2},{58,1},{58,0},{39,6},{39,5},{39,4},{39,3},\
>> +{ 9,0},{25,3},{25,2},{25,1},{25,0},{40,6},{40,5},{40,4},\
>> +{40,3},{40,2},{40,1},{40,0},{ 8,0},{24,3},{24,2},{24,1},\
>> +{42,3},{42,2},{42,1},{42,0},{10,0},{26,3},{26,2},{26,1},\
>> +{26,0},{41,6},{41,5},{41,4},{41,3},{41,2},{41,1},{41,0},\
>> +{59,1},{59,0},{43,6},{43,5},{43,4},{43,3},{43,2},{43,1},\
>> +{43,0},{11,0},{27,2},{27,1},{27,0},{42,6},{42,5},{42,4},\
>> +{44,1},{44,0},{12,0},{28,3},{28,2},{28,1},{28,0},{55,0},\
>> +{51,6},{51,5},{51,4},{51,3},{51,2},{51,1},{51,0},{59,2},\
>> +{45,5},{45,4},{45,3},{45,2},{45,1},{45,0},{13,0},{29,3},\
>> +{29,2},{29,1},{29,0},{44,6},{44,5},{44,4},{44,3},{44,2},\
>> +{31,2},{31,1},{31,0},{46,6},{46,5},{46,4},{46,3},{46,2},\
>> +{46,1},{46,0},{14,0},{30,3},{30,2},{30,1},{30,0},{45,6},\
>> +{65,1},{65,0},{47,6},{47,5},{47,4},{47,3},{47,2},{47,1},\
>> +{47,0},{15,0}
>> +
>> +#define QCELP_RATE_HALF_BITMAP \
>> +{62,2},{62,1},{62,0},{61,6},{61,5},{61,4},{61,3},{61,2},\
>> +{61,1},{61,0},{60,5},{60,4},{60,3},{60,2},{60,1},{60,0},\
>> +{64,5},{64,4},{64,3},{64,2},{64,1},{64,0},{63,5},{63,4},\
>> +{63,3},{63,2},{63,1},{63,0},{62,6},{62,5},{62,4},{62,3},\
>> +{ 0,0},{16,3},{16,2},{16,1},{16,0},{52,0},{48,6},{48,5},\
>> +{48,4},{48,3},{48,2},{48,1},{48,0},{56,2},{56,1},{56,0},\
>> +{49,5},{49,4},{49,3},{49,2},{49,1},{49,0},{57,2},{57,1},\
>> +{57,0},{32,6},{32,5},{32,4},{32,3},{32,2},{32,1},{32,0},\
>> +{58,1},{58,0},{33,6},{33,5},{33,4},{33,3},{33,2},{33,1},\
>> +{33,0},{ 1,0},{17,3},{17,2},{17,1},{17,0},{53,0},{49,6},\
>> +{34,1},{34,0},{ 2,0},{18,3},{18,2},{18,1},{18,0},{54,0},\
>> +{50,6},{50,5},{50,4},{50,3},{50,2},{50,1},{50,0},{58,2},\
>> +{55,0},{51,6},{51,5},{51,4},{51,3},{51,2},{51,1},{51,0},\
>> +{59,2},{59,1},{59,0},{34,6},{34,5},{34,4},{34,3},{34,2},\
>> +{35,6},{35,5},{35,4},{35,3},{35,2},{35,1},{35,0},{ 3,0},\
>> +{19,3},{19,2},{19,1},{19,0}
>> +
>> +#define QCELP_RATE_4THR_BITMAP \
>> +{62,2},{62,1},{62,0},{61,6},{61,5},{61,4},{61,3},{61,2},\
>> +{61,1},{61,0},{60,5},{60,4},{60,3},{60,2},{60,1},{60,0},\
>> +{64,5},{64,4},{64,3},{64,2},{64,1},{64,0},{63,5},{63,4},\
>> +{63,3},{63,2},{63,1},{63,0},{62,6},{62,5},{62,4},{62,3},\
>> +{19,3},{19,2},{19,1},{19,0},{18,3},{18,2},{18,1},{18,0},\
>> +{17,3},{17,2},{17,1},{17,0},{16,3},{16,2},{16,1},{16,0},\
>> +{65,1},{65,0},{20,3},{20,2},{20,1},{20,0}
>> +
>> +#define QCELP_RATE_8THR_BITMAP \
>> +{76,3},{66,0},{67,0},{68,0},{76,2},{69,0},{70,0},{71,0},\
>> +{76,1},{72,0},{73,0},{74,0},{76,0},{75,0},{16,1},{16,0},\
>> +{65,3},{65,2},{65,1},{65,0}
>> +
>> +static const QCELPBitmap QCELP_REFERENCE_FRAME[464] =
>> {QCELP_RATE_FULL_BITMAP,
>> +
>> QCELP_RATE_HALF_BITMAP,
>> +
>> QCELP_RATE_4THR_BITMAP,
>> +
>> QCELP_RATE_8THR_BITMAP};
>> +/**
>> + * position of the bitmapping data for each pkt type in
>> + * the big REFERENCE FRAME array
>> + */
>> +static const QCELPBitmap *qcelp_unpacking_bitmpap_per_rate[6] = {
>> + NULL, /*!< for BLANK */
>> + QCELP_REFERENCE_FRAME + 444, /*!< for RATE_OCTAVE */
>> + QCELP_REFERENCE_FRAME + 390, /*!< for RATE_QUARTER */
>> + QCELP_REFERENCE_FRAME + 266, /*!< for RATE_HALF */
>> + QCELP_REFERENCE_FRAME, /*!< for RATE_FULL */
>> + NULL /*!< for I_F_Q */
>> +};
>
> 4 arrays and 1 array of pointers to the 4 arrays would be cleaner IMHO
done, kept the array to 6 elements since because it simplifies the
selection of the
unpacking bitmap which reduces to:
qcelp_unpacking_bitmpap_per_rate[q->framerate]
>> +
>> +/**
>> + * position of the transmission codes inside the universal frame
>> + */
>> +
>> +#define QCELP_CBSIGN0_POS 0
>> +#define QCELP_CBGAIN0_POS 16
>> +#define QCELP_CINDEX0_POS 32
>> +#define QCELP_PLAG0_POS 48
>> +#define QCELP_PFRAC0_POS 52
>> +#define QCELP_PGAIN0_POS 56
>> +#define QCELP_LSPV0_POS 60
>> +#define QCELP_RSRVD_POS 65 /*!< on all but rate 1/2 packets */
>> +#define QCELP_LSP0_POS 66 /*!< only in rate 1/8 packets */
>> +#define QCELP_CBSEED_POS 76 /*!< only in rate 1/8 packets */
>
> instead of funny 'something= data + QCELP*_POS; something' please make
> this use context->something
> the "translation" tables should not contain indexes into a abstract
> byte
> array but into a struct IMHO.
done, it is much cleaner now :)
> [...]
>> +static const double qcelp_rnd_fir_coefs[22] = {
>> + 0 , -1.344519e-1, 1.735384e-2, -6.905826e-2,
>> + 2.434368e-2, -8.210701e-2, 3.041388e-2, -9.251384e-2,
>> + 3.501983e-2, -9.918777e-2, 3.749518e-2, 8.985137e-1,
>> + 3.749518e-2, -9.918777e-2, 3.501983e-2, -9.251384e-2,
>> + 3.041388e-2, -8.210701e-2, 2.434368e-2, -6.905826e-2,
>> + 1.735384e-2, -1.344519e-1
>> +}; /*!< Start reading from [1]. */
>> +
>> +#define QCELP_LSP_SPREAD_FACTOR 0.02
>
>> +#define QCELP_LSP_OCTAVE_PREDICTOR 0.90625
>
> a comment of "29/32" could be usefull
done
> [...]
>> +static void interpolate_lspf(float *interpolated_lspf, const float
>> curr_weight,
>> + const float *curr_lspf, const float
>> *prev_lspf) {
>> + int i;
>> +
>
>> + for (i=0;i<10;i++)
>> + interpolated_lspf[i] = (1.0 - curr_weight) * prev_lspf[i]
>> + + curr_weight * curr_lspf[i];
>
> this can be vertically aligned
done
> [...]
>> +
>> +/**
>> + * Decodes the 10 quantized LSP frequencies from the LSPV/LSP
>> + * transmission codes of any framerate and check for badly
>> + * received packets.
>> + *
>> + * TIA/EIA/IS-733 2.4.3.2.6.2-2, 2.4.8.7.3
>> + */
>> +static int decode_lspf(QCELPContext *q, float *lspf) {
>> + const uint8_t *lspv;
>> + int i;
>> + float predictor;
>> +
>
>> + if (q->rate == RATE_OCTAVE) {
>> + q->octave_count++;
>> +
>> + lspv=q->data+QCELP_LSP0_POS;
>> + for (i=0; i<10; i++) {
>> + lspf[i] = (i + 1) / (float)(10 + 1)
>> + + (lspv[i] ? QCELP_LSP_SPREAD_FACTOR *
>> QCELP_LSP_OCTAVE_PREDICTOR
>> + : -QCELP_LSP_SPREAD_FACTOR *
>> QCELP_LSP_OCTAVE_PREDICTOR);
>> + }
>> +
>
>> + // Check the stability of the LSP frequencies.
>> + if (lspf[0] < QCELP_LSP_SPREAD_FACTOR)
>> + lspf[0] = QCELP_LSP_SPREAD_FACTOR;
>
> this cannot be true
>
>
>> + for (i = 1; i < 10; i++) {
>> + if (lspf[i] < lspf[i-1] + QCELP_LSP_SPREAD_FACTOR)
>> + lspf[i] = lspf[i-1] + QCELP_LSP_SPREAD_FACTOR;
>> + }
>
> neither can this
>
>
>> + if (lspf[9] > 1.0 - QCELP_LSP_SPREAD_FACTOR)
>> + lspf[9] = 1.0 - QCELP_LSP_SPREAD_FACTOR;
>
> nor this
>
>
>> + for (i = 9; i > 0; i--) {
>> + if (lspf[i-1] > lspf[i] - QCELP_LSP_SPREAD_FACTOR)
>> + lspf[i-1] = lspf[i] - QCELP_LSP_SPREAD_FACTOR;
>> + }
>
> and even the duplicated code cannot be true
>>
for the 3 issues above, it comes from the wrong calculation of lspf
above.
I do not quite understand how to udpate/calculate the predicator.
I'll try to dig more into it, but any help/hint would be welcome :)
>
>> +
>> + // Low-pass filter the LSP frequencies
>> + if (q->octave_count < 10) {
>> + interpolate_lspf(lspf, 1 - 0.125, lspf, q->prev_lspf);
>> + } else {
>> + interpolate_lspf(lspf, 1 - 0.9, lspf, q->prev_lspf);
>> + }
>> +
>> + } else if (q->rate == I_F_Q) {
>> + predictor = QCELP_LSP_OCTAVE_PREDICTOR * -
>> QCELP_LSP_SPREAD_FACTOR;
>> + if (q->erasure_count > 1) {
>> + predictor *= (q->erasure_count < 4 ? 0.9 : 0.7);
>> + }
>
>> + for (i=0; i<10; i++) {
>> + lspf[i] = (i + 1) / (float)(10 + 1) + predictor;
>
> instead of casting literal constants to float please use a . like 11.0
done
>> + }
>> +
>> + // Low-pass filter the LSP frequencies
>> + interpolate_lspf(lspf, 1 - 0.875, lspf, q->prev_lspf);
>> + } else {
>> + q->octave_count = 0;
>> +
>> + lspv=q->data+QCELP_LSPV0_POS;
>> +
>
>> + lspf[0]= qcelp_lspvq1[lspv[0]].x / 10000.0;
>> + lspf[1]=lspf[0]+qcelp_lspvq1[lspv[0]].y / 10000.0;
>> + lspf[2]=lspf[1]+qcelp_lspvq2[lspv[1]].x / 10000.0;
>> + lspf[3]=lspf[2]+qcelp_lspvq2[lspv[1]].y / 10000.0;
>> + lspf[4]=lspf[3]+qcelp_lspvq3[lspv[2]].x / 10000.0;
>> + lspf[5]=lspf[4]+qcelp_lspvq3[lspv[2]].y / 10000.0;
>> + lspf[6]=lspf[5]+qcelp_lspvq4[lspv[3]].x / 10000.0;
>> + lspf[7]=lspf[6]+qcelp_lspvq4[lspv[3]].y / 10000.0;
>> + lspf[8]=lspf[7]+qcelp_lspvq5[lspv[4]].x / 10000.0;
>> + lspf[9]=lspf[8]+qcelp_lspvq5[lspv[4]].y / 10000.0;
>
> this looks like it should be a loop
done
>
> [...]
>> +/**
>> + * Converts codebook transmission codes to GAIN and INDEX.
>> + *
>> + * TIA/EIA/IS-733 2.4.6.2
>> + */
>> +static int decode_gain_and_index(QCELPContext *q, float *gain,
>> int *index) {
>> + int i, g1[16];
>> + const uint8_t *cbgain, *cbsign, *cindex;
>> + float ga[16], gain_memory;
>> +
>> + cbsign=q->data+QCELP_CBSIGN0_POS;
>> + cbgain=q->data+QCELP_CBGAIN0_POS;
>> + cindex=q->data+QCELP_CINDEX0_POS;
>> +
>> + switch (q->rate) {
>> + case RATE_FULL:
>> + case RATE_HALF:
>> + for (i=0; i<16; i++) {
>> + if (q->rate == RATE_HALF && i>=4) break;
>> +
>> + g1[i]=4*cbgain[i];
>> + if (q->rate == RATE_FULL && i > 0 && !((i+1) & 3)) {
>> + g1[i] += av_clip((g1[i-1] + g1[i-2] +
>> g1[i-3]) / 3, 6, 38) - 6;
>> + if (g1[i] > 60)
>> + g1[i] = 60;
>> + }
>> +
>> + gain[i]=qcelp_g12ga[g1[i]];
>> +
>> + if (cbsign[i]) {
>> + gain[i] = -gain[i];
>> + index[i]= (cindex[i]-89) & 127;
>> + } else {
>> + index[i] = cindex[i];
>> + }
>> + }
>> +
>> + q->prev_g1[0] = g1[i-2];
>> + q->prev_g1[1] = g1[i-1];
>> + q->last_codebook_gain=gain[i-1];
>> +
>> + break;
>> + case RATE_QUARTER:
>> + for (i=0; i<5; i++) {
>> + g1[i]=4*cbgain[i];
>> +
>
>> + if (i>0 && FFABS(g1[i] - g1[i-1]) > 40) return -1;
>> + if (i >= 2 && FFABS(g1[i] - 2*g1[i-1] + g1[i-2]) >
>> 48) return -1;
>
> inconsistent formating
done
>
>> + ga[i]=qcelp_g12ga[g1[i]];
>> + }
>> +
>> + q->prev_g1[0] = g1[3];
>
> so is the whitespace surrounding the =
done, everywhere
>
>
>
>> + q->prev_g1[1] = g1[4];
>> + q->last_codebook_gain=ga[4];
>> +
>> + // Provide smoothing of the energy of the unvoiced
>> excitation
>> + gain[0]= ga[0];
>> + gain[1]=0.6*ga[0]+0.4*ga[1];
>> + gain[2]= ga[1];
>> + gain[3]=0.2*ga[1]+0.8*ga[2];
>> + gain[4]=0.8*ga[2]+0.2*ga[3];
>> + gain[5]= ga[3];
>> + gain[7]=0.4*ga[3]+0.6*ga[4];
>> + gain[7]= ga[4];
>> + break;
>> + case RATE_OCTAVE:
>> + g1[0] = -4 + 2 * cbgain[0]
>> + + av_clip((q->prev_g1[0] + q->prev_g1[1]) / 2,
>> 4, 58);
>> +
>> + ga[0]=qcelp_g12ga[g1[0]];
>> + gain_memory=FFABS(q->last_codebook_gain);
>> +
>> + q->last_codebook_gain =
>> + gain[7] =
>
>> + ga[0] = 0.5*gain_memory + 0.5*ga[0];
>
> 0.5*(A+B)
done
>> +
>> + // This interpolation is done to produce smoother
>> background noise.
>> + for (i = 0; i < 7; i++)
>> + gain[i]=(0.875-0.125*i)*gain_memory
>> +(0.125+0.125*i)*ga[0];
>
> for (i = 1; i < 8; i++)
> gain[i-1] = gain_memory + 0.125*i*(ga[0] - gain_memory);
>
done
>
>> +
>> + q->prev_g1[0] = q->prev_g1[1];
>> + q->prev_g1[1] = g1[0];
>> + break;
>> + case I_F_Q:
>> + g1[0] = q->prev_g1[1];
>> + switch (q->erasure_count) {
>> + case 1 : break;
>> + case 2 : g1[0] -= 1; break;
>> + case 3 : g1[0] -= 2; break;
>> + default: g1[0] -= 6;
>> + }
>> + gain[0] = qcelp_g12ga[g1[0] < 0 ? g1[0] : 0];
>> +
>
>> + gain_memory=FFABS(q->last_codebook_gain);
>> + q->last_codebook_gain =
>> + gain[3] =
>> + ga[0] = 0.5*gain_memory + 0.5*gain[0];
>> +
>> + for (i = 0; i < 3; i++) {
>> + gain[i]= (0.75 - 0.25 * i) * gain_memory + (0.25 +
>> 0.25 * i) * ga[0];
>> + }
>> + q->prev_g1[0] = q->prev_g1[1];
>> + q->prev_g1[1] = g1[0];
>
> this code looks rather similar and likely can be factorized
done
>
>> + break;
>> + }
>> + return 0;
>> +}
>> +
>> +/**
>> + * Computes the scaled codebook vector Cdn From INDEX and GAIN
>> + * For all rates.
>> + *
>> + * The specification misses some information here.
>> + *
>> + * TIA/EIA/IS-733 has an omission on the codebook index
>> determination
>> + * formula for RATE_FULL and RATE_HALF frames at section
>> 2.4.8.1.1. It says
>> + * you have to subtract the decoded index parameter from the given
>> scaled
>> + * codebook vector index 'n' to get the desired circular codebook
>> index, but
>> + * it does not mention that you have to clamp 'n' to [0-9] in
>> order to get
>> + * RI-compliant results.
>> + *
>> + * The reason for this mistake seems to be the fact they forget to
>> mention you
>> + * have to do these calculations per codebook subframe and adjust
>> given
>> + * equation values accordingly.
>> + *
>> + * @param q the context
>> + * @param gain array holding the 4 pitch subframe gain values
>> + * @param index array holding the 4 pitch subframe index values
>> + * other than RATE_FULL or RATE_HALF
>> + * @param cnd_vector array for the generated scaled codebook vector
>> + */
>> +static void compute_svector(const QCELPContext *q, const float
>> *gain,
>> + const int *index, float *cdn_vector) {
>> + int i,j;
>> + uint16_t cbseed;
>> + float rnd[160];
>> +
>> + switch (q->rate) {
>> + case RATE_FULL:
>> +
>> + for (i=0; i<16; i++) {
>> + for (j=0; j<10; j++) {
>> + cdn_vector[10*i+j]=
>> gain[i]*QCELP_FULLRATE_CODEBOOK((j-index[i]) & 127);
>> + }
>> + }
>> + break;
>> + case RATE_HALF:
>> +
>> + for (i=0; i<4; i++) {
>> + for (j=0; j<40; j++) {
>> + cdn_vector[40*i+j]=
>> gain[i]*QCELP_HALFRATE_CODEBOOK((j-index[i]) & 127);
>> + }
>> + }
>> + break;
>> + case RATE_QUARTER:
>> + cbseed=(0x0003 & q->data[QCELP_LSPV0_POS + 4])<<14 |
>> + (0x003F & q->data[QCELP_LSPV0_POS + 3])<< 8 |
>> + (0x0060 & q->data[QCELP_LSPV0_POS + 2])<< 1 |
>> + (0x0007 & q->data[QCELP_LSPV0_POS + 1])<< 3 |
>> + (0x0038 & q->data[QCELP_LSPV0_POS + 0])>> 3 ;
>> + for (i=0; i<160; i++) {
>
>> + cbseed=(521*cbseed+259) & 65535;
>
> the & is unneeded
done in 2 places
>> + rnd[i] = QCELP_SQRT1887 / 32768.0 * (((cbseed +
>> 32768) & 65535) - 32768);
>
> QCELP_SQRT1887 / 32768.0 + (int16_t)cbseed;
done in 2 places
> [...]
>> +/**
>> + * Apply generic gain control, filtered by a first order IIR filter
>> + * for the final stage gain control.
>> + *
>> + * @param q if not null, apply harcoded coef infinite impulse
>> response filter
>> + * @param in vector to control gain off
>> + * @param out gain-controled output vector
>> + *
>> + * TIA/EIA/IS-733 2.4.8.3-4/5, 2.4.8.6
>> + */
>> +static void apply_gain_ctrl(QCELPContext *q, const float *in,
>> float *out) {
>> + int i;
>> + float scalefactors[4];
>> +
>> + for (i = 0; i < 4; i++)
>> + scalefactors[i] = sqrt(compute_subframe_energy(in , i) /
>> + compute_subframe_energy(out, i));
>> +
>
>> + if (q) {
>> + scalefactors[0]=0.9375*q->prev_iirf_scalefactor +
>> 0.0625*scalefactors[0];
>> +
>> + for (i=1;i<4;i++)
>> +
>> scalefactors[i]=0.9375*scalefactors[i-1]+0.0625*scalefactors[i];
>> + q->prev_iirf_scalefactor=scalefactors[3];
>> + }
>
> q is always NULL
removed, the code is a part of the postfilter
More information about the ffmpeg-devel
mailing list