2009-11-05 5 views
12

오디오 파일이 있고 파일을 반복하고 각 단계마다 512 개의 샘플을 가져온 다음 FFT를 통과시킵니다.FFT를 스펙트로 그램으로 변환

블록 514가 실제 및 허수 구성 요소가 인터리브 된 상태로 (IPP의 ippsFFTFwd_RToCCS_32f_I 사용) 길이가 긴 데이터로 출력되었습니다.

내 문제는 일단 내가 가지고 있으면 이러한 복잡한 숫자로 무엇을해야합니까? 순간 나는이 약간 사용할 수있는 무언가를 제공

const float realValue = buffer[(y * 2) + 0]; 
const float imagValue = buffer[(y * 2) + 1]; 
const float value  = sqrt((realValue * realValue) + (imagValue * imagValue)); 

각 값에 대해 일을 해요하지만 난 오히려 이상 그와 함께 1로 범위는 0에서 문제를 값을 받고있는 방법은 피크 인 것 약 9 이상으로 다시 돌아옵니다. 즉, 일이 악의적으로 포화 상태에 이르렀을 때, 오디션의 스펙트로 그램을 통해 오디오를 실행할 때 매우 강하게 보이지만 간신히 나타나게되는 스펙트로 그램의 다른 부분이 있습니다. 나는 완전히 내가 FFT에 의해 반환 된 데이터가 무엇인지 100 % 확신하지 못한다는 것을 인정한다. (그렇지 않으면 내가 통과하는 512 샘플 긴 블록의 빈도 값을 나타낸다.) 특히 compex 번호가 무엇을 의미하는지에 대한 나의 이해가 부족합니다.

모든 조언과 도움을 주시면 감사하겠습니다.

편집 : 설명하기 만하면됩니다. 내 큰 문제는 스케일이 무엇인지에 대한 아이디어가 없으면 리턴 된 FFT 값은 의미가 없다는 것입니다. 누군가 저 저울을 해결하기 위해 나를 가리킬 수 있습니까?

Edit2가 : 내 눈이 심지어 내가 살펴 보았다 다른 대부분의 스펙트로 구현보다 더 나은 모습으로

size_t count2 = 0; 
size_t max2  = kFFTSize + 2; 
while(count2 < max2) 
{ 
    const float realValue = buffer[(count2) + 0]; 
    const float imagValue = buffer[(count2) + 1]; 
    const float value = (log10f(sqrtf((realValue * realValue) + (imagValue * imagValue)) * rcpVerticalZoom) + 1.0f) * 0.5f; 
    buffer[count2 >> 1] = value; 
    count2 += 2; 
} 

: 정말 좋은 찾고 다음을 수행하여 결과를 얻을 수 있습니다.

제가하고있는 일에 중대한 문제가 있습니까?

+1

복소수의 크기를 구하는 데 올바른 방법을 사용하고 있습니다. 이 (복잡한) 숫자 (0-1, 0-255, ..?)의 크기를 알아 내야합니다. FFT 함수의 문서를 참조하십시오.범위가 너무 커서 좋아하는 경우, 아래에 제안 된대로 크기의 log()를 사용하면 도움이됩니다. – Wim

+0

아마 당신의 사용에는 중요하지 않지만 FFT 너비로 나누어 주파수 도메인 값 (예 : FFT에서 얻은 값)을 정규화 할 수도 있습니다. (즉, FFT가 넓을수록 다양한 주파수 버킷의 값이 커집니다) –

답변

11

FFT를 모두 얻으려면해야 할 일은 시각의 대수를 구하는 것이 가능합니다.

그래서 출력 버퍼의 위치는 어떤 주파수가 감지되었는지 알려줍니다. 복소수의 크기 (L2 표준)는 사용자에게 호 검출 된 주파수가 강하고 위상 (아크 탄젠트)이 오디오 공간보다 훨씬 중요한 이미지 공간에서 정보를 제공합니다. FFT는 불연속이므로 주파수는 0에서 나이 퀴 스트 주파수로 실행됩니다. 이미지에서 첫 번째 용어 (DC)는 일반적으로 가장 크므로 정규화에 사용하기에 좋은 후보입니다.나는 그것이 오디오에서도 마찬가지인지 모른다. (의심 스럽다.)

+0

흥미로운 반응. 오디오에는 보통 DC 값이 없습니다 (앰프를 통과하면 스피커가 파손될 것입니다). 이것은 단지 AC입니다. – Wim

+0

어쨌든 최대 값을 찾는 것은 FFT에 비해 꽤 짧은 작업입니다. –

+0

로그 스케일을 사용하여 최대 값을 찾습니다. – peterchen

1

이상한 결과가 나오면 출력을 압축하는 방법을 FFT 라이브러리 설명서에서 확인하십시오. 일부 루틴은 실수/허수 값이 인터리브 된 팩 형식을 사용하거나 N/2 요소에서 시작하여 랩핑 할 수 있습니다.

정상 확인을 위해 알려진 특성, 예를 들어 Fs/2, Fs/4 (Fs = 샘플 빈도)로 샘플 데이터를 생성하고 FFT 루틴의 출력을 예상했던 것과 비교해 볼 것을 권장합니다. 동일한 주파수에서 사인과 코사인을 모두 만들어보십시오. 스펙트럼에서 동일한 크기를 가져야하지만 위상이 다릅니다 (즉, realValue/imagValue는 다를 수 있지만 제곱의 합은 동일해야합니다.)

그래도 FFT를 사용하려고한다면 수학적으로 어떻게 작동하는지 정말로 알아야합니다. 그렇지 않으면 앨리어싱과 같은 다른 이상한 문제가 발생할 가능성이 있습니다.

+0

음, 프로파일을 확인했습니다. 내 문제는 스케일에서 무엇을 나타내는 지 전혀 몰라도 FFT에서 가져온 숫자가 의미가 없다는 것입니다. 나는 원래의 질문을 업데이트 할 것이다. – Goz

7

512 샘플의 각 창마다, 사용자가했던 것처럼 FFT의 크기를 계산한다. 각 값은 신호에 나타나는 해당 주파수의 크기를 나타냅니다.

mag 
/\ 
| 
|  !   ! 
|  ! ! ! 
+--!---!----!----!---!--> freq 
0   Fs/2  Fs 

이제 주파수를 알아야합니다.

입력 신호가 실수 값이므로 FFT는 중간 (Nyquist 구성 요소)을 중심으로 대칭이며 첫 번째 항이 DC 구성 요소입니다. 신호 샘플링 주파수 Fs을 알면 나이 퀴 스트 주파수는 Fs/2입니다. 따라서 인덱스 k의 경우 해당 주파수는 k*Fs/512

입니다. 따라서 길이가 512 인 각 창에 대해 지정된 주파수로 크기가 표시됩니다. 연속적인 창을 통해 그 그룹이 스펙트로 그램을 형성합니다.

5

유용하다고 생각되는 몇 가지 사항이 있습니다.

앞으로 FT는 입력에서보다 출력에서 ​​더 큰 숫자를 제공하는 경향이 있습니다. 특정 주파수의 모든 강도가 데이터 세트를 통해 배포되는 것이 아니라 한 곳에서 표시되는 것으로 생각할 수 있습니다. 이게 중요합니까? 아마도 당신이 당신의 요구에 맞게 데이터를 확장 할 수 있기 때문일 것입니다. 정수 기반의 FFT/IFFT 쌍을 작성한 후 정수 오버플로를 방지하기 위해 각각의 재 지정이 필요합니다.

입력 한 실제 데이터는 거의 복잡한 데이터로 변환됩니다. 버퍼 [0]과 버퍼 [n/2]가 실제로 밝혀 졌기 때문에 독립적입니다. 그것의 좋은 토론은 here입니다.

입력 데이터는 동일한 시간 간격으로 찍은 음향 강도 값입니다. 그들은 시간 영역에서 충분히 적절하다고 말해진다. 수평축은 주파수이기 때문에 FT의 출력은 주파수 영역에 있다고합니다. 수직 스케일은 강도를 유지합니다. 입력 데이터에는 명확하지 않지만 입력에도 위상 정보가 있습니다. 모든 사운드가 사인파이지만, 사인파의 위상을 고정시키는 것은 없습니다. 이 위상 정보는 주파수 도메인에서 개별 복소수의 위상으로 나타나지만, 종종 우리는 그것에 대해 신경 쓰지 않습니다 (그리고 종종 그렇게합니다!). 그것은 단지 당신이하는 일에 달려 있습니다. 계산

은 강도 정보를 검색하지만 위상 정보는 무시합니다. 대수를 취하는 것은 본질적으로 큰 봉우리를 약화시킵니다.

희망이 있으면 도움이됩니다.

+0

그럼 내가 어떻게 단계 정보를 버리지 않고 그것을 사용하는 것이라고? 그리고 위상은 스펙트로 그램에 어떻게 적용 할 수 있습니까? – Goz

6

사람들은 내가이 모든 문제에 대해 많은 연구를했다는 것을 알고 있습니다. 내가 발견 한 가장 중요한 것은 FFT가 그것을 한 후에 정규화가 필요하다는 것입니다.

이렇게하려면 창 벡터의 모든 값을 평균하여 1보다 약간 작은 값을 얻으십시오 (직사각형 창을 사용하는 경우 1). 그런 다음 해당 숫자를 FFT 변환을 게시 한 빈 빈 수로 나눕니다.

마지막으로 FFT에서 반환 한 실제 숫자를 정규화 숫자로 나눕니다. 이제 진폭 값이 -Inf 대 1 범위에 있어야합니다. 로그 등. 당신은 여전히 ​​알려진 범위에서 일할 것입니다.