Commit 73b458e3 authored by Kenan Gillet's avatar Kenan Gillet Committed by Vitor Sessak

Commit last ok'ed parts of QCELP decoder and enable it.

patch by Kenan Gillet, kenan.gillet gmail com

Originally committed as revision 15978 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 2ba0cdd5
...@@ -141,6 +141,7 @@ version <next> ...@@ -141,6 +141,7 @@ version <next>
- Speex decoding via libspeex - Speex decoding via libspeex
- Electronic Arts TGQ decoder - Electronic Arts TGQ decoder
- RV40 decoder - RV40 decoder
- QCELP / PureVoice decoder
version 0.4.9-pre1: version 0.4.9-pre1:
......
...@@ -397,6 +397,7 @@ following image formats are supported: ...@@ -397,6 +397,7 @@ following image formats are supported:
@item Musepack @tab @tab X @item Musepack @tab @tab X
@tab SV7 and SV8 are supported. @tab SV7 and SV8 are supported.
@item Nellymoser ASAO @tab X @tab X @item Nellymoser ASAO @tab X @tab X
@item QCELP / PureVoice @tab @tab X
@item Qdesign QDM2 @tab @tab X @item Qdesign QDM2 @tab @tab X
@tab There are still some distortions. @tab There are still some distortions.
@item QT IMA ADPCM @tab X @tab X @item QT IMA ADPCM @tab X @tab X
......
...@@ -158,6 +158,7 @@ OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o ...@@ -158,6 +158,7 @@ OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o
OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o
OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o pnm.o OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o pnm.o
OBJS-$(CONFIG_PTX_DECODER) += ptx.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_QDM2_DECODER) += qdm2.o mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o
OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o
OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o
......
...@@ -204,6 +204,7 @@ void avcodec_register_all(void) ...@@ -204,6 +204,7 @@ void avcodec_register_all(void)
REGISTER_DECODER (MPC7, mpc7); REGISTER_DECODER (MPC7, mpc7);
REGISTER_DECODER (MPC8, mpc8); REGISTER_DECODER (MPC8, mpc8);
REGISTER_ENCDEC (NELLYMOSER, nellymoser); REGISTER_ENCDEC (NELLYMOSER, nellymoser);
REGISTER_DECODER (QCELP, qcelp);
REGISTER_DECODER (QDM2, qdm2); REGISTER_DECODER (QDM2, qdm2);
REGISTER_DECODER (RA_144, ra_144); REGISTER_DECODER (RA_144, ra_144);
REGISTER_DECODER (RA_288, ra_288); REGISTER_DECODER (RA_288, ra_288);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#define LIBAVCODEC_VERSION_MAJOR 52 #define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 5 #define LIBAVCODEC_VERSION_MINOR 6
#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
......
/*
* 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 { ...@@ -65,8 +65,8 @@ typedef struct {
float last_codebook_gain; float last_codebook_gain;
int prev_g1[2]; int prev_g1[2];
int prev_bitrate; int prev_bitrate;
float prev_pitch_gain[4]; float pitch_gain[4];
uint8_t prev_pitch_lag[4]; uint8_t pitch_lag[4];
uint16_t first16bits; uint16_t first16bits;
} QCELPContext; } QCELPContext;
...@@ -75,7 +75,7 @@ typedef struct { ...@@ -75,7 +75,7 @@ typedef struct {
* *
* TIA/EIA/IS-733 2.4.3.3.5 * 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, static void weighted_vector_sumf(float *out, const float *in_a,
const float *in_b, float weight_coeff_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], ...@@ -494,6 +494,58 @@ static const float *do_pitchfilter(float memory[303], const float v_in[160],
return memory + 143; 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 * Interpolates LSP frequencies and computes LPC coefficients
* for a given bitrate & pitch subframe. * for a given bitrate & pitch subframe.
...@@ -522,9 +574,9 @@ void interpolate_lpc(QCELPContext *q, const float *curr_lspf, float *lpc, ...@@ -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, weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf,
weight, 1.0 - weight, 10); 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)) }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) 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) ...@@ -988,7 +988,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
#endif #endif
/* no ifdef since parameters are always those */ /* no ifdef since parameters are always those */
case CODEC_ID_QCELP: case CODEC_ID_QCELP:
st->codec->frame_size= 160;
st->codec->channels= 1; /* really needed */ st->codec->channels= 1; /* really needed */
break;
case CODEC_ID_AMR_NB: case CODEC_ID_AMR_NB:
case CODEC_ID_AMR_WB: case CODEC_ID_AMR_WB:
st->codec->frame_size= sc->samples_per_frame; st->codec->frame_size= sc->samples_per_frame;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment