📄 filtbank.c
字号:
/*
* FAAC - Freeware Advanced Audio Coder
* Copyright (C) 2001 Menno Bakker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: filtbank.c,v 1.3 2001/06/04 23:02:24 wmay Exp $
*/
/*
* CHANGES:
* 2001/01/17: menno: Added frequency cut off filter.
*
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "coder.h"
#include "filtbank.h"
#include "frame.h"
#include "fft.h"
#include "util.h"
#define TWOPI 2*M_PI
void FilterBankInit(faacEncHandle hEncoder)
{
unsigned int i, channel;
for (channel = 0; channel < hEncoder->numChannels; channel++) {
hEncoder->freqBuff[channel] = (double*)AllocMemory(2*FRAME_LEN*sizeof(double));
hEncoder->overlapBuff[channel] = (double*)AllocMemory(FRAME_LEN*sizeof(double));
SetMemory(hEncoder->overlapBuff[channel], 0, FRAME_LEN*sizeof(double));
}
hEncoder->sin_window_long = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double));
hEncoder->sin_window_short = (double*)AllocMemory(BLOCK_LEN_SHORT*sizeof(double));
hEncoder->kbd_window_long = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double));
hEncoder->kbd_window_short = (double*)AllocMemory(BLOCK_LEN_SHORT*sizeof(double));
for( i=0; i<BLOCK_LEN_LONG; i++ )
hEncoder->sin_window_long[i] = sin((M_PI/(2*BLOCK_LEN_LONG)) * (i + 0.5));
for( i=0; i<BLOCK_LEN_SHORT; i++ )
hEncoder->sin_window_short[i] = sin((M_PI/(2*BLOCK_LEN_SHORT)) * (i + 0.5));
CalculateKBDWindow(hEncoder->kbd_window_long, 4, BLOCK_LEN_LONG*2);
CalculateKBDWindow(hEncoder->kbd_window_short, 6, BLOCK_LEN_SHORT*2);
}
void FilterBankEnd(faacEncHandle hEncoder)
{
unsigned int channel;
for (channel = 0; channel < hEncoder->numChannels; channel++) {
if (hEncoder->freqBuff[channel]) FreeMemory(hEncoder->freqBuff[channel]);
if (hEncoder->overlapBuff[channel]) FreeMemory(hEncoder->overlapBuff[channel]);
}
if (hEncoder->sin_window_long) FreeMemory(hEncoder->sin_window_long);
if (hEncoder->sin_window_short) FreeMemory(hEncoder->sin_window_short);
if (hEncoder->kbd_window_long) FreeMemory(hEncoder->kbd_window_long);
if (hEncoder->kbd_window_short) FreeMemory(hEncoder->kbd_window_short);
}
void FilterBank(faacEncHandle hEncoder,
CoderInfo *coderInfo,
double *p_in_data,
double *p_out_mdct,
double *p_overlap,
int overlap_select)
{
double *p_o_buf, *first_window, *second_window;
double *transf_buf;
int k, i;
int block_type = coderInfo->block_type;
transf_buf = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double));
/* create / shift old values */
/* We use p_overlap here as buffer holding the last frame time signal*/
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 */
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;
}
/* Set ptr to transf-Buffer */
p_o_buf = transf_buf;
/* Separate action for each 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];
p_out_mdct[i+BLOCK_LEN_LONG] = p_o_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1];
}
MDCT( p_out_mdct, 2*BLOCK_LEN_LONG );
break;
case LONG_SHORT_WINDOW :
for ( i = 0 ; i < BLOCK_LEN_LONG ; i++)
p_out_mdct[i] = p_o_buf[i] * first_window[i];
memcpy(p_out_mdct+BLOCK_LEN_LONG,p_o_buf+BLOCK_LEN_LONG,NFLAT_LS*sizeof(double));
for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++)
p_out_mdct[i+BLOCK_LEN_LONG+NFLAT_LS] = p_o_buf[i+BLOCK_LEN_LONG+NFLAT_LS] * second_window[BLOCK_LEN_SHORT-i-1];
SetMemory(p_out_mdct+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double));
MDCT( p_out_mdct, 2*BLOCK_LEN_LONG );
break;
case SHORT_LONG_WINDOW :
SetMemory(p_out_mdct,0,NFLAT_LS*sizeof(double));
for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++)
p_out_mdct[i+NFLAT_LS] = p_o_buf[i+NFLAT_LS] * first_window[i];
memcpy(p_out_mdct+NFLAT_LS+BLOCK_LEN_SHORT,p_o_buf+NFLAT_LS+BLOCK_LEN_SHORT,NFLAT_LS*sizeof(double));
for ( i = 0 ; i < BLOCK_LEN_LONG ; i++)
p_out_mdct[i+BLOCK_LEN_LONG] = p_o_buf[i+BLOCK_LEN_LONG] * second_window[BLOCK_LEN_LONG-i-1];
MDCT( p_out_mdct, 2*BLOCK_LEN_LONG );
break;
case ONLY_SHORT_WINDOW :
p_o_buf += NFLAT_LS;
for ( k=0; k < MAX_SHORT_WINDOWS; k++ ) {
for ( i = 0 ; i < BLOCK_LEN_SHORT ; i++ ){
p_out_mdct[i] = p_o_buf[i] * first_window[i];
p_out_mdct[i+BLOCK_LEN_SHORT] = p_o_buf[i+BLOCK_LEN_SHORT] * second_window[BLOCK_LEN_SHORT-i-1];
}
MDCT( p_out_mdct, 2*BLOCK_LEN_SHORT );
p_out_mdct += BLOCK_LEN_SHORT;
p_o_buf += BLOCK_LEN_SHORT;
first_window = second_window;
}
break;
}
if (transf_buf) FreeMemory(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*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double));
overlap_buf = (double*)AllocMemory(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];
SetMemory(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];
SetMemory(transf_buf+BLOCK_LEN_LONG+NFLAT_LS+BLOCK_LEN_SHORT,0,NFLAT_LS*sizeof(double));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -