如何对SDL2音频流数据执行实时FFT?

我正在尝试使用SDL2和FFTW3在C ++中创建音乐可视化工具。 我的目标是加载.wav音频文件,然后同时播放音频并使用SDL2回叫功能执行实时快速傅立叶变换。 我想获取频谱数据,以便日后可以实现图形可视化。

我按照SDL YouTube指南加载.wav并使用回调函数播放音频,但我不明白如何对此数据执行FFT。 我遵循另一个使用FFTW和SDL的C指南来产生类似的效果,但我仍然不确定如何实际执行它。

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将.wav数据解包到NumPy数组中,然后发送内置的NumPy-FFT函数,但我对如何处理我在这里的SDL流数据毫无头绪。


你想要的是短期的FFT。 您可以在执行FFT之前从流中收集样本的缓冲区,并将窗函数应用于样本。 然后您收集另一个缓冲区,保留来自第一个缓冲区的一些样本并追加新的样本。 重复,直到所有的数据已被处理。

由于您的输入数据是真实的,所以FFT是对称的,因此您只需要第一个N / 2 + 1复杂输出分档。 这些代表从DC到Fs / 2的频率。 以他们的大小和情节。 对每个FFT重复一次。

链接地址: http://www.djcxy.com/p/33827.html

上一篇: How can I perform a realtime FFT on SDL2 audio stream data

下一篇: I've got audio samples; how to play them correctly with the SDL?