2017-04-18 1 views
1

SDL2 및 FFTW3을 사용하여 C++에서 음악 시각화 프로그램을 만들려고합니다. 목표는 .wav 오디오 파일을로드 한 다음 오디오를 동시에 재생하고 SDL2 콜백 기능을 사용하여 실시간 고속 푸리에 변환을 수행하는 것입니다. 나중에 그래픽 시각화 프로그램을 구현할 수 있도록 주파수 스펙트럼 데이터를 가져오고 싶습니다.SDL2 오디오 스트림 데이터에서 실시간 FFT를 수행하려면 어떻게해야합니까?

.wav를로드하고 콜백 기능을 사용하여 오디오를 재생할 때 SDL YouTube 가이드를 따랐지만이 데이터에서 FFT를 수행하는 방법을 모르겠습니다. 비슷한 효과를 내기 위해 FFTW와 SDL을 C와 함께 사용하는 방법에 대한 또 다른 안내서를 따라 갔지만 실제로 구현하는 방법은 아직 확실하지 않습니다. 내가 NumPy와 배열로 .WAV 데이터 압축을 풀 NumPy와 사용 이전의 경험에서

Uint8* sampData; 
SDL_AudioSpec wavSpec; 
Uint8* wavStart; 
Uint32 wavLength; 
SDL_AudioDeviceID aDevice; 

struct AudioData { 
    Uint8* filePosition; 
    Uint32 fileLength; 
}; 

void PlayAudioCallback(void* userData, Uint8* stream, int streamLength) { 
    AudioData* audio = (AudioData*)userData; 
    sampData = new Uint8; 

    if (audio->fileLength == 0) { 
     return; 
    } 

    Uint32 length = (Uint32)streamLength; 
    length = (length > audio->fileLength ? audio->fileLength : length); 

    SDL_memcpy(stream, audio->filePosition, length); 

    // HERE is where i'd like to implement the FFT on 'stream' data 
    // but i don't know how to implement this using FFTW 

    audio->filePosition += length; 
    audio->fileLength -= length; 
} 

int main() { 
    SDL_Init(SDL_INIT_AUDIO); 

    // Load .wav file 
    if (SDL_LoadWAV(FILE_PATH, &wavSpec, &wavStart, &wavLength) == NULL) { 
     cerr << "Couldnt load file: " << FILE_PATH << endl; 
     getchar(); 
    } 
    cout << "Loaded " << FILE_PATH << endl; 

    AudioData audio; 
    audio.filePosition = wavStart; 
    audio.fileLength = wavLength; 

    wavSpec.callback = PlayAudioCallback; 
    wavSpec.userdata = &audio; 

    // Open audio playback endpoint 
    aDevice = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE); 
    if (aDevice == 0) { 
     cerr << "Audio Device connection failed: " << SDL_GetError() << endl; 
     getchar(); 
    } 
    // Play audio on playback endpoint 
    SDL_PauseAudioDevice(aDevice, 0); 

    // Do nothing while there's still data to be played 
    while (audio.fileLength > 0) { 
     SDL_Delay(100); 
    } 
} 

를 보내기 전에 NumPy와-FFT 기능 내장,하지만 난 SDL 스트림 데이터로 무엇을해야하는지에 대한 단서가있어 그 나는 여기있다.

답변

2

원하는 것은 단기 FFT입니다. 스트림에서 샘플 버퍼를 수집하고 FFT를 수행하기 전에 샘플에 창 함수를 적용합니다. 그런 다음 다른 버퍼를 수집하여 첫 번째 버퍼에서 일부 샘플을 유지하고 새 샘플을 추가합니다. 모든 데이터가 처리 될 때까지 반복하십시오.

입력 데이터가 실제이므로 FFT는 대칭이므로 첫 번째 N/2 + 1 복합 ​​출력 빈만 필요합니다. 이들은 d.c. ~ Fs/2. 그들의 규모와 음모를 가져 가라. 각 FFT에 대해 반복하십시오.

+0

거의 정확함. 설명 된 솔루션의 문제점은 윈도우 함수의 적용이 파괴적이라는 것입니다. "첫 번째 버퍼에서 일부 샘플 유지"라고 말하면 창 샘플을 유지합니다. 사실, 작은 겹침을 사용하면 창 함수가 거의 0 인 각 창 가장자리에 정확히 _ 대부분의 필터링 된 부분을 유지할 수 있습니다. 겹치는 창을 사용하는 경우 샘플을 복사 할 때 창 함수를 적용하는 것이 가장 좋습니다. 나는. 'auto * windowed = buffer * windowFunction' 대신'buffer * = windowFunction'을 사용합니다. – MSalters

+0

당신 말이 맞아요. 나는 내 iPad 키보드에 이것을 입력하려고 할 때 세부 사항을 제공하는 데 꽤 불투명했다. 아직도, 그것의 중요한 세부 사항. 감사. – sizzzzlerz

관련 문제