[FFmpeg-soc] [soc]: r2914 - aacenc/aacpsy.c

kostya subversion at mplayerhq.hu
Wed Jul 30 13:50:16 CEST 2008


Author: kostya
Date: Wed Jul 30 13:50:16 2008
New Revision: 2914

Log:
Blockswitching for 3gpp psy model

Modified:
   aacenc/aacpsy.c

Modified: aacenc/aacpsy.c
==============================================================================
--- aacenc/aacpsy.c	(original)
+++ aacenc/aacpsy.c	Wed Jul 30 13:50:16 2008
@@ -332,6 +332,11 @@ typedef struct Psy3gppChannel{
     float       thr[2];
     Psy3gppBand band[2][128];
     Psy3gppBand prev_band[2][128];
+
+    float       win_nrg[2];
+    float       iir_state[2][2];
+    uint8_t     next_grouping[2];
+    enum WindowSequence next_window_seq[2];
 }Psy3gppChannel;
 
 /**
@@ -430,6 +435,26 @@ static av_cold int psy_3gpp_init(AACPsyC
 }
 
 /**
+ * IIR filter used in block switching decision
+ */
+static float iir_filter(int in, float state[2])
+{
+    float ret;
+
+    ret = 0.7548f * (in - state[0]) + 0.5095f * state[1];
+    state[0] = in;
+    state[1] = ret;
+    return ret;
+}
+
+/**
+ * window grouping information stored as bits (0 - new group, 1 - group continues)
+ */
+static const uint8_t window_grouping[9] = {
+    0xB6, 0x6C, 0xD8, 0xB2, 0x66, 0xC6, 0x96, 0x36, 0x36
+};
+
+/**
  * Tell encoder which window types to use.
  * @see 3GPP TS26.403 5.4.1
  */
