[FFmpeg-soc] G.723.1 Encoder: Compute fixed CB excitation

Mohamed Naufal naufal11 at gmail.com
Fri Aug 20 09:13:20 CEST 2010


---
 libavcodec/g723_1.c      |  224 ++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/g723_1_data.h |   12 +++
 2 files changed, 236 insertions(+), 0 deletions(-)

diff --git a/libavcodec/g723_1.c b/libavcodec/g723_1.c
index fa57527..d344217 100755
--- a/libavcodec/g723_1.c
+++ b/libavcodec/g723_1.c
@@ -1793,6 +1793,228 @@ static void sub_acb_contrib(int16_t *residual,
int16_t *impulse_resp,
     }
 }

+/**
+ * Quantize the residual signal using the fixed codebook (MP-MLQ).
+ *
+ * @param optim optimized fixed codebook parameters
+ * @param buf   excitation vector
+ */
+static void get_fcb_param(FCBParam *optim, int16_t *impulse_resp,
+                          int16_t *buf, int pulse_cnt, int pitch_lag)
+{
+    FCBParam param;
+    int16_t impulse_r[SUBFRAME_LEN];
+    int16_t temp_corr[SUBFRAME_LEN];
+    int16_t impulse_corr[SUBFRAME_LEN];
+
+    int ccr1[SUBFRAME_LEN];
+    int ccr2[SUBFRAME_LEN];
+    int amp, err, max, max_amp_index, min, scale, i, j, k, l;
+
+    int64_t temp;
+
+    /* Update impulse response */
+    memcpy(impulse_r, impulse_resp, sizeof(int16_t) * SUBFRAME_LEN);
+    param.dirac_train = 0;
+    if (pitch_lag < SUBFRAME_LEN - 2) {
+        param.dirac_train = 1;
+        gen_dirac_train(impulse_r, pitch_lag);
+    }
+
+    for (i = 0; i < SUBFRAME_LEN; i++)
+        temp_corr[i] = impulse_r[i] >> 1;
+
+    /* Compute impulse response autocorrelation */
+    temp = dot_product(temp_corr, temp_corr, SUBFRAME_LEN, 1);
+
+    scale = normalize_bits_int32(temp);
+    impulse_corr[0] = av_clipl_int32((temp << scale) + (1 << 15)) >> 16;
+
+    for (i = 1; i < SUBFRAME_LEN; i++) {
+        temp = dot_product(temp_corr + i, temp_corr, SUBFRAME_LEN - i, 1);
+        impulse_corr[i] = av_clipl_int32((temp << scale) + (1 << 15)) >> 16;
+    }
+
+    /* Compute crosscorrelation of impulse response with residual signal */
+    scale -= 4;
+    for (i = 0; i < SUBFRAME_LEN; i++){
+        temp = dot_product(buf + i, impulse_r, SUBFRAME_LEN - i, 1);
+        if (scale < 0)
+            ccr1[i] = temp >> -scale;
+        else
+            ccr1[i] = av_clipl_int32(temp << scale);
+    }
+
+    /* Search loop */
+    for (i = 0; i < GRID_SIZE; i++) {
+        /* Maximize the crosscorrelation */
+        max = 0;
+        for (j = i; j < SUBFRAME_LEN; j += GRID_SIZE) {
+            temp = FFABS(ccr1[j]);
+            if (temp >= max) {
+                max = temp;
+                param.pulse_pos[0] = j;
+            }
+        }
+
+        /* Quantize the gain (max crosscorrelation/impulse_corr[0]) */
+        amp = max;
+        min = 1 << 30;
+        max_amp_index = GAIN_LEVELS - 2;
+        for (j = max_amp_index; j >= 2; j--) {
+            temp = av_clipl_int32((int64_t)fixed_cb_gain[j] *
+                                  impulse_corr[0] << 1);
+            temp = FFABS(temp - amp);
+            if (temp < min) {
+                min = temp;
+                max_amp_index = j;
+            }
+        }
+
+        max_amp_index--;
+        /* Select additional gain values */
+        for (j = 1; j < 5; j++) {
+            for (k = i; k < SUBFRAME_LEN; k += GRID_SIZE) {
+                temp_corr[k] = 0;
+                ccr2[k]      = ccr1[k];
+            }
+            param.amp_index = max_amp_index + j - 2;
+            amp = fixed_cb_gain[param.amp_index];
+
+            param.pulse_sign[0] = (ccr2[param.pulse_pos[0]] < 0) ? -amp : amp;
+
+            temp_corr[param.pulse_pos[0]] = 1;
+
+            for (k = 1; k < pulse_cnt; k++) {
+                max = -1 << 30;
+                for (l = i; l < SUBFRAME_LEN; l += GRID_SIZE) {
+                    if (temp_corr[l])
+                        continue;
+                    temp = impulse_corr[FFABS(l - param.pulse_pos[k - 1])];
+                    temp = av_clipl_int32((int64_t)temp *
+                                          param.pulse_sign[k - 1] << 1);
+                    ccr2[l] -= temp;
+                    temp = FFABS(ccr2[l]);
+
+                    if (temp > max) {
+                        max = temp;
+                        param.pulse_pos[k] = l;
+                    }
+                }
+
+                param.pulse_sign[k] = (ccr2[param.pulse_pos[k]] < 0) ?
+                                      -amp : amp;
+                temp_corr[param.pulse_pos[k]] = 1;
+            }
+
+            /* Create the error vector */
+            memset(temp_corr, 0, sizeof(int16_t) * SUBFRAME_LEN);
+
+            for (k = 0; k < pulse_cnt; k++)
+                temp_corr[param.pulse_pos[k]] = param.pulse_sign[k];
+
+            for (k = SUBFRAME_LEN - 1; k >= 0; k--) {
+                temp = 0;
+                for (l = 0; l <= k; l++) {
+                    int prod = av_clipl_int32((int64_t)temp_corr[l] *
+                                              impulse_r[k - l] << 1);
+                    temp     = av_clipl_int32(temp + prod);
+                }
+                temp_corr[k] = temp << 2 >> 16;
+            }
+
+            /* Compute square of error */
+            err = 0;
+            for (k = 0; k < SUBFRAME_LEN; k++) {
+                int64_t prod;
+                prod = av_clipl_int32((int64_t)buf[k] * temp_corr[k] << 1);
+                err  = av_clipl_int32(err - prod);
+                prod = av_clipl_int32((int64_t)temp_corr[k] * temp_corr[k]);
+                err  = av_clipl_int32(err + prod);
+            }
+
+            /* Minimize */
+            if (err < optim->min_err) {
+                optim->min_err     = err;
+                optim->grid_index  = i;
+                optim->amp_index   = param.amp_index;
+                optim->dirac_train = param.dirac_train;
+
+                for (k = 0; k < pulse_cnt; k++) {
+                    optim->pulse_sign[k] = param.pulse_sign[k];
+                    optim->pulse_pos[k]  = param.pulse_pos[k];
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Combinatorially encode the pulse position and gain of the
+ * current subframe.
+ *
+ * @param optim optimized fixed codebook parameters
+ * @param buf   excitation vector
+ */
+static void pack_fcb_param(G723_1_Subframe *subfrm, FCBParam *optim,
+                           int16_t *buf, int pulse_cnt)
+{
+    int i, j;
+
+    j = PULSE_MAX - pulse_cnt;
+
+    subfrm->pulse_sign = 0;
+    subfrm->pulse_pos  = 0;
+
+    for (i = 0; i < SUBFRAME_LEN >> 1; i++) {
+        int val = buf[optim->grid_index + (i << 1)];
+        if (!val) {
+            subfrm->pulse_pos += combinatorial_table[j][i];
+        } else {
+            subfrm->pulse_sign <<= 1;
+            if (val < 0) subfrm->pulse_sign++;
+            j++;
+
+            if (j == PULSE_MAX) break;
+        }
+    }
+    subfrm->amp_index   = optim->amp_index;
+    subfrm->grid_index  = optim->grid_index;
+    subfrm->dirac_train = optim->dirac_train;
+}
+
+/**
+ * Compute the fixed codebook excitation.
+ *
+ * @param buf          target vector
+ * @param impulse_resp impulse response of the combined filter
+ */
+static void fcb_search(G723_1_Context *p, int16_t *impulse_resp,
+                       int16_t *buf, int index)
+{
+    FCBParam optim;
+    int pulse_cnt = pulses[index];
+    int i;
+
+    optim.min_err = 1 << 30;
+    get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, SUBFRAME_LEN);
+
+    if (p->pitch_lag[index >> 1] < SUBFRAME_LEN - 2) {
+        get_fcb_param(&optim, impulse_resp, buf, pulse_cnt,
+                      p->pitch_lag[index >> 1]);
+    }
+
+    /* Reconstruct the excitation */
+    memset(buf, 0, sizeof(int16_t) * SUBFRAME_LEN);
+    for (i = 0; i < pulse_cnt; i++)
+        buf[optim.pulse_pos[i]] = optim.pulse_sign[i];
+
+    pack_fcb_param(&p->subframe[index], &optim, buf, pulse_cnt);
+
+    if (optim.dirac_train)
+        gen_dirac_train(buf, p->pitch_lag[index >> 1]);
+}
+
 static int g723_1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
                                int buf_size, void *data)
 {
@@ -1881,6 +2103,8 @@ static int g723_1_encode_frame(AVCodecContext
*avctx, unsigned char *buf,
                            p->subframe[i], p->cur_rate);
         sub_acb_contrib(residual, impulse_resp, in);

+        fcb_search(p, impulse_resp, in, i);
+
         offset += LPC_ORDER;
         in += SUBFRAME_LEN;
     }
diff --git a/libavcodec/g723_1_data.h b/libavcodec/g723_1_data.h
index ea1a86d..199185d 100644
--- a/libavcodec/g723_1_data.h
+++ b/libavcodec/g723_1_data.h
@@ -90,6 +90,18 @@ typedef struct {
 } HFParam;

 /**
+ * Optimized fixed codebook excitation parameters
+ */
+typedef struct {
+    int min_err;
+    int amp_index;
+    int grid_index;
+    int dirac_train;
+    int pulse_pos[PULSE_MAX];
+    int pulse_sign[PULSE_MAX];
+} FCBParam;
+
+/**
  * Postfilter gain weighting factors scaled by 2^15
  */
 static const int16_t ppf_gain_weight[2] = {0x1800, 0x2000};
--


More information about the FFmpeg-soc mailing list