Я прочитал эти вопросы:IOS FFT Розыгрыш спектр
Using the Apple FFT and Accelerate Framework
How do I set up a buffer when doing an FFT using the Accelerate framework?
iOS FFT Accerelate.framework draw spectrum during playback
Все они описывают, как настроить FFT с рамками ускорения. С их помощью я смог настроить fft и получить базовый анализатор спектра. Прямо сейчас, я показываю все значения, которые я получил от fft. Тем не менее, я хочу показать только 10-15 или переменное число баров, пересчитывающих определенные частоты. Точно так же как измеритель уровня iTunes или WinAmp. 1. Нужно ли мне усреднять значения амплитуд из диапазона частот? Или они просто показывают вам величину для конкретной полосы частот? 2. Кроме того, мне нужно преобразовать значения величин в db? 3. Как сопоставить мои данные с определенным диапазоном. Я сопоставляю с диапазоном max db для своих битов бит? Получение максимального значения для бина приведет к максимальному отображению значений перехода.
Мой RenderCallback:
static OSStatus PlaybackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
UInt32 maxSamples = kAudioBufferNumFrames;
UInt32 log2n = log2f(maxSamples); //bins
UInt32 n = 1 << log2n;
UInt32 stride = 1;
UInt32 nOver2 = n/2;
COMPLEX_SPLIT A;
float *originalReal, *obtainedReal, *frequencyArray, *window, *in_real;
in_real = (float *) malloc(maxSamples * sizeof(float));
A.realp = (float *) malloc(nOver2 * sizeof(float));
A.imagp = (float *) malloc(nOver2 * sizeof(float));
memset(A.imagp, 0, nOver2 * sizeof(float));
obtainedReal = (float *) malloc(n * sizeof(float));
originalReal = (float *) malloc(n * sizeof(float));
frequencyArray = (float *) malloc(n * sizeof(float));
//-- window
UInt32 windowSize = maxSamples;
window = (float *) malloc(windowSize * sizeof(float));
memset(window, 0, windowSize * sizeof(float));
// vDSP_hann_window(window, windowSize, vDSP_HANN_DENORM);
vDSP_blkman_window(window, windowSize, 0);
vDSP_vmul(ioBuffer, 1, window, 1, in_real, 1, maxSamples);
//-- window
vDSP_ctoz((COMPLEX*)in_real, 2, &A, 1, maxSamples/2);
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);
float scale = (float) 1.0/(2 * n);
vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2);
vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2);
vDSP_ztoc(&A, 1, (COMPLEX *) obtainedReal, 2, nOver2);
vDSP_zvmags(&A, 1, obtainedReal, 1, nOver2);
Float32 one = 1;
vDSP_vdbcon(obtainedReal, 1, &one, obtainedReal, 1, nOver2, 0);
for (int i = 0; i < nOver2; i++) {
frequencyArray[i] = obtainedReal[i];
}
// Extract the maximum value
double fftMax = 0.0;
vDSP_maxmgvD((double *)obtainedReal, 1, &fftMax, nOver2);
float max = sqrt(fftMax);
}
Играя музыку, я получаю значения от -96db до 0дБ. Plotting точку на:
CGPointMake(i, kMaxSpectrumHeight * (1 - frequencyArray[i]/-96.));
дает свой довольно округлый кривую:
Если я не конвертировать в БД можно построить путем умножения моего значения массива на 10000 и получить хорошие пики.
я делаю что-то совершенно неправильно? И как я могу показать переменное количество баров?
Просто интересно: но у вас есть окончательный код, который отображает бары? У меня возникают трудности с пониманием, куда идти от ответа ниже. – kezi