[FFmpeg-soc] [soc] G.723.1 Encoder: Compute LPC coefficients
Mohamed Naufal
naufal11 at gmail.com
Wed Aug 11 18:36:19 CEST 2010
---
libavcodec/g723_1.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/g723_1_data.h | 33 +++++++++++++
2 files changed, 149 insertions(+), 0 deletions(-)
diff --git a/libavcodec/g723_1.c b/libavcodec/g723_1.c
index a689497..7a0d6aa 100755
--- a/libavcodec/g723_1.c
+++ b/libavcodec/g723_1.c
@@ -57,6 +57,7 @@ typedef struct g723_1_context {
int iir_mem[LPC_ORDER];
int16_t pf_gain; ///< formant postfilter
///< gain scaling unit memory
+ int16_t prev_data[HALF_FRAME_LEN];
} G723_1_Context;
static av_cold int g723_1_decode_init(AVCodecContext *avctx)
@@ -1122,12 +1123,127 @@ static void highpass_filter(int16_t *buf,
int16_t *fir, int *iir)
}
}
+/**
+ * Estimate autocorrelation of the input vector.
+ *
+ * @param buf input buffer
+ * @param autocorr autocorrelation coefficients vector
+ */
+static void comp_autocorr(int16_t *buf, int16_t *autocorr)
+{
+ int i, scale, temp;
+ int16_t vector[LPC_FRAME];
+
+ memcpy(vector, buf, LPC_FRAME * sizeof(int16_t));
+ scale_vector(vector, LPC_FRAME);
+
+ /* Apply the Hamming window */
+ for (i = 0; i < LPC_FRAME; i++)
+ vector[i] = (vector[i] * hamming_window[i] + (1 << 14)) >> 15;
+
+ /* Compute the first autocorrelation coefficient */
+ temp = dot_product(vector, vector, LPC_FRAME, 0);
+
+ /* Apply a white noise correlation factor of (1025/1024) */
+ temp += temp >> 10;
+
+ /* Normalize */
+ scale = normalize_bits_int32(temp);
+ autocorr[0] = av_clipl_int32((int64_t)(temp << scale) +
+ (1 << 15)) >> 16;
+
+ /* Compute the remaining coefficients */
+ if (!autocorr[0]) {
+ memset(autocorr + 1, 0, LPC_ORDER * sizeof(int16_t));
+ } else {
+ for (i = 1; i <= LPC_ORDER; i++) {
+ temp = dot_product(vector, vector + i, LPC_FRAME - i, 0);
+ temp = MULL2((temp << scale), binomial_window[i - 1]);
+ autocorr[i] = av_clipl_int32((int64_t)temp + (1 << 15)) >> 16;
+ }
+ }
+}
+
+/**
+ * Use Levinson-Durbin recursion to compute LPC coefficients from
+ * autocorrelation values.
+ *
+ * @param lpc LPC coefficients vector
+ * @param autocorr autocorrelation coefficients vector
+ * @param error prediction error
+ */
+static void levinson_durbin(int16_t *lpc, int16_t *autocorr, int16_t error)
+{
+ int16_t vector[LPC_ORDER];
+ int16_t partial_corr;
+ int i, j, temp;
+
+ memset(lpc, 0, LPC_ORDER * sizeof(int16_t));
+
+ for (i = 0; i < LPC_ORDER; i++) {
+ /* Compute the partial correlation coefficient */
+ temp = 0;
+ for (j = 0; j < i; j++)
+ temp -= lpc[j] * autocorr[i - j - 1];
+ temp = ((autocorr[i] << 13) + temp) << 3;
+
+ if (FFABS(temp) >= (error << 16))
+ break;
+
+ partial_corr = temp / (error << 1);
+
+ lpc[i] = av_clipl_int32((int64_t)(partial_corr << 14) +
+ (1 << 15)) >> 16;
+
+ /* Update the prediction error */
+ temp = MULL2(temp, partial_corr);
+ error = av_clipl_int32((int64_t)(error << 16) - temp +
+ (1 << 15)) >> 16;
+
+ memcpy(vector, lpc, i * sizeof(int16_t));
+ for (j = 0; j < i; j++) {
+ temp = partial_corr * vector[i - j - 1] << 1;
+ lpc[j] = av_clipl_int32((int64_t)(lpc[j] << 16) - temp +
+ (1 << 15)) >> 16;
+ }
+ }
+}
+
+/**
+ * Calculate LPC coefficients for the current frame.
+ *
+ * @param buf current frame
+ * @param prev_data 2 trailing subframes of the previous frame
+ * @param lpc LPC coefficients vector
+ */
+static void comp_lpc_coeff(int16_t *buf, int16_t *prev_data, int16_t *lpc)
+{
+ int16_t vector[FRAME_LEN + HALF_FRAME_LEN];
+ int16_t autocorr[(LPC_ORDER + 1) * SUBFRAMES];
+ int16_t *autocorr_ptr = autocorr;
+ int16_t *lpc_ptr = lpc;
+ int i, j;
+
+ memcpy(vector, prev_data, HALF_FRAME_LEN * sizeof(int16_t));
+ memcpy(vector + HALF_FRAME_LEN, buf, FRAME_LEN * sizeof(int16_t));
+
+ for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) {
+ comp_autocorr(vector + i, autocorr_ptr);
+ levinson_durbin(lpc_ptr, autocorr_ptr + 1, autocorr_ptr[0]);
+
+ lpc_ptr += LPC_ORDER;
+ autocorr_ptr += LPC_ORDER + 1;
+ }
+}
+
static int g723_1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
int buf_size, void *data)
{
G723_1_Context *p = avctx->priv_data;
+ int16_t unq_lpc[LPC_ORDER * SUBFRAMES];
highpass_filter(data, &p->fir_mem[0], &p->iir_mem[0]);
+ comp_lpc_coeff(data, p->prev_data, unq_lpc);
return 0;
}
diff --git a/libavcodec/g723_1_data.h b/libavcodec/g723_1_data.h
index a407465..a2407bf 100644
--- a/libavcodec/g723_1_data.h
+++ b/libavcodec/g723_1_data.h
@@ -30,6 +30,8 @@
#define SUBFRAMES 4
#define FRAME_LEN 240
#define SUBFRAME_LEN (FRAME_LEN / SUBFRAMES)
+#define HALF_FRAME_LEN (FRAME_LEN / 2)
+#define LPC_FRAME (HALF_FRAME_LEN + SUBFRAME_LEN)
#define LPC_ORDER 10
#define LSP_BANDS 3
#define LSP_CB_SIZE 256
@@ -1244,3 +1246,34 @@ static const int16_t postfilter_tbl[2][LPC_ORDER] = {
/* Pole */
{24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845}
};
+
+/**
+ * Hamming window coefficients scaled by 2^15
+ */
+static const int16_t hamming_window[LPC_FRAME] = {
+ 2621, 2631, 2659, 2705, 2770, 2853, 2955, 3074, 3212, 3367,
+ 3541, 3731, 3939, 4164, 4405, 4663, 4937, 5226, 5531, 5851,
+ 6186, 6534, 6897, 7273, 7661, 8062, 8475, 8899, 9334, 9780,
+ 10235, 10699, 11172, 11653, 12141, 12636, 13138, 13645, 14157, 14673,
+ 15193, 15716, 16242, 16769, 17298, 17827, 18356, 18884, 19411, 19935,
+ 20457, 20975, 21489, 21999, 22503, 23002, 23494, 23978, 24455, 24924,
+ 25384, 25834, 26274, 26704, 27122, 27529, 27924, 28306, 28675, 29031,
+ 29373, 29700, 30012, 30310, 30592, 30857, 31107, 31340, 31557, 31756,
+ 31938, 32102, 32249, 32377, 32488, 32580, 32654, 32710, 32747, 32766,
+ 32766, 32747, 32710, 32654, 32580, 32488, 32377, 32249, 32102, 31938,
+ 31756, 31557, 31340, 31107, 30857, 30592, 30310, 30012, 29700, 29373,
+ 29031, 28675, 28306, 27924, 27529, 27122, 26704, 26274, 25834, 25384,
+ 24924, 24455, 23978, 23494, 23002, 22503, 21999, 21489, 20975, 20457,
+ 19935, 19411, 18884, 18356, 17827, 17298, 16769, 16242, 15716, 15193,
+ 14673, 14157, 13645, 13138, 12636, 12141, 11653, 11172, 10699, 10235,
+ 9780, 9334, 8899, 8475, 8062, 7661, 7273, 6897, 6534, 6186,
+ 5851, 5531, 5226, 4937, 4663, 4405, 4164, 3939, 3731, 3541,
+ 3367, 3212, 3074, 2955, 2853, 2770, 2705, 2659, 2631, 2621
+};
+
+/**
+ * Binomial window coefficients scaled by 2^15
+ */
+static const int16_t binomial_window[LPC_ORDER] = {
+ 32749, 32695, 32604, 32477, 32315, 32118, 31887, 31622, 31324, 30995
+};
--
More information about the FFmpeg-soc
mailing list