MP3 보다 성능이 좋다고 알려진 AAC 코덱의 핵심 알고리즘은 MDCT 와 IMDCT그리고 , Overlap and Add
소스보자
/***
제목 : MDCT/IMDCT 동작 구현
과목명 : 음성 신호 처리
교수님 : 박호종 교수님
이름 : 이영곤
학번 : 1999108145
***/
#include
#include
#include
#define SAMPLES_PER_FRAME 128 // 한개 frame에 있는 sample 개수
#define SAMPLES_PER_WINDOW (SAMPLES_PER_FRAME*2) // window samples개수
#define POINT_IMDCT (SAMPLES_PER_FRAME*2) // 시간축에서 DCT point 개수
#define POINT_MDCT SAMPLES_PER_FRAME // 주파수축에서 IDCT point 개수
#define PI 3.141592 // pi
// MDCT
void doMdct(double *src , double *result , int srcLen , int resLen)
{
int i,j;
for (i = 0 ; i < resLen ; i++)
{
result[i] = 0.0;
for (j = 0 ; j < srcLen ; j++)
{
result[i] += src[j]*cos(2*PI/SAMPLES_PER_WINDOW*(j+(SAMPLES_PER_FRAME+1)/2.0)*(i+0.5));
}
result[i] *= 2;
}
}
// IMDCT
void doIMdct(double *src , double *result , int srcLen , int resLen)
{
int i,j;
for (i = 0 ; i < resLen ; i++)
{
result[i] = 0.0;
for (j = 0 ; j < srcLen ; j++)
{
result[i] += src[j]*cos(2*PI/SAMPLES_PER_WINDOW*(i+(SAMPLES_PER_FRAME+1)/2.0)*(j+0.5));
}
result[i] /= SAMPLES_PER_FRAME;
}
}
// memory 할당 영역을 초기화 해준다.
void initVar(short *tmp , int length)
{
int i;
for (i = 0 ; i < length ; i++)
tmp[i] = 0;
}
void printQueue(double *queue , int len)
{
int i = 0 ;
for ( i = 0 ; i < len ; i++)
{
printf ("%d th data = %f\n",i,queue[i]);
}
}
// queue 에 dlen 길이단위로 data 를 push 시킨다. 앞에 있는 데이타는 잃어버린다.
void enQueue(double *queue , short *data , int qlen , int dlen)
{
int i;
if (qlen >= dlen/2)
{
for (i = 0 ; i < dlen ; i++)
{
queue[i] = queue[dlen+i];
queue[dlen+i] = (double)data[i];
}
}
else
printf("queue overflow..\n");
}
// data 를 queue 에서 뽑아온다.
void deQueue(double *queue , double *data , int qlen , int dlen)
{
int i;
for (i = 0 ; i < dlen ; i++)
{
data[i] = queue[i];
queue[i] = queue[i+dlen];
queue[i+dlen] = 0.0;
}
}
// sample 값들에 window를 씌운다. 2 frame 단위로 처리한다.
void makeWindowedSample(double *data , int len)
{
int i=0;
for (i = 0 ; i < len ; i++)
{
data[i] = data[i]*sin((PI/SAMPLES_PER_WINDOW)*(i+0.5));
}
}
double getMaxVal(double *src , int size)
{
int i;
double tmp = 0.0,max;
for ( i = 0 ; i < size ; i++)
{
max = (src[i] < 0 ) ? -src[i] : src[i];
tmp = (max > tmp) ? max : tmp;
}
return tmp;
}
// overlap and add function
void addOverlapped(double *preVal , double *curVal , short *result , int size)
{
int i;
for ( i = 0 ; i < size ; i++)
{
result[i] = (short)(preVal[i] + curVal[i])/2;
result[i] = (result[i] > 32767 ) ? 32767 : result[i];
result[i] = (result[i] < -32768 ) ? -32768 : result[i];
}
}
int main ()
{
FILE *fi,*fo; // FILE IO
int first = 0;
short frame[SAMPLES_PER_FRAME] = {0,}; // data frame
short result[SAMPLES_PER_FRAME] = {0,}; // result data
double dQueue[SAMPLES_PER_WINDOW] = {0,}; //data queue 256 size
double rQueue[SAMPLES_PER_FRAME] = {0,}; //data queue 256 size
double nQueue[SAMPLES_PER_FRAME] = {0,}; // data queue 256 size
double mDct[POINT_MDCT] = {0,}; // dct array
double imDct[POINT_IMDCT] = {0,}; // idct array
/** File OPEN **/
fi = fopen("input.raw", "rb"); // input file open
fo = fopen("output.raw","wb"); // output file open
if(fi == NULL || fo == NULL)
{
printf("File Open Failed..\n");
exit(-1);
}
/** 1Frame 씩 데이타를 받아서 2Frame 단위로 처리를 한다. **/
while( fread(frame, sizeof(short), SAMPLES_PER_FRAME, fi) ) // 1frame 단위로 데이타를 읽는다.
{
// 1frame 의 데이타를 받아서 queue에 넣는다.
enQueue(dQueue , frame , SAMPLES_PER_WINDOW , SAMPLES_PER_FRAME);
// 2frame에 window 를 씌운다.
makeWindowedSample(dQueue , SAMPLES_PER_WINDOW);
// MDct 를 수행한다.
doMdct(dQueue , mDct , SAMPLES_PER_WINDOW , POINT_MDCT);
// inverseMDct 를 수행한다.
doIMdct(mDct , imDct , POINT_MDCT , POINT_IMDCT);
// idct 결과에 window 를 씌운다.
makeWindowedSample(imDct , POINT_IMDCT);
//Queue 에서 현재 계산할 frame을 저장해놓는다.
deQueue(imDct , rQueue , POINT_IMDCT , SAMPLES_PER_FRAME);
// 이전에 얻은 frame 과 지금 구한 frame 을 더해서 결과를 구한다.
addOverlapped(nQueue,rQueue,result,SAMPLES_PER_FRAME);
//Queue 에서 다음 frame 과 add 시킬 frame 을 저장해놓는다.
deQueue(imDct , nQueue , POINT_IMDCT , SAMPLES_PER_FRAME);
// 결과를 파일에 저장한다. 처음 나온 frame은 무효 frame 처리를 한다.
if (first == 1)
fwrite(result, sizeof(short), SAMPLES_PER_FRAME, fo);
else
first = 1;
//다음에 사용할 frame 을 위해서 overlap 할 frame을 추가했다.
enQueue(dQueue , frame , SAMPLES_PER_WINDOW , SAMPLES_PER_FRAME);
}
/** 마지막 frame 처리를 위해서 virtual frame 을 생성시켜서 연산을 한번 더 한다. **/
initVar(frame,SAMPLES_PER_FRAME);
// 1frame 의 데이타를 받아서 queue에 넣는다.
enQueue(dQueue , frame , SAMPLES_PER_WINDOW , SAMPLES_PER_FRAME);
// 2frame에 window 를 씌운다.
makeWindowedSample(dQueue , SAMPLES_PER_WINDOW);
// MDct 를 수행한다.
doMdct(dQueue , mDct , SAMPLES_PER_WINDOW , POINT_MDCT);
// inverseMDct 를 수행한다.
doIMdct(mDct , imDct , POINT_MDCT , POINT_IMDCT);
// idct 결과에 window 를 씌운다.
makeWindowedSample(imDct , POINT_IMDCT);
//Queue 에서 현재 계산할 frame을 저장해놓는다.
deQueue(imDct , rQueue , POINT_IMDCT , SAMPLES_PER_FRAME);
// 이전에 얻은 frame 과 지금 구한 frame 을 더해서 결과를 구한다.
addOverlapped(nQueue,rQueue,result,SAMPLES_PER_FRAME);
fwrite(result, sizeof(short), SAMPLES_PER_FRAME, fo);
fcloseall(); // 파일을 닫는다.
return 0;
}
제목 : MDCT/IMDCT 동작 구현
과목명 : 음성 신호 처리
교수님 : 박호종 교수님
이름 : 이영곤
학번 : 1999108145
***/
#include
#include
#include
#define SAMPLES_PER_FRAME 128 // 한개 frame에 있는 sample 개수
#define SAMPLES_PER_WINDOW (SAMPLES_PER_FRAME*2) // window samples개수
#define POINT_IMDCT (SAMPLES_PER_FRAME*2) // 시간축에서 DCT point 개수
#define POINT_MDCT SAMPLES_PER_FRAME // 주파수축에서 IDCT point 개수
#define PI 3.141592 // pi
// MDCT
void doMdct(double *src , double *result , int srcLen , int resLen)
{
int i,j;
for (i = 0 ; i < resLen ; i++)
{
result[i] = 0.0;
for (j = 0 ; j < srcLen ; j++)
{
result[i] += src[j]*cos(2*PI/SAMPLES_PER_WINDOW*(j+(SAMPLES_PER_FRAME+1)/2.0)*(i+0.5));
}
result[i] *= 2;
}
}
// IMDCT
void doIMdct(double *src , double *result , int srcLen , int resLen)
{
int i,j;
for (i = 0 ; i < resLen ; i++)
{
result[i] = 0.0;
for (j = 0 ; j < srcLen ; j++)
{
result[i] += src[j]*cos(2*PI/SAMPLES_PER_WINDOW*(i+(SAMPLES_PER_FRAME+1)/2.0)*(j+0.5));
}
result[i] /= SAMPLES_PER_FRAME;
}
}
// memory 할당 영역을 초기화 해준다.
void initVar(short *tmp , int length)
{
int i;
for (i = 0 ; i < length ; i++)
tmp[i] = 0;
}
void printQueue(double *queue , int len)
{
int i = 0 ;
for ( i = 0 ; i < len ; i++)
{
printf ("%d th data = %f\n",i,queue[i]);
}
}
// queue 에 dlen 길이단위로 data 를 push 시킨다. 앞에 있는 데이타는 잃어버린다.
void enQueue(double *queue , short *data , int qlen , int dlen)
{
int i;
if (qlen >= dlen/2)
{
for (i = 0 ; i < dlen ; i++)
{
queue[i] = queue[dlen+i];
queue[dlen+i] = (double)data[i];
}
}
else
printf("queue overflow..\n");
}
// data 를 queue 에서 뽑아온다.
void deQueue(double *queue , double *data , int qlen , int dlen)
{
int i;
for (i = 0 ; i < dlen ; i++)
{
data[i] = queue[i];
queue[i] = queue[i+dlen];
queue[i+dlen] = 0.0;
}
}
// sample 값들에 window를 씌운다. 2 frame 단위로 처리한다.
void makeWindowedSample(double *data , int len)
{
int i=0;
for (i = 0 ; i < len ; i++)
{
data[i] = data[i]*sin((PI/SAMPLES_PER_WINDOW)*(i+0.5));
}
}
double getMaxVal(double *src , int size)
{
int i;
double tmp = 0.0,max;
for ( i = 0 ; i < size ; i++)
{
max = (src[i] < 0 ) ? -src[i] : src[i];
tmp = (max > tmp) ? max : tmp;
}
return tmp;
}
// overlap and add function
void addOverlapped(double *preVal , double *curVal , short *result , int size)
{
int i;
for ( i = 0 ; i < size ; i++)
{
result[i] = (short)(preVal[i] + curVal[i])/2;
result[i] = (result[i] > 32767 ) ? 32767 : result[i];
result[i] = (result[i] < -32768 ) ? -32768 : result[i];
}
}
int main ()
{
FILE *fi,*fo; // FILE IO
int first = 0;
short frame[SAMPLES_PER_FRAME] = {0,}; // data frame
short result[SAMPLES_PER_FRAME] = {0,}; // result data
double dQueue[SAMPLES_PER_WINDOW] = {0,}; //data queue 256 size
double rQueue[SAMPLES_PER_FRAME] = {0,}; //data queue 256 size
double nQueue[SAMPLES_PER_FRAME] = {0,}; // data queue 256 size
double mDct[POINT_MDCT] = {0,}; // dct array
double imDct[POINT_IMDCT] = {0,}; // idct array
/** File OPEN **/
fi = fopen("input.raw", "rb"); // input file open
fo = fopen("output.raw","wb"); // output file open
if(fi == NULL || fo == NULL)
{
printf("File Open Failed..\n");
exit(-1);
}
/** 1Frame 씩 데이타를 받아서 2Frame 단위로 처리를 한다. **/
while( fread(frame, sizeof(short), SAMPLES_PER_FRAME, fi) ) // 1frame 단위로 데이타를 읽는다.
{
// 1frame 의 데이타를 받아서 queue에 넣는다.
enQueue(dQueue , frame , SAMPLES_PER_WINDOW , SAMPLES_PER_FRAME);
// 2frame에 window 를 씌운다.
makeWindowedSample(dQueue , SAMPLES_PER_WINDOW);
// MDct 를 수행한다.
doMdct(dQueue , mDct , SAMPLES_PER_WINDOW , POINT_MDCT);
// inverseMDct 를 수행한다.
doIMdct(mDct , imDct , POINT_MDCT , POINT_IMDCT);
// idct 결과에 window 를 씌운다.
makeWindowedSample(imDct , POINT_IMDCT);
//Queue 에서 현재 계산할 frame을 저장해놓는다.
deQueue(imDct , rQueue , POINT_IMDCT , SAMPLES_PER_FRAME);
// 이전에 얻은 frame 과 지금 구한 frame 을 더해서 결과를 구한다.
addOverlapped(nQueue,rQueue,result,SAMPLES_PER_FRAME);
//Queue 에서 다음 frame 과 add 시킬 frame 을 저장해놓는다.
deQueue(imDct , nQueue , POINT_IMDCT , SAMPLES_PER_FRAME);
// 결과를 파일에 저장한다. 처음 나온 frame은 무효 frame 처리를 한다.
if (first == 1)
fwrite(result, sizeof(short), SAMPLES_PER_FRAME, fo);
else
first = 1;
//다음에 사용할 frame 을 위해서 overlap 할 frame을 추가했다.
enQueue(dQueue , frame , SAMPLES_PER_WINDOW , SAMPLES_PER_FRAME);
}
/** 마지막 frame 처리를 위해서 virtual frame 을 생성시켜서 연산을 한번 더 한다. **/
initVar(frame,SAMPLES_PER_FRAME);
// 1frame 의 데이타를 받아서 queue에 넣는다.
enQueue(dQueue , frame , SAMPLES_PER_WINDOW , SAMPLES_PER_FRAME);
// 2frame에 window 를 씌운다.
makeWindowedSample(dQueue , SAMPLES_PER_WINDOW);
// MDct 를 수행한다.
doMdct(dQueue , mDct , SAMPLES_PER_WINDOW , POINT_MDCT);
// inverseMDct 를 수행한다.
doIMdct(mDct , imDct , POINT_MDCT , POINT_IMDCT);
// idct 결과에 window 를 씌운다.
makeWindowedSample(imDct , POINT_IMDCT);
//Queue 에서 현재 계산할 frame을 저장해놓는다.
deQueue(imDct , rQueue , POINT_IMDCT , SAMPLES_PER_FRAME);
// 이전에 얻은 frame 과 지금 구한 frame 을 더해서 결과를 구한다.
addOverlapped(nQueue,rQueue,result,SAMPLES_PER_FRAME);
fwrite(result, sizeof(short), SAMPLES_PER_FRAME, fo);
fcloseall(); // 파일을 닫는다.
return 0;
}
어렵다..=_=
'설계' 카테고리의 다른 글
| Address Fowarding Module - 연구실에서 한 작업. (0) | 2006/07/07 |
|---|---|
| [자료구조] 시험 공부하다가 얻은 소득... (0) | 2006/06/14 |
| [음성신호처리] AAC Codec 핵심 알고리즘 (0) | 2006/06/04 |
| RC 카 구입 정보 (1) | 2006/05/24 |
| [영상신호처리] Sobel Edge Detect , Robert-cross gradiant , Prewitt Edge Detect 구현 (2) | 2006/05/11 |
| [음성신호처리] DFT , IDFT (1) | 2006/05/10 |


