ref: 61c54b66612d77e6767c55b639969ebff9717caa
parent: 21c348fd5d20f77b018d0b812361a64fc139dc18
author: menno <menno>
date: Mon Mar 5 06:33:37 EST 2001
Added LTP Needs some more refinement, but it works
--- a/frontend/faac.dsp
+++ b/frontend/faac.dsp
@@ -25,7 +25,7 @@
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "faac - Win32 Release"
@@ -48,7 +48,7 @@
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 libsndfile.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386
@@ -72,7 +72,7 @@
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 libsndfile.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
--- a/frontend/faacgui.rc
+++ b/frontend/faacgui.rc
@@ -52,7 +52,7 @@
// Dialog
//
-IDD_MAINDIALOG DIALOGEX 0, 0, 266, 170
+IDD_MAINDIALOG DIALOGEX 0, 0, 266, 175
STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "FAAC GUI"
@@ -65,9 +65,9 @@
CONTROL "Allow Mid/Side",IDC_ALLOWMIDSIDE,"Button",
BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,13,78,71,10
EDITTEXT IDC_BITRATE,142,73,69,14,ES_AUTOHSCROLL
- EDITTEXT IDC_BANDWIDTH,142,93,69,14,ES_AUTOHSCROLL
- DEFPUSHBUTTON "Encode",IDOK,75,149,50,14,WS_DISABLED
- PUSHBUTTON "Quit",IDCANCEL,141,149,50,14
+ EDITTEXT IDC_BANDWIDTH,142,95,69,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "Encode",IDOK,75,154,50,14,WS_DISABLED
+ PUSHBUTTON "Quit",IDCANCEL,141,154,50,14
EDITTEXT IDC_INPUTFILENAME,61,12,161,14,ES_AUTOHSCROLL
EDITTEXT IDC_OUTPUTFILENAME,61,32,161,14,ES_AUTOHSCROLL |
WS_DISABLED
@@ -78,17 +78,20 @@
LTEXT "-",IDC_INPUTPARAMS,32,66,55,8
LTEXT "In:",IDC_STATIC,14,66,12,8
CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,
- 120,252,10
- GROUPBOX "Output Format",IDC_STATIC,94,62,153,51
- CTEXT "- - -",IDC_TIME,7,136,252,8
- LTEXT "Bandwidth:",IDC_STATIC,101,96,37,8
+ 124,252,10
+ GROUPBOX "Output Format",IDC_STATIC,94,62,153,57
+ CTEXT "- - -",IDC_TIME,7,140,252,8
+ LTEXT "Bandwidth:",IDC_STATIC,101,98,37,8
LTEXT "Bitrate:",IDC_STATIC,101,76,37,8
LTEXT "bps/ch",IDC_STATIC,218,76,24,8
- LTEXT "Hz",IDC_STATIC,218,96,10,8
+ LTEXT "Hz",IDC_STATIC,218,98,10,8
CONTROL "Use LFE channel",IDC_USELFE,"Button",BS_AUTOCHECKBOX |
- BS_LEFTTEXT | WS_DISABLED | WS_TABSTOP,13,102,71,10
+ BS_LEFTTEXT | WS_DISABLED | WS_TABSTOP,13,111,71,10
CONTROL "Use TNS",IDC_USETNS,"Button",BS_AUTOCHECKBOX |
- BS_LEFTTEXT | WS_TABSTOP,13,90,71,10
+ BS_LEFTTEXT | WS_TABSTOP,13,89,71,10
+ CONTROL "Use LTP",IDC_USELTP,"Button",BS_AUTOCHECKBOX |
+ BS_LEFTTEXT | WS_TABSTOP,13,100,71,10
+ RTEXT "-",IDC_COMPILEDATE,196,160,63,8
END
@@ -105,7 +108,7 @@
LEFTMARGIN, 7
RIGHTMARGIN, 259
TOPMARGIN, 7
- BOTTOMMARGIN, 163
+ BOTTOMMARGIN, 168
END
END
#endif // APSTUDIO_INVOKED
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: main.c,v 1.8 2001/03/02 08:48:24 menno Exp $
+ * $Id: main.c,v 1.9 2001/03/05 11:33:37 menno Exp $
*/
#ifdef _WIN32
@@ -69,7 +69,7 @@
int mins;
#endif
- printf("FAAC - command line demo\n");
+ printf("FAAC - command line demo of %s\n", __DATE__);
printf("Uses FAACLIB version: %.1f %s\n\n", FAACENC_VERSION, (FAACENC_VERSIONB)?"beta":"");
if (argc < 3)
@@ -78,6 +78,7 @@
printf("Options:\n");
printf(" -nm Don\'t use mid/side coding\n");
printf(" -tns Use TNS coding\n");
+ printf(" -ltp Use LTP coding\n");
printf(" -bwX Set the bandwidth, X in Hz\n");
printf(" -brX Set the bitrate per channel, X in bps\n\n");
return 1;
@@ -121,6 +122,10 @@
case 't': case 'T':
if ((argv[i][2] == 'n') || (argv[i][2] == 'N'))
myFormat->useTns = 1;
+ break;
+ case 'l': case 'L':
+ if ((argv[i][2] == 't') || (argv[i][2] == 'T'))
+ myFormat->useLtp = 1;
break;
case 'n': case 'N':
if ((argv[i][2] == 'm') || (argv[i][2] == 'M'))
--- a/frontend/maingui.c
+++ b/frontend/maingui.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: maingui.c,v 1.7 2001/02/28 19:09:56 menno Exp $
+ * $Id: maingui.c,v 1.8 2001/03/05 11:33:37 menno Exp $
*/
#include <windows.h>
@@ -138,6 +138,7 @@
config->allowMidside = IsDlgButtonChecked(hWnd, IDC_ALLOWMIDSIDE) == BST_CHECKED ? 1 : 0;
config->useTns = IsDlgButtonChecked(hWnd, IDC_USETNS) == BST_CHECKED ? 1 : 0;
+ config->useLtp = IsDlgButtonChecked(hWnd, IDC_USELTP) == BST_CHECKED ? 1 : 0;
GetDlgItemText(hWnd, IDC_BITRATE, szTemp, sizeof(szTemp));
config->bitRate = atoi(szTemp);
GetDlgItemText(hWnd, IDC_BANDWIDTH, szTemp, sizeof(szTemp));
@@ -180,6 +181,7 @@
config->allowMidside = IsDlgButtonChecked(hWnd, IDC_ALLOWMIDSIDE) == BST_CHECKED ? 1 : 0;
config->useTns = IsDlgButtonChecked(hWnd, IDC_USETNS) == BST_CHECKED ? 1 : 0;
config->useLfe = IsDlgButtonChecked(hWnd, IDC_USELFE) == BST_CHECKED ? 1 : 0;
+ config->useLtp = IsDlgButtonChecked(hWnd, IDC_USELTP) == BST_CHECKED ? 1 : 0;
GetDlgItemText(hWnd, IDC_BITRATE, szTemp, sizeof(szTemp));
config->bitRate = atoi(szTemp);
GetDlgItemText(hWnd, IDC_BANDWIDTH, szTemp, sizeof(szTemp));
@@ -317,8 +319,11 @@
CheckDlgButton(hWnd, IDC_ALLOWMIDSIDE, TRUE);
CheckDlgButton(hWnd, IDC_USELFE, FALSE);
CheckDlgButton(hWnd, IDC_USETNS, TRUE);
+ CheckDlgButton(hWnd, IDC_USELTP, FALSE);
SetDlgItemText(hWnd, IDC_BITRATE, "64000");
SetDlgItemText(hWnd, IDC_BANDWIDTH, "18000");
+
+ SetDlgItemText(hWnd, IDC_COMPILEDATE, "Ver: " __DATE__);
DragAcceptFiles(hWnd, TRUE);
return TRUE;
--- a/frontend/resource.h
+++ b/frontend/resource.h
@@ -15,6 +15,8 @@
#define IDC_BITRATE 1010
#define IDC_USELFE 1011
#define IDC_USETNS 1012
+#define IDC_USELTP 1013
+#define IDC_COMPILEDATE 1018
// Next default values for new objects
//
@@ -22,7 +24,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1016
+#define _APS_NEXT_CONTROL_VALUE 1019
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
--- a/include/faac.h
+++ b/include/faac.h
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: faac.h,v 1.3 2001/02/28 18:39:34 menno Exp $
+ * $Id: faac.h,v 1.4 2001/03/05 11:33:37 menno Exp $
*/
#ifndef FAACLIB_H
@@ -58,6 +58,9 @@
/* Use Temporal Noise Shaping */
unsigned int useTns;
+
+ /* Use Long Term Prediction */
+ unsigned int useLtp;
/* bitrate / channel of AAC file */
unsigned long bitRate;
--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: aacquant.c,v 1.4 2001/02/28 18:39:34 menno Exp $
+ * $Id: aacquant.c,v 1.5 2001/03/05 11:33:37 menno Exp $
*/
#include <math.h>
@@ -62,14 +62,22 @@
for (channel = 0; channel < numChannels; channel++) {
coderInfo[channel].old_value = 0;
coderInfo[channel].CurrentStep = 4;
+
+ coderInfo[channel].requantFreq = (double*)malloc(BLOCK_LEN_LONG*sizeof(double));
}
}
-void AACQuantizeEnd()
+void AACQuantizeEnd(CoderInfo *coderInfo, unsigned int numChannels)
{
+ unsigned int channel;
+
if (pow43) free(pow43);
if (adj43) free(adj43);
if (adj43asm) free(adj43asm);
+
+ for (channel = 0; channel < numChannels; channel++) {
+ if (coderInfo[channel].requantFreq) free(coderInfo[channel].requantFreq);
+ }
}
int AACQuantize(CoderInfo *coderInfo,
@@ -406,7 +414,6 @@
int *scale_factor = coderInfo->scale_factor;
int *best_scale_factor;
- double *requant_xr;
int *save_xi;
double *distort;
@@ -413,7 +420,6 @@
distort = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
best_scale_factor = (int*)malloc(MAX_SCFAC_BANDS*sizeof(int));
- requant_xr = (double*)malloc(FRAME_LEN*sizeof(double));
save_xi = (int*)malloc(FRAME_LEN*sizeof(int));
notdone = 1;
@@ -428,7 +434,7 @@
store_global_gain = coderInfo->global_gain;
- over = CalcNoise(coderInfo, xr, xi, requant_xr, distort, xmin, &noiseInfo);
+ over = CalcNoise(coderInfo, xr, xi, coderInfo->requantFreq, distort, xmin, &noiseInfo);
if (outer_loop_count == 1)
better = 1;
@@ -467,7 +473,6 @@
}
memcpy(xi, save_xi, sizeof(int)*BLOCK_LEN_LONG);
- if (requant_xr) free(requant_xr);
if (best_scale_factor) free(best_scale_factor);
if (save_xi) free(save_xi);
if (distort) free(distort);
--- a/libfaac/aacquant.h
+++ b/libfaac/aacquant.h
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: aacquant.h,v 1.1 2001/01/17 11:21:40 menno Exp $
+ * $Id: aacquant.h,v 1.2 2001/03/05 11:33:37 menno Exp $
*/
#ifndef AACQUANT_H
@@ -47,7 +47,7 @@
} calcNoiseResult;
void AACQuantizeInit(CoderInfo *coderInfo, unsigned int numChannels);
-void AACQuantizeEnd();
+void AACQuantizeEnd(CoderInfo *coderInfo, unsigned int numChannels);
int AACQuantize(CoderInfo *coderInfo,
PsyInfo *psyInfo,
--- a/libfaac/bitstream.c
+++ b/libfaac/bitstream.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: bitstream.c,v 1.4 2001/02/28 18:39:34 menno Exp $
+ * $Id: bitstream.c,v 1.5 2001/03/05 11:33:37 menno Exp $
*/
#include <stdlib.h>
@@ -26,8 +26,8 @@
#include "channels.h"
#include "huffman.h"
#include "bitstream.h"
+#include "ltp.h"
-
int WriteBitstream(faacEncHandle hEncoder,
CoderInfo *coderInfo,
ChannelInfo *channelInfo,
@@ -377,18 +377,50 @@
return bits;
}
-static int WriteLTPPredictorData(CoderInfo *coderInfo,
- BitStream *bitStream,
- int writeFlag)
+static int WriteLTPPredictorData(CoderInfo *coderInfo, BitStream *bitStream, int writeFlag)
{
- int bits = 0;
+ int i, last_band;
+ int bits;
+ LtpInfo *ltpInfo = &coderInfo->ltpInfo;
- if(writeFlag)
- PutBit (bitStream, 0, 1); /* LTP not used */
+ bits = 1;
+
+ if (ltpInfo->global_pred_flag)
+ {
+ if(writeFlag)
+ PutBit(bitStream, 1, 1); /* LTP used */
- bits += 1;
+ switch(coderInfo->block_type)
+ {
+ case ONLY_LONG_WINDOW:
+ case LONG_SHORT_WINDOW:
+ case SHORT_LONG_WINDOW:
+ bits += LEN_LTP_LAG;
+ bits += LEN_LTP_COEF;
+ if(writeFlag)
+ {
+ PutBit(bitStream, ltpInfo->delay[0], LEN_LTP_LAG);
+ PutBit(bitStream, ltpInfo->weight_idx, LEN_LTP_COEF);
+ }
- return bits;
+ last_band = (coderInfo->nr_of_sfb < MAX_LT_PRED_LONG_SFB) ?
+ coderInfo->nr_of_sfb : MAX_LT_PRED_LONG_SFB;
+
+ bits += last_band;
+ if(writeFlag)
+ for (i = 0; i < last_band; i++)
+ PutBit(bitStream, ltpInfo->sfb_prediction_used[i], LEN_LTP_LONG_USED);
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ if(writeFlag)
+ PutBit(bitStream, 0, 1); /* LTP not used */
+ }
+
+ return (bits);
}
static int WritePulseData(CoderInfo *coderInfo,
--- a/libfaac/coder.h
+++ b/libfaac/coder.h
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: coder.h,v 1.3 2001/02/28 18:39:34 menno Exp $
+ * $Id: coder.h,v 1.4 2001/03/05 11:33:37 menno Exp $
*/
#ifndef CODER_H
@@ -44,7 +44,6 @@
SHORT_LONG_WINDOW
};
-/* Added TNS defines and structures here to get it to compile */
#define TNS_MAX_ORDER 20
#define DEF_TNS_GAIN_THRESH 1.4
#define DEF_TNS_COEFF_THRESH 0.1
@@ -53,6 +52,23 @@
#define LEN_TNS_NFILTL 2
#define LEN_TNS_NFILTS 1
+#define LPC 1
+#define DELAY 2048
+#define LEN_LTP_DATA_PRESENT 1
+#define LEN_LTP_LAG 11
+#define LEN_LTP_COEF 3
+#define LEN_LTP_SHORT_USED 1
+#define LEN_LTP_SHORT_LAG_PRESENT 1
+#define LEN_LTP_SHORT_LAG 5
+#define LTP_LAG_OFFSET 16
+#define LEN_LTP_LONG_USED 1
+#define MAX_LT_PRED_LONG_SFB 40
+#define MAX_LT_PRED_SHORT_SFB 13
+#define SHORT_SQ_OFFSET (BLOCK_LEN_LONG-(BLOCK_LEN_SHORT*4+BLOCK_LEN_SHORT/2))
+#define CODESIZE 8
+#define NOK_LT_BLEN (3 * BLOCK_LEN_LONG)
+
+
typedef struct {
int order; /* Filter order */
int direction; /* Filtering direction */
@@ -79,9 +95,23 @@
int tnsMaxOrderShort;
TnsWindowData windowData[MAX_SHORT_WINDOWS]; /* TNS data per window */
} TnsInfo;
-/* End of TNS defines and structures */
+typedef struct
+{
+ int weight_idx;
+ double weight;
+ int sbk_prediction_used[MAX_SHORT_WINDOWS];
+ int sfb_prediction_used[MAX_SCFAC_BANDS];
+ int delay[MAX_SHORT_WINDOWS];
+ int global_pred_flag;
+ int side_info;
+ short *buffer;
+ double *mdct_predicted;
+ double *time_buffer;
+ double *ltp_overlap_buffer;
+} LtpInfo;
+
typedef struct {
int window_shape;
int prev_window_shape;
@@ -111,7 +141,11 @@
/* Lengths of spectral bitstream elements */
int *len;
+ /* Holds the requantized spectrum */
+ double *requantFreq;
+
TnsInfo tnsInfo;
+ LtpInfo ltpInfo;
} CoderInfo;
--- a/libfaac/filtbank.c
+++ b/libfaac/filtbank.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: filtbank.c,v 1.4 2001/02/28 18:39:34 menno Exp $
+ * $Id: filtbank.c,v 1.5 2001/03/05 11:33:37 menno Exp $
*/
/*
@@ -82,10 +82,11 @@
CoderInfo *coderInfo,
double *p_in_data,
double *p_out_mdct,
- double *p_overlap)
+ double *p_overlap,
+ int overlap_select)
{
- double *transf_buf;
double *p_o_buf, *first_window, *second_window;
+ double *transf_buf;
int k, i;
int block_type = coderInfo->block_type;
@@ -93,39 +94,49 @@
/* create / shift old values */
/* We use p_overlap here as buffer holding the last frame time signal*/
- memcpy(transf_buf, p_overlap, FRAME_LEN*sizeof(double));
- memcpy(transf_buf+BLOCK_LEN_LONG, p_in_data, FRAME_LEN*sizeof(double));
- memcpy(p_overlap, p_in_data, FRAME_LEN*sizeof(double));
+ if(overlap_select != MNON_OVERLAPPED) {
+ memcpy(transf_buf, p_overlap, FRAME_LEN*sizeof(double));
+ memcpy(transf_buf+BLOCK_LEN_LONG, p_in_data, FRAME_LEN*sizeof(double));
+ memcpy(p_overlap, p_in_data, FRAME_LEN*sizeof(double));
+ } else {
+ memcpy(transf_buf, p_in_data, 2*FRAME_LEN*sizeof(double));
+ }
/* Window shape processing */
- switch (coderInfo->prev_window_shape){
- case SINE_WINDOW:
- if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW))
- first_window = hEncoder->sin_window_long;
- else
- first_window = hEncoder->sin_window_short;
- break;
- case KBD_WINDOW:
- if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW))
- first_window = hEncoder->kbd_window_long;
- else
- first_window = hEncoder->kbd_window_short;
- break;
- }
+ if(overlap_select != MNON_OVERLAPPED) {
+ switch (coderInfo->prev_window_shape) {
+ case SINE_WINDOW:
+ if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW))
+ first_window = hEncoder->sin_window_long;
+ else
+ first_window = hEncoder->sin_window_short;
+ break;
+ case KBD_WINDOW:
+ if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW))
+ first_window = hEncoder->kbd_window_long;
+ else
+ first_window = hEncoder->kbd_window_short;
+ break;
+ }
- switch (coderInfo->window_shape){
- case SINE_WINDOW:
- if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW))
- second_window = hEncoder->sin_window_long;
- else
- second_window = hEncoder->sin_window_short;
- break;
- case KBD_WINDOW:
- if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW))
- second_window = hEncoder->kbd_window_long;
- else
- second_window = hEncoder->kbd_window_short;
- break;
+ switch (coderInfo->window_shape){
+ case SINE_WINDOW:
+ if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW))
+ second_window = hEncoder->sin_window_long;
+ else
+ second_window = hEncoder->sin_window_short;
+ break;
+ case KBD_WINDOW:
+ if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW))
+ second_window = hEncoder->kbd_window_long;
+ else
+ second_window = hEncoder->kbd_window_short;
+ break;
+ }
+ } else {
+ /* Always long block and sine window for LTP */
+ first_window = hEncoder->sin_window_long;
+ second_window = hEncoder->sin_window_long;
}
/* Set ptr to transf-Buffer */
@@ -132,7 +143,7 @@
p_o_buf = transf_buf;
/* Separate action for each Block Type */
- switch( block_type ) {
+ switch (block_type) {
case ONLY_LONG_WINDOW :
for ( i = 0 ; i < BLOCK_LEN_LONG ; i++){
p_out_mdct[i] = p_o_buf[i] * first_window[i];
@@ -179,6 +190,161 @@
if (transf_buf) free(transf_buf);
}
+void IFilterBank(faacEncHandle hEncoder,
+ CoderInfo *coderInfo,
+ double *p_in_data,
+ double *p_out_data,
+ double *p_overlap,
+ int overlap_select)
+{
+ double *o_buf, *transf_buf, *overlap_buf;
+ double *first_window, *second_window;
+
+ double *fp;
+ int k, i;
+ int block_type = coderInfo->block_type;
+
+ transf_buf = (double*)malloc(2*BLOCK_LEN_LONG*sizeof(double));
+ overlap_buf = (double*)malloc(2*BLOCK_LEN_LONG*sizeof(double));
+
+ /* Window shape processing */
+ if (overlap_select != MNON_OVERLAPPED) {
+// switch (coderInfo->prev_window_shape){
+// case SINE_WINDOW:
+ if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW))
+ first_window = hEncoder->sin_window_long;
+ else
+ first_window = hEncoder->sin_window_short;
+// break;
+// case KBD_WINDOW:
+// if ( (block_type == ONLY_LONG_WINDOW) || (block_type == LONG_SHORT_WINDOW))
+// first_window = hEncoder->kbd_window_long;
+// else
+// first_window = hEncoder->kbd_window_short;
+// break;
+// }
+
+// switch (coderInfo->window_shape){
+// case SINE_WINDOW:
+ if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW))
+ second_window = hEncoder->sin_window_long;
+ else
+ second_window = hEncoder->sin_window_short;
+// break;
+// case KBD_WINDOW:
+// if ( (block_type == ONLY_LONG_WINDOW) || (block_type == SHORT_LONG_WINDOW))
+// second_window = hEncoder->kbd_window_long;
+// else
+// second_window = hEncoder->kbd_window_short;
+// break;
+// }
+ } else {
+ /* Always long block and sine window for LTP */
+ first_window = hEncoder->sin_window_long;
+ second_window = hEncoder->sin_window_long;
+ }
+
+ /* Assemble overlap buffer */
+ memcpy(overlap_buf,p_overlap,BLOCK_LEN_LONG*sizeof(double));
+ o_buf = overlap_buf;
+
+ /* Separate action for each Block Type */
+ switch( block_type ) {
+ case ONLY_LONG_WINDOW :
+ memcpy(transf_buf, p_in_data,BLOCK_LEN_LONG*sizeof(double));
+ IMDCT( transf_buf, 2*BLOCK_LEN_LONG );
+ for ( i = 0 ; i < BLOCK_LEN_LONG ; i++)
+ transf_buf[i] *= first_window[i];
+ if (overlap_select != MNON_OVERLAPPED) {
+ for ( i = 0 ; i < BLOCK_LEN_LONG; i++ ){
+ o_buf[i] += transf_buf[i];
+ o_buf[i+BLOCK_LEN_LONG] = transf_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1];
+ }
+ } else { /* overlap_select == NON_OVERLAPPED */
+ for ( i = 0 ; i < BLOCK_LEN_LONG; i++ )
+ transf_buf[i+BLOCK_LEN_LONG] *= second_window[BLOCK_LEN_LONG-i-1];
+ }
+ break;
+
+ case LONG_SHORT_WINDOW :
+ memcpy(transf_buf, p_in_data,BLOCK_LEN_LONG*sizeof(double));
+ IMDCT( transf_buf, 2*BLOCK_LEN_LONG );
+ for ( i = 0 ; i < BLOCK_LEN_LONG ; i++)
+ transf_buf[i] *= first_window[i];
+ if (overlap_select != MNON_OVERLAPPED) {
+ for ( i = 0 ; i < BLOCK_LEN_LONG; i++ )
+ o_buf[i] += transf_buf[i];
+ memcpy(o_buf+BLOCK_LEN_LONG,transf_buf+BLOCK_LEN_LONG,NFLAT_LS*sizeof(double));
+ for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++)
+ o_buf[i+BLOCK_LEN_LONG+NFLAT_LS] = transf_buf[i+BLOCK_LEN_LONG+NFLAT_LS] * second_window[BLOCK_LEN_SHORT-i-1];
+ memset(o_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double));
+ } else { /* overlap_select == NON_OVERLAPPED */
+ for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++)
+ transf_buf[i+BLOCK_LEN_LONG+NFLAT_LS] *= second_window[BLOCK_LEN_SHORT-i-1];
+ memset(transf_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double));
+ }
+ break;
+
+ case SHORT_LONG_WINDOW :
+ memcpy(transf_buf, p_in_data,BLOCK_LEN_LONG*sizeof(double));
+ IMDCT( transf_buf, 2*BLOCK_LEN_LONG );
+ for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++)
+ transf_buf[i+NFLAT_LS] *= first_window[i];
+ if (overlap_select != MNON_OVERLAPPED) {
+ for ( i = 0 ; i < BLOCK_LEN_SHORT; i++ )
+ o_buf[i+NFLAT_LS] += transf_buf[i+NFLAT_LS];
+ memcpy(o_buf+BLOCK_LEN_SHORT+NFLAT_LS,transf_buf+BLOCK_LEN_SHORT+NFLAT_LS,NFLAT_LS*sizeof(double));
+ for ( i = 0 ; i < BLOCK_LEN_LONG ; i++)
+ o_buf[i+BLOCK_LEN_LONG] = transf_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1];
+ } else { /* overlap_select == NON_OVERLAPPED */
+ memset(transf_buf,0,NFLAT_LS*sizeof(double));
+ for ( i = 0 ; i < BLOCK_LEN_LONG ; i++)
+ transf_buf[i+BLOCK_LEN_LONG] *= second_window[BLOCK_LEN_LONG-i-1];
+ }
+ break;
+
+ case ONLY_SHORT_WINDOW :
+ if (overlap_select != MNON_OVERLAPPED) {
+ fp = o_buf + NFLAT_LS;
+ } else { /* overlap_select == NON_OVERLAPPED */
+ fp = transf_buf;
+ }
+ for ( k=0; k < MAX_SHORT_WINDOWS; k++ ) {
+ memcpy(transf_buf,p_in_data,BLOCK_LEN_SHORT*sizeof(double));
+ IMDCT( transf_buf, 2*BLOCK_LEN_SHORT );
+ p_in_data += BLOCK_LEN_SHORT;
+ if (overlap_select != MNON_OVERLAPPED) {
+ for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++){
+ transf_buf[i] *= first_window[i];
+ fp[i] += transf_buf[i];
+ fp[i+BLOCK_LEN_SHORT] = transf_buf[i+BLOCK_LEN_SHORT] * second_window[BLOCK_LEN_SHORT-i-1];
+ }
+ fp += BLOCK_LEN_SHORT;
+ } else { /* overlap_select == NON_OVERLAPPED */
+ for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++){
+ fp[i] *= first_window[i];
+ fp[i+BLOCK_LEN_SHORT] *= second_window[BLOCK_LEN_SHORT-i-1];
+ }
+ fp += 2*BLOCK_LEN_SHORT;
+ }
+ first_window = second_window;
+ }
+ memset(o_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double));
+ break;
+ }
+
+ if (overlap_select != MNON_OVERLAPPED)
+ memcpy(p_out_data,o_buf,BLOCK_LEN_LONG*sizeof(double));
+ else /* overlap_select == NON_OVERLAPPED */
+ memcpy(p_out_data,transf_buf,2*BLOCK_LEN_LONG*sizeof(double));
+
+ /* save unused output data */
+ memcpy(p_overlap,o_buf+BLOCK_LEN_LONG,BLOCK_LEN_LONG*sizeof(double));
+
+ if (overlap_buf) free(overlap_buf);
+ if (transf_buf) free(transf_buf);
+}
+
void specFilter(double *freqBuff,
int sampleRate,
int lowpassFreq,
@@ -308,6 +474,86 @@
data [(N >> 1) - 1 - 2 * i] = tempi; /* first half odd */
data [(N >> 1) + 2 * i] = -tempi; /* second half even */
data [N - 1 - 2 * i] = tempr; /* second half odd */
+
+ /* use recurrence to prepare cosine and sine for next value of i */
+ cold = c;
+ c = c * cfreq - s * sfreq;
+ s = s * cfreq + cold * sfreq;
+ }
+
+ if (xr) free(xr);
+ if (xi) free(xi);
+}
+
+static void IMDCT(double *data, int N)
+{
+ double *xi, *xr;
+ double tempr, tempi, c, s, cold, cfreq, sfreq; /* temps for pre and post twiddle */
+ double freq = 2.0 * M_PI / N;
+ double fac, cosfreq8, sinfreq8;
+ int i;
+
+ xi = (double*)malloc((N >> 2)*sizeof(double));
+ xr = (double*)malloc((N >> 2)*sizeof(double));
+
+ /* Choosing to allocate 2/N factor to Inverse Xform! */
+ fac = 2. / N; /* remaining 2/N from 4/N IFFT factor */
+
+ /* prepare for recurrence relation in pre-twiddle */
+ cfreq = cos (freq);
+ sfreq = sin (freq);
+ cosfreq8 = cos (freq * 0.125);
+ sinfreq8 = sin (freq * 0.125);
+ c = cosfreq8;
+ s = sinfreq8;
+
+ for (i = 0; i < (N >> 2); i++) {
+ /* calculate real and imaginary parts of g(n) or G(p) */
+ tempr = -data[2 * i];
+ tempi = data[(N >> 1) - 1 - 2 * i];
+
+ /* calculate pre-twiddled FFT input */
+ xr[i] = tempr * c - tempi * s;
+ xi[i] = tempi * c + tempr * s;
+
+ /* use recurrence to prepare cosine and sine for next value of i */
+ cold = c;
+ c = c * cfreq - s * sfreq;
+ s = s * cfreq + cold * sfreq;
+ }
+
+ /* Perform in-place complex IFFT of length N/4 */
+ switch (N) {
+ case 256:
+ srifft(xr, xi, 6);
+ break;
+ case 2048:
+ srifft(xr, xi, 9);
+ }
+
+ /* prepare for recurrence relations in post-twiddle */
+ c = cosfreq8;
+ s = sinfreq8;
+
+ /* post-twiddle FFT output and then get output data */
+ for (i = 0; i < (N >> 2); i++) {
+
+ /* get post-twiddled FFT output */
+ tempr = fac * (xr[i] * c - xi[i] * s);
+ tempi = fac * (xi[i] * c + xr[i] * s);
+
+ /* fill in output values */
+ data [(N >> 1) + (N >> 2) - 1 - 2 * i] = tempr;
+ if (i < (N >> 3))
+ data [(N >> 1) + (N >> 2) + 2 * i] = tempr;
+ else
+ data [2 * i - (N >> 2)] = -tempr;
+
+ data [(N >> 2) + 2 * i] = tempi;
+ if (i < (N >> 3))
+ data [(N >> 2) - 1 - 2 * i] = -tempi;
+ else
+ data [(N >> 2) + N - 1 - 2*i] = tempi;
/* use recurrence to prepare cosine and sine for next value of i */
cold = c;
--- a/libfaac/filtbank.h
+++ b/libfaac/filtbank.h
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: filtbank.h,v 1.5 2001/02/28 18:39:34 menno Exp $
+ * $Id: filtbank.h,v 1.6 2001/03/05 11:33:37 menno Exp $
*/
#ifndef FILTBANK_H
@@ -31,6 +31,10 @@
#define NFLAT_LS 448
+#define MOVERLAPPED 0
+#define MNON_OVERLAPPED 1
+
+
#define SINE_WINDOW 0
#define KBD_WINDOW 1
@@ -42,7 +46,15 @@
CoderInfo *coderInfo,
double *p_in_data,
double *p_out_mdct,
- double *p_overlap);
+ double *p_overlap,
+ int overlap_select);
+
+void IFilterBank(faacEncHandle hEncoder,
+ CoderInfo *coderInfo,
+ double *p_in_data,
+ double *p_out_mdct,
+ double *p_overlap,
+ int overlap_select);
void specFilter(double *freqBuff,
int sampleRate,
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: frame.c,v 1.10 2001/02/28 18:39:34 menno Exp $
+ * $Id: frame.c,v 1.11 2001/03/05 11:33:37 menno Exp $
*/
/*
@@ -41,6 +41,7 @@
#include "huffman.h"
#include "psych.h"
#include "tns.h"
+#include "ltp.h"
faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder)
@@ -56,6 +57,7 @@
hEncoder->config.allowMidside = config->allowMidside;
hEncoder->config.useLfe = config->useLfe;
hEncoder->config.useTns = config->useTns;
+ hEncoder->config.useLtp = config->useLtp;
hEncoder->config.aacProfile = config->aacProfile;
/* No SSR supported yet */
@@ -100,6 +102,7 @@
hEncoder->config.allowMidside = 1;
hEncoder->config.useLfe = 0;
hEncoder->config.useTns = 0;
+ hEncoder->config.useLtp = 0;
hEncoder->config.bitRate = 64000; /* default bitrate / channel */
hEncoder->config.bandWidth = 18000; /* default bandwidth */
@@ -116,6 +119,8 @@
hEncoder->sampleBuff[channel] = NULL;
hEncoder->nextSampleBuff[channel] = NULL;
hEncoder->next2SampleBuff[channel] = NULL;
+ hEncoder->ltpTimeBuff[channel] = (double*)malloc(2*BLOCK_LEN_LONG*sizeof(double));
+ memset(hEncoder->ltpTimeBuff[channel], 0, 2*BLOCK_LEN_LONG*sizeof(double));
}
/* Initialize coder functions */
@@ -126,6 +131,8 @@
TnsInit(hEncoder);
+ LtpInit(hEncoder);
+
AACQuantizeInit(hEncoder->coderInfo, hEncoder->numChannels);
HuffmanInit(hEncoder->coderInfo, hEncoder->numChannels);
@@ -143,12 +150,15 @@
FilterBankEnd(hEncoder);
- AACQuantizeEnd();
+ LtpEnd(hEncoder);
+ AACQuantizeEnd(hEncoder->coderInfo, hEncoder->numChannels);
+
HuffmanEnd(hEncoder->coderInfo, hEncoder->numChannels);
/* Free remaining buffer memory */
for (channel = 0; channel < hEncoder->numChannels; channel++) {
+ if (hEncoder->ltpTimeBuff[channel]) free(hEncoder->ltpTimeBuff[channel]);
if (hEncoder->sampleBuff[channel]) free(hEncoder->sampleBuff[channel]);
if (hEncoder->nextSampleBuff[channel]) free(hEncoder->nextSampleBuff[channel]);
}
@@ -170,6 +180,8 @@
int sb, frameBytes;
unsigned int bitsToUse, offset;
BitStream *bitStream; /* bitstream used for writing the frame to */
+ TnsInfo *tnsInfo_for_LTP;
+ TnsInfo *tnsDecInfo;
/* local copy's of parameters */
ChannelInfo *channelInfo = hEncoder->channelInfo;
@@ -179,6 +191,7 @@
unsigned int aacProfile = hEncoder->config.aacProfile;
unsigned int useLfe = hEncoder->config.useLfe;
unsigned int useTns = hEncoder->config.useTns;
+ unsigned int useLtp = hEncoder->config.useLtp;
unsigned int allowMidside = hEncoder->config.allowMidside;
unsigned int bitRate = hEncoder->config.bitRate;
unsigned int bandWidth = hEncoder->config.bandWidth;
@@ -189,7 +202,7 @@
if (samplesInput == 0)
hEncoder->flushFrame++;
- /* After 4 flush frames all samples have been encoded,
+ /* After 2 flush frames all samples have been encoded,
return 0 bytes written */
if (hEncoder->flushFrame == 2)
return 0;
@@ -199,6 +212,18 @@
/* Update current sample buffers */
for (channel = 0; channel < numChannels; channel++) {
+ if (hEncoder->sampleBuff[channel]) {
+ for(i = 0; i < FRAME_LEN; i++) {
+ hEncoder->ltpTimeBuff[channel][i] = hEncoder->sampleBuff[channel][i];
+ }
+ }
+ if (hEncoder->nextSampleBuff[channel]) {
+ for(i = 0; i < FRAME_LEN; i++) {
+ hEncoder->ltpTimeBuff[channel][FRAME_LEN + i] =
+ hEncoder->nextSampleBuff[channel][i];
+ }
+ }
+
if (hEncoder->sampleBuff[channel])
free(hEncoder->sampleBuff[channel]);
hEncoder->sampleBuff[channel] = hEncoder->nextSampleBuff[channel];
@@ -240,7 +265,8 @@
&coderInfo[channel],
hEncoder->sampleBuff[channel],
hEncoder->freqBuff[channel],
- hEncoder->overlapBuff[channel]);
+ hEncoder->overlapBuff[channel],
+ MOVERLAPPED);
if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) {
for (k = 0; k < 8; k++) {
@@ -307,6 +333,27 @@
}
}
+ for(channel = 0; channel < numChannels; channel++)
+ {
+ if((coderInfo[channel].tnsInfo.tnsDataPresent != 0) && (useTns))
+ tnsInfo_for_LTP = &(coderInfo[channel].tnsInfo);
+ else
+ tnsInfo_for_LTP = NULL;
+
+ if(channelInfo[channel].present && (!channelInfo[channel].lfe) &&
+ (coderInfo[channel].block_type != ONLY_SHORT_WINDOW) && (useLtp))
+ {
+ LtpEncode(hEncoder,
+ &coderInfo[channel],
+ &(coderInfo[channel].ltpInfo),
+ tnsInfo_for_LTP,
+ hEncoder->freqBuff[channel],
+ hEncoder->ltpTimeBuff[channel]);
+ } else {
+ coderInfo[channel].ltpInfo.global_pred_flag = 0;
+ }
+ }
+
MSEncode(coderInfo, channelInfo, hEncoder->freqBuff, numChannels, allowMidside);
/* Quantize and code the signal */
@@ -320,6 +367,44 @@
AACQuantize(&coderInfo[channel], &hEncoder->psyInfo[channel],
&channelInfo[channel], hEncoder->srInfo->cb_width_long,
hEncoder->srInfo->num_cb_long, hEncoder->freqBuff[channel], bitsToUse);
+ }
+ }
+
+ for (channel = 0; channel < numChannels; channel++)
+ {
+ if((coderInfo[channel].tnsInfo.tnsDataPresent != 0) && (useTns))
+ tnsDecInfo = &(coderInfo[channel].tnsInfo);
+ else
+ tnsDecInfo = NULL;
+
+ if ((!channelInfo[channel].lfe) && (useLtp)) { /* no reconstruction needed for LFE channel*/
+
+ LtpReconstruct(&coderInfo[channel], &(coderInfo[channel].ltpInfo),
+ coderInfo[channel].requantFreq);
+
+ if(tnsDecInfo != NULL)
+ TnsDecodeFilterOnly(&(coderInfo[channel].tnsInfo), coderInfo[channel].nr_of_sfb,
+ coderInfo[channel].max_sfb, coderInfo[channel].block_type,
+ coderInfo[channel].sfb_offset, coderInfo[channel].requantFreq);
+
+ IFilterBank(hEncoder, &coderInfo[channel],
+ coderInfo[channel].requantFreq,
+ coderInfo[channel].ltpInfo.time_buffer,
+ coderInfo[channel].ltpInfo.ltp_overlap_buffer,
+ MOVERLAPPED);
+
+ LtpUpdate(&(coderInfo[channel].ltpInfo),
+ coderInfo[channel].ltpInfo.time_buffer,
+ coderInfo[channel].ltpInfo.ltp_overlap_buffer,
+ BLOCK_LEN_LONG);
+ }
+
+ /* If short window, reconstruction not needed for prediction */
+ if ((coderInfo[channel].block_type == ONLY_SHORT_WINDOW)) {
+ int sind;
+ for (sind = 0; sind < 1024; sind++) {
+ coderInfo[channel].requantFreq[sind] = 0.0;
+ }
}
}
--- a/todo.txt
+++ b/todo.txt
@@ -5,9 +5,9 @@
- DONE: Add frequency cutoff filter
- DONE: Add ADTS headers
- DONE: Write GUI
-- Add TNS
+- DONE: Add TNS
+- DONE: Add LTP
- Add PNS
-- Add LTP
- Add backward prediction (MPEG2-AAC)????
- Add IS
- Add bit reservoir control