2012-03-10 2 views
2

현재 FMOD 오디오 라이브러리의 getSpectrum 기능을 재현하려고합니다. 이 함수는 현재 재생중인 버퍼의 PCM 데이터를 읽고,이 데이터에 창을 적용하고 스펙트럼을 얻기 위해 FFT를 적용합니다.FFT - PCM 데이터에 창 적용

각 플로트가 0과 1 dB (10.0f * (float)log10(val) * 2.0f) 사이에있는 float 배열을 반환합니다. 나는이 문서에 따르면, 4096 바이트 버퍼에 PCM 데이터를 얻을

첫째, PCM 데이터입니다 : 내가하는 일의 확실하지 않다

내가 그렇게해야 내가 그것을 설명 할 것입니다 왼쪽과 오른쪽 쌍의 데이터 인 샘플로 구성됩니다. 내 경우

data

나는 위의 이미지처럼 16 비트 샘플 함께 일하고 있어요. 나는 왼쪽 채널에서만 작동 싶다면, 내가하고 짧은 배열의 왼쪽 PCM 데이터를 저장 : 샘플은 = 4 바이트 경우

short *data = malloc(4096); 
FMOD_Sound_ReadData(sound, (void *)data, 4096, &read); 

그래서, 내가 가진 1024 개 샘플은 왼쪽을 나타내는 1024 반바지 즉, 오른쪽 채널을 나타내는 1024 개의 반바지.

가 FFT를 수행하기 위해, I는 float 배열을 가지고 내 데이터의 창 (해닝)를 적용해야 i 배열에서의 위치이며, 상기 입력은

float hanningWindow(short in, size_t i, size_t s) 
{ 
    return in*0.5f*(1.0f-cos(2.0f*M_PI*(float)(i)/(float)(s-1.0f))); 
} 

in 및 배열의 크기 (1024)는 s입니다.

는 왼쪽 채널을 효율적으로 활용하려면 다음

float *input = malloc(1024*sizeof(float)); 
for (i = 0; i < 1024; i++) 
    input[i] = hanningWindow(data[i*2], i, 1024); 

가 그럼 난 (실제의 복잡한) kiss_fft하기 위해 FFT의 감사를 수행합니다. dB에서

kiss_fft_cpx c = output[i]; 
float   amp = sqrt(c.r*c.r + c.i*c.i); 

계산 :

amp = 10.0f * (float)log10(amp) * 2.0f; 

I 1024/2 + 1 = 513

I는 각 주파수의 진폭을 계산 크기의 kiss_fft_cpx *ouput (복소 배열)를 얻을 amp은 0과 1 사이에 있지 않습니다. PCM 데이터 또는 끝 부분에서 데이터를 정규화해야하는 곳을 알지 못합니다. 또한 나는 PCM 데이터에 내 윈도우를 적용하는 방법을 잘 모르겠습니다.

여기 getSpectrum 함수의 결과에 비해 0에서 20kHz까지의 노래에서 얻은 결과가 있습니다. (A 직사각형 창에 대한)

results

   My Result       getSpectrum Result 

어떻게 동일한 결과를 얻을 수 있습니까?

+0

, 당신이 정말로 각각의 삼각에서 그들을 계산보다는에서 Hann의 윈도우 계수를 저장한다 시각. –

+0

sqrt를 사용할 필요가 없습니다. 참고로, 20 * log10 (sqrt (x)) == 10 * log10 (x) –

답변

2

로그 (dB) 스케일에 대해 약간 혼란 스럽습니다. 0 - 1dB의 범위를 얻지 못하면 16 비트 오디오에 대해 일반적으로 96dB의 범위를 얻습니다. 상단 및 하단은 다소 자의적이다. 0 ~ -96dB 또는 96dB ~ 0dB 또는 기타 다양한 범위에 따라 원하는 범위를 선택하십시오. 아마도 이것을 보정하기 위해 적절한 오프셋 및 요인을 사용하여 분광법을 이동하고 비율을 조정해야합니다.

(참고 : 96dB의 범위는 비트 수는 16 공식 20 * log10(2^16)에서 온다.) 속도 노트에

+0

답장을 보내 주셔서 감사 합니다만, 이상하게도'20 * log10 (amp)'을 적용하면 120까지의 값을 얻을 수 있습니다. (플로트) 주조는하지만 그것에 대해서는 확신하지 못합니다. – Lowip

+0

실제로 중요한 것은 * 범위 * dB는 일부 명목상의 0dB 기준에 비례하는 비율입니다. 합당한 강도 범위를 얻기 위해 점점 커지고있는 최소/최대 값을 살펴 봐야합니다. 너의 스펙트로 그램. –

+0

위의 한 창은 평균 값 0.5를 곱합니다. 또한 부호가있는 16 비트 데이터의 최대 값은 2^16이 아니라 2^15-1입니다. 이 스케일링의 각각에 대해 -6dB를 백 오프하면 피크 dB가 84dB로 설정됩니다 –