patch by Kenan Gillet, kenan.gillet gmail com Originally committed as revision 15978 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -141,6 +141,7 @@ version <next> | |||
| - Speex decoding via libspeex | |||
| - Electronic Arts TGQ decoder | |||
| - RV40 decoder | |||
| - QCELP / PureVoice decoder | |||
| version 0.4.9-pre1: | |||
| @@ -397,6 +397,7 @@ following image formats are supported: | |||
| @item Musepack @tab @tab X | |||
| @tab SV7 and SV8 are supported. | |||
| @item Nellymoser ASAO @tab X @tab X | |||
| @item QCELP / PureVoice @tab @tab X | |||
| @item Qdesign QDM2 @tab @tab X | |||
| @tab There are still some distortions. | |||
| @item QT IMA ADPCM @tab X @tab X | |||
| @@ -158,6 +158,7 @@ OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o | |||
| OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o | |||
| OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o pnm.o | |||
| OBJS-$(CONFIG_PTX_DECODER) += ptx.o | |||
| OBJS-$(CONFIG_QCELP_DECODER) += qcelpdec.o qcelp_lsp.o celp_math.o celp_filters.o | |||
| OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o | |||
| OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o | |||
| OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o | |||
| @@ -204,6 +204,7 @@ void avcodec_register_all(void) | |||
| REGISTER_DECODER (MPC7, mpc7); | |||
| REGISTER_DECODER (MPC8, mpc8); | |||
| REGISTER_ENCDEC (NELLYMOSER, nellymoser); | |||
| REGISTER_DECODER (QCELP, qcelp); | |||
| REGISTER_DECODER (QDM2, qdm2); | |||
| REGISTER_DECODER (RA_144, ra_144); | |||
| REGISTER_DECODER (RA_288, ra_288); | |||
| @@ -30,7 +30,7 @@ | |||
| #include "libavutil/avutil.h" | |||
| #define LIBAVCODEC_VERSION_MAJOR 52 | |||
| #define LIBAVCODEC_VERSION_MINOR 5 | |||
| #define LIBAVCODEC_VERSION_MINOR 6 | |||
| #define LIBAVCODEC_VERSION_MICRO 0 | |||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | |||
| @@ -0,0 +1,100 @@ | |||
| /* | |||
| * QCELP decoder | |||
| * Copyright (c) 2007 Reynaldo H. Verdejo Pinochet | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg 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. | |||
| * | |||
| * FFmpeg 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 FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| /** | |||
| * @file qcelp_lsp.c | |||
| * QCELP decoder | |||
| * @author Reynaldo H. Verdejo Pinochet | |||
| */ | |||
| #include "libavutil/mathematics.h" | |||
| /** | |||
| * initial coefficient to perform bandwidth expansion on LPC | |||
| * | |||
| * @note: 0.9883 looks like an approximation of 253/256. | |||
| * | |||
| * TIA/EIA/IS-733 2.4.3.3.6 6 | |||
| */ | |||
| #define QCELP_BANDWITH_EXPANSION_COEFF 0.9883 | |||
| /** | |||
| * Computes the Pa / (1 + z(-1)) or Qa / (1 - z(-1)) coefficients | |||
| * needed for LSP to LPC conversion. | |||
| * We only need to calculate the 6 first elements of the polynomial. | |||
| * | |||
| * @param lspf line spectral pair frequencies | |||
| * @param f [out] polynomial input/output as a vector | |||
| * | |||
| * TIA/EIA/IS-733 2.4.3.3.5-1/2 | |||
| */ | |||
| static void lsp2polyf(const float *lspf, double *f, int lp_half_order) | |||
| { | |||
| int i, j; | |||
| f[0] = 1.0; | |||
| f[1] = -2 * cos(M_PI * lspf[0]); | |||
| lspf -= 2; | |||
| for(i=2; i<=lp_half_order; i++) | |||
| { | |||
| double val = -2 * cos(M_PI * lspf[2*i]); | |||
| f[i] = val * f[i-1] + 2*f[i-2]; | |||
| for(j=i-1; j>1; j--) | |||
| f[j] += f[j-1] * val + f[j-2]; | |||
| f[1] += val; | |||
| } | |||
| } | |||
| /** | |||
| * Reconstructs LPC coefficients from the line spectral pair frequencies | |||
| * and performs bandwidth expansion. | |||
| * | |||
| * @param lspf line spectral pair frequencies | |||
| * @param lpc linear predictive coding coefficients | |||
| * | |||
| * @note: bandwith_expansion_coeff could be precalculated into a table | |||
| * but it seems to be slower on x86 | |||
| * | |||
| * TIA/EIA/IS-733 2.4.3.3.5 | |||
| */ | |||
| void ff_qcelp_lspf2lpc(const float *lspf, float *lpc) | |||
| { | |||
| double pa[6], qa[6]; | |||
| int i; | |||
| double bandwith_expansion_coeff = -QCELP_BANDWITH_EXPANSION_COEFF * 0.5; | |||
| lsp2polyf(lspf, pa, 5); | |||
| lsp2polyf(lspf + 1, qa, 5); | |||
| for (i=4; i>=0; i--) | |||
| { | |||
| double paf = pa[i+1] + pa[i]; | |||
| double qaf = qa[i+1] - qa[i]; | |||
| lpc[i ] = paf + qaf; | |||
| lpc[9-i] = paf - qaf; | |||
| } | |||
| for (i=0; i<10; i++) | |||
| { | |||
| lpc[i] *= bandwith_expansion_coeff; | |||
| bandwith_expansion_coeff *= QCELP_BANDWITH_EXPANSION_COEFF; | |||
| } | |||
| } | |||
| @@ -65,8 +65,8 @@ typedef struct { | |||
| float last_codebook_gain; | |||
| int prev_g1[2]; | |||
| int prev_bitrate; | |||
| float prev_pitch_gain[4]; | |||
| uint8_t prev_pitch_lag[4]; | |||
| float pitch_gain[4]; | |||
| uint8_t pitch_lag[4]; | |||
| uint16_t first16bits; | |||
| } QCELPContext; | |||
| @@ -75,7 +75,7 @@ typedef struct { | |||
| * | |||
| * TIA/EIA/IS-733 2.4.3.3.5 | |||
| */ | |||
| void qcelp_lspf2lpc(const float *lspf, float *lpc); | |||
| void ff_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, | |||
| @@ -494,6 +494,58 @@ static const float *do_pitchfilter(float memory[303], const float v_in[160], | |||
| return memory + 143; | |||
| } | |||
| /** | |||
| * 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; | |||
| 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++) { | |||
| q->pitch_gain[i] = q->frame.plag[i] ? (q->frame.pgain[i] + 1) * 0.25 : 0.0; | |||
| q->pitch_lag[i] = q->frame.plag[i] + 16; | |||
| } | |||
| } else { | |||
| float max_pitch_gain = q->erasure_count < 3 ? 0.9 - 0.3 * (q->erasure_count - 1) | |||
| : 0.0; | |||
| for (i = 0; i < 4; i++) | |||
| q->pitch_gain[i] = FFMIN(q->pitch_gain[i], max_pitch_gain); | |||
| memset(q->frame.pfrac, 0, sizeof(q->frame.pfrac)); | |||
| } | |||
| // pitch synthesis filter | |||
| v_synthesis_filtered = do_pitchfilter(q->pitch_synthesis_filter_mem, cdn_vector, | |||
| q->pitch_gain, q->pitch_lag, q->frame.pfrac); | |||
| // pitch prefilter update | |||
| for (i = 0; i < 4; i++) | |||
| q->pitch_gain[i] = 0.5 * FFMIN(q->pitch_gain[i], 1.0); | |||
| v_pre_filtered = do_pitchfilter(q->pitch_pre_filter_mem, v_synthesis_filtered, | |||
| q->pitch_gain, q->pitch_lag, q->frame.pfrac); | |||
| apply_gain_ctrl(cdn_vector, v_synthesis_filtered, v_pre_filtered); | |||
| } 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->pitch_gain, 0, sizeof(q->pitch_gain)); | |||
| memset(q->pitch_lag, 0, sizeof(q->pitch_lag)); | |||
| } | |||
| } | |||
| /** | |||
| * Interpolates LSP frequencies and computes LPC coefficients | |||
| * for a given bitrate & pitch subframe. | |||
| @@ -522,9 +574,9 @@ void interpolate_lpc(QCELPContext *q, const float *curr_lspf, float *lpc, | |||
| { | |||
| weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf, | |||
| weight, 1.0 - weight, 10); | |||
| qcelp_lspf2lpc(interpolated_lspf, lpc); | |||
| ff_qcelp_lspf2lpc(interpolated_lspf, lpc); | |||
| }else if(q->bitrate >= RATE_QUARTER || (q->bitrate == I_F_Q && !subframe_num)) | |||
| qcelp_lspf2lpc(curr_lspf, lpc); | |||
| ff_qcelp_lspf2lpc(curr_lspf, lpc); | |||
| } | |||
| static int buf_size2bitrate(const int buf_size) | |||
| @@ -988,7 +988,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| #endif | |||
| /* no ifdef since parameters are always those */ | |||
| case CODEC_ID_QCELP: | |||
| st->codec->frame_size= 160; | |||
| st->codec->channels= 1; /* really needed */ | |||
| break; | |||
| case CODEC_ID_AMR_NB: | |||
| case CODEC_ID_AMR_WB: | |||
| st->codec->frame_size= sc->samples_per_frame; | |||