iOS FFT Accerelate.framework рисует спектр во время воспроизведения

ОБНОВЛЕНИЕ 2016-03-15

Пожалуйста, взгляните на этот проект: https://github.com/ooper-shlab/aurioTouch2.0-Swift. Он был перенесен на Swift и содержит все ответы, которые вы ищете, если вы пришли сюда.


Я провел много исследований и многое узнал о БПФ и Accelerate Framework. Но после нескольких дней экспериментов я немного расстроен.

Я хочу отображать частотный спектр аудиофайла во время воспроизведения на диаграмме. Для каждого временного интервала он должен показывать величину в дБ по оси Y (отображаемой красной полосой) для каждой частоты (в моем случае 512 значений), рассчитанной с помощью БПФ по оси X.

Результат должен выглядеть следующим образом: введите здесь описание изображения

Я заполняю буфер 1024 сэмплами, извлекая для начала только левый канал. Затем я делаю все эти вещи FFT.

Вот мой код:

Настройка некоторых переменных

- (void)setupVars  
{  
    maxSamples = 1024;

    log2n = log2f(maxSamples);  
    n = 1 << log2n;  

    stride = 1;  
    nOver2 = maxSamples/2;  

    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));

    setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2);  
}

Делаем БПФ. FrequencyArray — это просто структура данных, содержащая 512 значений с плавающей запятой.

- (FrequencyArry)performFastFourierTransformForSampleData:(SInt16*)sampleData andSampleRate:(UInt16)sampleRate   
{  
    NSLog(@"log2n %i n %i,  nOver2 %i", log2n, n, nOver2);

    // n = 1024
    // log2n 10
    // nOver2 = 512

    for (int i = 0; i < n; i++) {
        originalReal[i] = (float) sampleData[i];
    }

    vDSP_ctoz((COMPLEX *) originalReal, 2, &A, 1, nOver2);

    vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);

    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);

    FrequencyArry frequencyArray;

    for (int i = 0; i < nOver2; i++) {
        frequencyArray.frequency[i] = log10f(obtainedReal[i]); // Magnitude in db???
    }

    return frequencyArray;  
}

Вывод всегда выглядит странно, хотя кажется, что он движется в соответствии с музыкой.

Я рад, что зашел так далеко благодаря некоторым очень хорошим сообщениям, например: Использование Apple FFT и ускорение Framework

Но теперь я не знаю, что делать. Что мне не хватает?


person benjamin.ludwig    schedule 17.05.2012    source источник
comment
в каком формате ваши входные данные?   -  person hooleyhoop    schedule 17.05.2012


Ответы (1)


Во-первых, вы не применяете оконную функцию перед БПФ - это приведет к размытию спектра из-за спектральная утечка.

Во-вторых, вы просто используете реальную составляющую выходных бинов БПФ для вычисления величины в дБ - вам нужно использовать комплексную величину:

magnitude_dB = 10 * log10(re * re + im * im);
person Paul R    schedule 17.05.2012
comment
vDSP_zvmags(&A, 1, полученоReal, 1, nOver2); получить те же результаты - person Sergey Kopanev; 28.12.2012