ref: d378fcfb11437762dc639711322a58212caf8148
parent: 0eed37002e2fdf7a89c034efa1f4d5a397e213e2
author: menno <menno>
date: Thu Jan 27 12:25:09 EST 2000
New block switching (sounds bad for now)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-SOURCE=aac_qc.c aac_se_enc.c bitstream.c enc_tf.c encoder.c imdct.c is.c mc_enc.c ms.c psych.c pulse.c tns.c transfo.c fastfft.c nok_ltp_enc.c nok_pitch.c
+SOURCE=aac_qc.c aac_se_enc.c bitstream.c enc_tf.c encoder.c imdct.c is.c mc_enc.c ms.c psych.c pulse.c tns.c transfo.c fastfft.c nok_ltp_enc.c nok_pitch.c winswitch.c
OBJ = $(SOURCE:.c=.o)
--- a/enc_tf.c
+++ b/enc_tf.c
@@ -16,6 +16,7 @@
#include "all.h"
#include "aac_se_enc.h"
#include "nok_ltp_enc.h"
+#include "winswitch.h"
#define SQRT2 sqrt(2)
@@ -170,6 +171,8 @@
/* initialize psychoacoustic module */
EncTf_psycho_acoustic_init();
+ winSwitchInit(max_ch);
+
/* initialize spectrum processing */
/* initialize quantization and coding */
tf_init_encode_spectrum_aac(0);
@@ -336,34 +339,38 @@
* block_switch processing
*
******************************************************************************************************************************/
+ /* Window switching taken from the NTT source code in the MPEG4 VM. */
{
- int chanNum = 0;
- /* A few definitions: */
- /* block_type: Initially, the block_type used in the previous frame. */
- /* Will be set to the block_type to use this frame. */
- /* A block type will be selected to ensure a meaningful */
- /* window transition. */
- /* next_desired_block_type: Block_type (LONG or SHORT) which the psycho */
- /* model wants to use next frame. The psycho model is */
- /* using a look-ahead buffer. */
- /* desired_block_type: Block_type (LONG or SHORT) which the psycho */
- /* previously wanted to use. It is the desired block_type */
- /* for this frame. */
- if ( (block_type[chanNum]==ONLY_SHORT_WINDOW)||(block_type[chanNum]==LONG_SHORT_WINDOW) ) {
- if ( (desired_block_type==ONLY_LONG_WINDOW)&&(next_desired_block_type==ONLY_LONG_WINDOW) ) {
- block_type[chanNum]=SHORT_LONG_WINDOW;
- } else {
- block_type[chanNum]=ONLY_SHORT_WINDOW;
+ static int ntt_InitFlag = 1;
+ static double *sig_tmptmp, *sig_tmp;
+ int ismp, i_ch, top;
+ /* initialize */
+ if (ntt_InitFlag){
+ sig_tmptmp = malloc(max_ch*block_size_samples*3*sizeof(double));
+ sig_tmp = sig_tmptmp + block_size_samples * max_ch;
+ for (i_ch=0; i_ch<max_ch; i_ch++){
+ top = i_ch * block_size_samples;
+ for (ismp=0; ismp<block_size_samples; ismp++){
+ sig_tmp[ismp+top] = DTimeSigBuf[i_ch][ismp];
+ }
}
- } else if (next_desired_block_type==ONLY_SHORT_WINDOW) {
- block_type[chanNum]=LONG_SHORT_WINDOW;
- } else {
- block_type[chanNum]=ONLY_LONG_WINDOW;
}
- desired_block_type=next_desired_block_type;
+ for (i_ch=0; i_ch<max_ch; i_ch++){
+ top = i_ch * block_size_samples;
+ for (ismp=0; ismp<block_size_samples; ismp++){
+ sig_tmp[ismp+block_size_samples*max_ch+top] =
+ DTimeSigLookAheadBuf[i_ch][ismp];
+ }
+ }
+ /* automatic switching module */
+ winSwitch(sig_tmp, &block_type[0], ntt_InitFlag);
+ for (ismp=0; ismp<block_size_samples*2*max_ch; ismp++){
+ sig_tmp[ismp-block_size_samples*max_ch] = sig_tmp[ismp];
+ }
+ ntt_InitFlag = 0;
}
-// printf("%d %d\n", block_type[0], block_type[1]);
+// printf("%d\n", block_type[0]);
// block_type[0] = ONLY_LONG_WINDOW;
// block_type[1] = ONLY_LONG_WINDOW;
// block_type[0] = ONLY_SHORT_WINDOW;
--- a/faac.dsp
+++ b/faac.dsp
@@ -154,6 +154,10 @@
SOURCE=.\transfo.c
# End Source File
+# Begin Source File
+
+SOURCE=.\winswitch.c
+# End Source File
# End Group
# End Target
# End Project
--- a/faac_dll.dsp
+++ b/faac_dll.dsp
@@ -158,6 +158,10 @@
SOURCE=.\transfo.c
# End Source File
+# Begin Source File
+
+SOURCE=.\winswitch.c
+# End Source File
# End Group
# Begin Group "Resource Files"
--- /dev/null
+++ b/winswitch.c
@@ -1,0 +1,333 @@
+
+/*
+ * Window switching module
+ * Most of this has been taken from NTT source code in the MPEG-4
+ * Verification Model.
+ *
+ * TODO:
+ * - better multi-channel support
+ */
+
+#include <math.h>
+#include "tf_main.h"
+#include "winswitch.h"
+
+#define ntt_N_SUP_MAX 2
+
+int num_channel;
+
+
+int winSwitch(/* Input */
+ double sig[], /* input signal */
+ /* Output */
+ enum WINDOW_TYPE *w_type, /* code index for block type */
+ /* Control */
+ int InitFlag)/* initialization flag */
+{
+ /*--- Variables ---*/
+ int s_attack;
+ int ratio;
+
+ /*--- A.Jin 1997.10.19 ---*/
+ ratio = checkAttack(sig, &s_attack, InitFlag);
+
+ getWindowType( s_attack, w_type, InitFlag );
+ return ratio;
+}
+
+
+void getWindowType(int flag, /* Input : trigger for short block length */
+ enum WINDOW_TYPE *w_type, /* Output : code index for block type */
+ int InitFlag ) /* Control : initialization flag */
+{
+ static int w_type_pre;
+ static int flag_pre;
+
+ if ( InitFlag ){
+ flag_pre = 0;
+ w_type_pre = ONLY_LONG_WINDOW;
+ }
+
+ if (InitFlag){
+ if (flag) *w_type = ONLY_SHORT_WINDOW;
+ else *w_type = ONLY_LONG_WINDOW;
+ }
+ else{
+ switch( w_type_pre ){
+ case ONLY_LONG_WINDOW:
+ if ( flag ) *w_type = LONG_SHORT_WINDOW;
+ else *w_type = ONLY_LONG_WINDOW;
+ break;
+ case LONG_SHORT_WINDOW:
+ *w_type = ONLY_SHORT_WINDOW;
+ break;
+ case SHORT_LONG_WINDOW:
+ if ( flag ) *w_type = LONG_SHORT_WINDOW;
+ else *w_type = ONLY_LONG_WINDOW;
+ break;
+ case ONLY_SHORT_WINDOW:
+ if (flag || flag_pre) *w_type = ONLY_SHORT_WINDOW;
+ else *w_type = SHORT_LONG_WINDOW;
+ }
+ }
+ w_type_pre = *w_type;
+ flag_pre = flag;
+}
+
+
+#define ST_CHKATK (BLOCK_LEN_LONG/2+BLOCK_LEN_SHORT/2)
+
+#define N_BLK_MAX 4096
+#define N_SFT_MAX 256
+#define N_LPC_MAX 2
+
+__inline void ZeroMem(int n, double xx[])
+{
+ int i = n;
+ while(i-- != 0)
+ *(xx++) = 0.0;
+}
+
+void LagWindow(/* Output */
+ double wdw[], /* lag window data */
+ /* Input */
+ int n, /* dimension of wdw[.] */
+ double h) /* ratio of window half value band width to sampling frequency */
+{
+ int i;
+ double pi=3.14159265358979323846264338327959288419716939;
+ double a,b,w;
+ if(h<=0.0) for(i=0;i<=n;i++) wdw[i]=1.0;
+ else
+ {
+ a=log(0.5)*0.5/log(cos(0.5*pi*h));
+ a=(double)((int)a);
+ w=1.0; b=a; wdw[0]=1.0;
+ for(i=1;i<=n;i++)
+ {
+ b+=1.0; w*=a/b; wdw[i]=w; a-=1.0;
+ }
+ }
+}
+
+void HammingWindow(/* Output */
+ double wdw[], /* Hamming window data */
+ int n) /* window length */
+{
+ int i;
+ double d,pi=3.14159265358979323846264338327950288419716939;
+ if(n>0)
+ {
+ d=2.0*pi/n;
+ for(i=0;i<n;i++)
+ wdw[i]=0.54-0.46*cos(d*i);
+ }
+}
+
+__inline void ntt_cutfr(int st, /* Input --- Start point */
+ int len, /* Input --- Block length */
+ int ich, /* Input --- Channel number */
+ double frm[], /* Input --- Input frame */
+ double buf[]) /* Output --- Output data buffer */
+{
+ /*--- Variables ---*/
+ int stb, sts, edb, nblk, iblk, ibuf, ifrmb, ifrms;
+
+ stb = (st/BLOCK_LEN_LONG)*num_channel + ich; /* start block */
+ sts = st % BLOCK_LEN_LONG; /* start sample */
+ edb = ((st+len)/BLOCK_LEN_LONG)*num_channel + ich; /* end block */
+ nblk = (edb-stb)/num_channel; /* number of overflow */
+
+ ibuf=0; ifrmb=stb; ifrms=sts;
+ for ( iblk=0; iblk<nblk; iblk++ ){
+ while( ifrms < BLOCK_LEN_LONG ) buf[ibuf++] = frm[(ifrms++)+ifrmb*BLOCK_LEN_LONG];
+ ifrms = 0;
+ ifrmb += num_channel;
+ }
+ while( ibuf < len )
+ buf[ibuf++] = frm[(ifrms++)+ifrmb*BLOCK_LEN_LONG];
+}
+
+__inline void CopyMem(int n, double xx[], double yy[])
+{
+ int i = n;
+ if (i <= 0)
+ return;
+ do {
+ *(yy++) = *(xx++);
+ } while(--i);
+}
+
+__inline double DotProd(/* Input */
+ int n, /* dimension of data */
+ double xx[],
+ double yy[])
+{
+ int i;
+ double s;
+ s=0.0;
+ for(i=0;i<n;i++)
+ s+=xx[i]*yy[i];
+ return(s);
+}
+
+__inline void ntt_mulddd(/* Input */
+ int n, /* dimension of data */
+ double xx[],
+ double yy[],
+ /* Output */
+ double zz[])
+{
+ int i;
+ for (i=0; i<n; i++ )
+ zz[i] = xx[i]*yy[i];
+}
+
+__inline void AutoCorr(double *sig, /* Input : signal sample sequence */
+ int n, /* Input : length of sample sequence*/
+ double *_pow,/* Output : power */
+ double cor[],/* Output : autocorrelation coefficients */
+ int p)
+{
+ int k;
+ register double sqsum,c, dsqsum;
+
+ if (n>0) {
+ sqsum = DotProd(n, sig, sig)+1.e-35;
+ dsqsum = 1./sqsum;
+ k=p;
+ do {
+ c = DotProd(n-k, sig, sig+k);
+ cor[k] = c*dsqsum;
+ }while(--k);
+ }
+ *_pow = (sqsum-1.e-35)/(double)n;
+}
+
+__inline void Corr2Ref(int p, /* Input : LPC analysis order */
+ double cor[], /* Input : correlation coefficients */
+ double alf[], /* Output : linear predictive coefficients */
+ double ref[], /* Output : reflection coefficients */
+ double *resid_) /* Output : normalized residual power */
+{
+ int i,j,k;
+ double resid,r,a;
+ if(p>0) {
+ ref[1]=cor[1];
+ alf[1]= -ref[1];
+ resid=(1.0-ref[1])*(1.0+ref[1]);
+ for(i=2;i<=p;i++) {
+ r=cor[i];
+ for(j=1;j<i;j++)
+ r+=alf[j]*cor[i-j];
+ alf[i]= -(ref[i]=(r/=resid));
+ j=0; k=i;
+ while(++j<=--k) {
+ a=alf[j];
+ alf[j]-=r*alf[k];
+ if(j<k) alf[k]-=r*a;
+ }
+ resid*=(1.0-r)*(1.0+r);
+ }
+ *resid_=resid;
+ }
+ else
+ *resid_=1.0;
+}
+
+int checkAttack(double in[], /* Input signal */
+ int *flag, /* flag for attack */
+ int InitFlag) /* Initialization Flag */
+{
+ /*--- Variables ---*/
+ int n_div, iblk, ismp, ich;
+ double bufin[N_SFT_MAX];
+ static double sig[ntt_N_SUP_MAX][N_BLK_MAX+N_LPC_MAX];
+ double wsig[N_BLK_MAX];
+ static double wdw[N_BLK_MAX];
+ static double wlag[N_LPC_MAX+1];
+ double cor[N_LPC_MAX+1],ref[N_LPC_MAX+1],alf[N_LPC_MAX+1];
+ static double prev_alf[ntt_N_SUP_MAX][N_LPC_MAX+1];
+ double resid, wpowfr;
+ double long_power;
+ double synth, resid2;
+ static int N_BLK, N_SFT, S_POW, L_POW, N_LPC;
+ double ratio, sum, product;
+
+ /*--- Initialization ---*/
+ if ( InitFlag ){
+ /* Set parameters */
+ N_BLK = BLOCK_LEN_LONG;
+ N_SFT = BLOCK_LEN_SHORT;
+ S_POW = BLOCK_LEN_SHORT;
+ L_POW = BLOCK_LEN_LONG;
+ N_LPC = 1;
+ /* clear buffers */
+ for ( ich=0; ich<num_channel; ich++ ){
+ ZeroMem( N_LPC+N_BLK, sig[ich] );
+ ZeroMem( N_LPC+1, prev_alf[ich] );
+ }
+ /* set windows */
+ LagWindow( wlag, N_LPC, 0.02 );
+ HammingWindow( wdw, N_BLK );
+ }
+
+
+ n_div = BLOCK_LEN_LONG/N_SFT;
+ *flag = 0;
+ sum=0.0;
+ product=1.0;
+ for ( ich=0; ich<num_channel; ich++ ){
+ for ( iblk=0; iblk<n_div; iblk++ ){
+ ntt_cutfr( ST_CHKATK+iblk*N_SFT, N_SFT, ich, in, bufin );
+ CopyMem(N_SFT,bufin,&sig[ich][N_LPC+N_BLK-N_SFT]);
+ /*--- Calculate long power ---*/
+ long_power =
+ (DotProd( L_POW, &sig[ich][N_BLK-L_POW], &sig[ich][N_BLK-L_POW] )+0.1)
+ / L_POW;
+ long_power = sqrt(long_power);
+
+ /*--- Calculate alpha parameter ---*/
+ ntt_mulddd( N_BLK, &sig[ich][N_LPC], wdw, wsig );
+ AutoCorr( wsig, N_BLK, &wpowfr, cor, N_LPC ); cor[0] = 1.0;
+ ntt_mulddd( N_LPC+1, cor, wlag, cor );
+ Corr2Ref( N_LPC, cor, alf, ref, &resid );
+ /*--- Get residual signal and its power ---*/
+ resid2 = 0.;
+ for ( ismp=N_BLK-S_POW; ismp<N_BLK; ismp++ ){
+ synth = sig[ich][ismp]+
+ prev_alf[ich][1]*sig[ich][ismp-1];
+ resid2 += synth*synth;
+ }
+ resid2 /= long_power;
+ resid2 = sqrt(resid2);
+ sum += resid2+0.0001;
+ product *= (resid2+0.0001);
+
+ CopyMem( N_LPC, &alf[1], &prev_alf[ich][1] );
+
+ CopyMem( N_BLK-N_SFT, &sig[ich][N_LPC+N_SFT], &sig[ich][N_LPC] );
+ }
+ }
+/* ratio = sum/(n_div*num_channel)/pow(product, 1./(double)(n_div*num_channel)); */
+ /* This below is a bit different than the commented line above here,
+ but I like it better this way, because it gives higher values,
+ that are better to tune. */
+ ratio = pow(product, 1./(double)(n_div*num_channel));
+ ratio = (n_div*num_channel)/ratio;
+ ratio = sum/ratio;
+
+ if(ratio > 8000) {
+ *flag = 1;
+ } else {
+ *flag = 0;
+ }
+ return (int)(ratio+0.5);
+}
+
+
+void winSwitchInit(int max_ch)
+{
+ num_channel = max_ch;
+}
+
--- /dev/null
+++ b/winswitch.h
@@ -1,0 +1,24 @@
+
+#ifndef _WINSWITCH_H_
+#define _WINSWITCH_H_
+
+void getWindowType(int flag, /* Input : trigger for short block length */
+ enum WINDOW_TYPE *w_type, /* Output : code index for block type*/
+ int InitFlag ); /* Control : initialization flag */
+
+int checkAttack(double in[], /* Input : input signal */
+ int *flag,/* Output : trigger for short block length */
+ int InitFlag); /* Control : initialization flag */
+
+
+int winSwitch(/* Input */
+ double sig[], /* input signal */
+ /* Output */
+ enum WINDOW_TYPE *w_type, /* Output : code index for block type*/
+ /* Control */
+ int InitFlag); /* initialization flag */
+
+void winSwitchInit(int max_ch);
+
+#endif
+