[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