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 스트림 데이터로 무엇을해야하는지에 대한 단서가있어 그 나는 여기있다.
거의 정확함. 설명 된 솔루션의 문제점은 윈도우 함수의 적용이 파괴적이라는 것입니다. "첫 번째 버퍼에서 일부 샘플 유지"라고 말하면 창 샘플을 유지합니다. 사실, 작은 겹침을 사용하면 창 함수가 거의 0 인 각 창 가장자리에 정확히 _ 대부분의 필터링 된 부분을 유지할 수 있습니다. 겹치는 창을 사용하는 경우 샘플을 복사 할 때 창 함수를 적용하는 것이 가장 좋습니다. 나는. 'auto * windowed = buffer * windowFunction' 대신'buffer * = windowFunction'을 사용합니다. – MSalters
당신 말이 맞아요. 나는 내 iPad 키보드에 이것을 입력하려고 할 때 세부 사항을 제공하는 데 꽤 불투명했다. 아직도, 그것의 중요한 세부 사항. 감사. – sizzzzlerz