@@ -437,17 +462,83 @@ static void psy_3gpp_window(AACPsyContex
 {
     int ch;
     int chans = FFMIN(apc->avctx->channels - channel, 2);
+    int i, j;
+    int br = apc->avctx->bit_rate / apc->avctx->channels;
+    int attack_ratio = (br <= 16000 + 8000*chans) ? 18 : 10;
+    Psy3gppContext *pctx = (Psy3gppContext*) apc->model_priv_data;
+    Psy3gppChannel *pch = &pctx->ch;
+    uint8_t grouping[2];
+    enum WindowSequence win[2];
+
+    if(la){
+        float s[8], v;
+        for(ch = 0; ch < chans; ch++){
+            enum WindowSequence last_window_sequence = cpe->ch[ch].ics.window_sequence;
+            int switch_to_eight = 0;
+            float sum = 0.0, sum2 = 0.0;
+            int attack_n = 0;
+            for(i = 0; i < 8; i++){
+                for(j = 0; j < 128; j++){
+                    v = iir_filter(audio[(i*128+j)*apc->avctx->channels+ch], pch->iir_state[ch]);
+                    sum += v*v;
+                }
+                s[i] = sum;
+                sum2 += sum;
+            }
+            for(i = 0; i < 8; i++){
+                if(s[i] > pch->win_nrg[ch] * attack_ratio){
+                    attack_n = i + 1;
+                    switch_to_eight = 1;
+                    break;
+                }
+            }
+            pch->win_nrg[ch] = pch->win_nrg[ch]*7/8 + sum2/64;
+
+            switch(last_window_sequence){
+            case ONLY_LONG_SEQUENCE:
+                win[ch] = switch_to_eight ? LONG_START_SEQUENCE : ONLY_LONG_SEQUENCE;
+                grouping[ch] = 0;
+                break;
+            case LONG_START_SEQUENCE:
+                win[ch] = EIGHT_SHORT_SEQUENCE;
+                grouping[ch] = pch->next_grouping[ch];
+                break;
+            case LONG_STOP_SEQUENCE:
+                win[ch] = ONLY_LONG_SEQUENCE;
+                grouping[ch] = 0;
+                break;
+            case EIGHT_SHORT_SEQUENCE:
+                win[ch] = switch_to_eight ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE;
+                grouping[ch] = switch_to_eight ? pch->next_grouping[ch] : 0;
+                break;
+            }
+            pch->next_grouping[ch] = window_grouping[attack_n];
+        }
+    }else{
+        for(ch = 0; ch < chans; ch++){
+            win[ch] = (cpe->ch[ch].ics.window_sequence == EIGHT_SHORT_SEQUENCE) ? EIGHT_SHORT_SEQUENCE : ONLY_LONG_SEQUENCE;
+            grouping[ch] = (cpe->ch[ch].ics.window_sequence == EIGHT_SHORT_SEQUENCE) ? window_grouping[0] : 0;
+        }
+    }
 
-//XXX: stub, because encoder does not support long to short window transition yet :(
     for(ch = 0; ch < chans; ch++){
-        cpe->ch[ch].ics.window_sequence = ONLY_LONG_SEQUENCE;
+        cpe->ch[ch].ics.window_sequence = win[ch];
         cpe->ch[ch].ics.use_kb_window[0] = 1;
-        cpe->ch[ch].ics.num_windows = 1;
-        cpe->ch[ch].ics.swb_sizes = apc->bands1024;
-        cpe->ch[ch].ics.num_swb = apc->num_bands1024;
-        cpe->ch[ch].ics.group_len[0] = 0;
+        if(win[ch] != EIGHT_SHORT_SEQUENCE){
+            cpe->ch[ch].ics.num_windows = 1;
+            cpe->ch[ch].ics.swb_sizes = apc->bands1024;
+            cpe->ch[ch].ics.num_swb = apc->num_bands1024;
+        }else{
+            cpe->ch[ch].ics.num_windows = 8;
+            cpe->ch[ch].ics.swb_sizes = apc->bands128;
+            cpe->ch[ch].ics.num_swb = apc->num_bands128;
+        }
+        for(i = 0; i < 8; i++)
+            cpe->ch[ch].ics.group_len[i] = (grouping[ch] >> i) & 1;
     }
-    cpe->common_window = cpe->ch[0].ics.use_kb_window[0] == cpe->ch[1].ics.use_kb_window[0];
+    cpe->common_window = chans > 1 && cpe->ch[0].ics.window_sequence == cpe->ch[1].ics.window_sequence && cpe->ch[0].ics.use_kb_window[0] == cpe->ch[1].ics.use_kb_window[0];
+    if(cpe->common_window && cpe->ch[0].ics.window_sequence == EIGHT_SHORT_SEQUENCE && grouping[0] != grouping[1])
+        cpe->common_window = 0;
 }
 
 /**
@@ -489,7 +580,7 @@ static void calc_pe(Psy3gppBand *band, i
 static void psy_3gpp_process(AACPsyContext *apc, int channel, ChannelElement *cpe)
 {
     int start;
-    int ch, w, g, g2, i;
+    int ch, w, w2, g, g2, i;
     int prev_scale;
     Psy3gppContext *pctx = (Psy3gppContext*) apc->model_priv_data;
     float stereo_att, pe_target;
@@ -674,6 +765,24 @@ static void psy_3gpp_process(AACPsyConte
                 if(!cpe->ch[ch].gain) cpe->ch[ch].gain = cpe->ch[ch].sf_idx[w][g];
             }
         }
+        //adjust scalefactors for window groups
+        for(w = 0; w < cpe->ch[ch].ics.num_windows - 1; w++){
+            int min_scale = 256;
+
+            if(cpe->ch[ch].ics.group_len[w]) continue;
+            w2 = w;
+            do{
+                w2++;
+            }while(w2 < cpe->ch[ch].ics.num_windows && cpe->ch[ch].ics.group_len[w2]);
+            for(g = 0; g < cpe->ch[ch].ics.num_swb; g++){
+                for(i = w; i < w2; i++){
+                    if(cpe->ch[ch].zeroes[i][g]) continue;
+                    min_scale = FFMIN(min_scale, cpe->ch[ch].sf_idx[i][g]);
+                }
+                for(i = w; i < w2; i++)
+                    cpe->ch[ch].sf_idx[i][g] = min_scale;
+            }
+        }
     }
 
     memcpy(pch->prev_band, pch->band, sizeof(pch->band));



More information about the FFmpeg-soc mailing list