Мне кажется, что есть проблема в преобразовании в комплексный ввод для БПФ. vDSP_ctoz()
разбивает буфер, в котором действительные и мнимые компоненты чередуются на два буфера, один действительный и один мнимый. Ваш ввод для этой функции, кажется, просто реальные данные, которые были преобразованы в COMPLEX
. Это означает, что ваш входной буфер в vDSP_ctoz()
только вдвое дольше необходимого, и некоторые ненужные данные, превышающие размер буфера, преобразуются.
Вам нужно либо создать sampleOut
, чтобы иметь длину 2*n
, и установить любое другое значение (действительные части) или, что еще лучше, вы можете обойти vDSP_ctoz()
и напрямую скопировать свои входные данные в A.realp
и установите A.imagp
в нули. vDSP_ctoz()
требуется только при взаимодействии с источником, который создает чередующиеся сложные данные.
Редактировать
Хорошо, я думаю, что ошибся в своем первом предложении, так как документация vDSP говорит, что реальный ввод реального-сложного fft на месте должен быть отформатирован в формат разделения сложного так, чтобы imagp
содержал четные примеры. и realp
содержит нечетные выборки. На самом деле я не использовал библиотеку vDSP, но я знаком со многими другими библиотеками FFT и упустил эту деталь.
Вы должны быть в состоянии найти пики, используя A.realp
после вызова vDSP_zvmags(&A, 1, A.realp, 1, nOver2);
. В этой точке A.realp
должен содержать квадрат величины выходного сигнала БПФ, который является скалярным. Если вы собираетесь выполнить масштабирование, это следует сделать до операции mag2, но это может не понадобиться, если вы просто ищете пики.
Чтобы получить реальные частоты, представленные на выходе FFT, используйте следующую формулу:
F = (i * Fs) / N, i=0,1,...,N/2
где
i
- индекс выходного буфера FFT
Fs
- частота дискретизации звука
N
это длина БПФ
так что ваш расчет может выглядеть так:
float frequency = (peakIndex * 44100) / n;
Имейте в виду, что vDSP возвращает только первую половину входного спектра для реального ввода, поскольку вторая половина является избыточной. Таким образом, выход FFT представляет частоты от 0
до Fs/2
.
Еще одно замечание: я не знаю, будет ли ваш алгоритм нахождения пиков работать очень хорошо, поскольку выходной сигнал БПФ не будет плавным и часто будет много колебаний. Вы просто берете первый образец, где два соседних образца ниже. Если вы просто хотите найти один пик, было бы лучше просто найти максимальную величину по всему выходному сигналу. Если вы хотите найти несколько пиков, вам придется сделать что-то более сложное.