swift FFT chunk audio file to get Amplitude

1.1k Views Asked by At

i need your help. in want to use the FFT on my audio file. i want to cut my audio file in more little buffer array and use my FFT with all sub buffer.

why ?? because i need to know and see (with plot data) how my fréquence have particularity. i want to know, how a noise start in my audio file.

that is my FFT code . i dont know what im doing wrong.

thx for your help

EDITING CODE

func FFT (buffer: AVAudioPCMBuffer){

    let frameCount = buffer.frameCapacity
    let log2n = UInt(round(log2(Double(frameCount))))

    print (" log2n \(log2n)");

    let bufferSizePOT = Int(1 << log2n)

    print (" bufferSizePot \(bufferSizePOT)");
    let inputCount = bufferSizePOT / 2
    let fftSetup = vDSP_create_fftsetup(log2n, Int32(kFFTRadix2))

    var realp = [Float](repeating: 0, count: inputCount)
    var imagp = [Float](repeating: 0, count: inputCount)
    var output = DSPSplitComplex(realp: &realp, imagp: &imagp)


    let windowSize = bufferSizePOT
    var transferBuffer = [Float](repeating: 0, count: windowSize)
    var window = [Float](repeating: 0, count: windowSize)

    vDSP_hann_window(&window, vDSP_Length(windowSize), Int32(vDSP_HANN_NORM))
    vDSP_vmul((buffer.floatChannelData?.pointee)!, 1, window,
              1, &transferBuffer, 1, vDSP_Length(windowSize))

    let temp = UnsafePointer<Float>(transferBuffer)

    temp.withMemoryRebound(to: DSPComplex.self, capacity: transferBuffer.count) { (typeConvertedTransferBuffer) -> Void in
        vDSP_ctoz(typeConvertedTransferBuffer, 2, &output, 1, vDSP_Length(inputCount))

    }

    // Do the fast Fourier forward transform, packed input to packed output
    vDSP_fft_zrip(fftSetup!, &output, 1, log2n, FFTDirection(FFT_FORWARD))


    //---------------------------------------------------


    var magnitudes = [Float](repeating: 0.0, count: inputCount)
    vDSP_zvmags(&output, 1, &magnitudes, 1, vDSP_Length(inputCount))

    var normalizedMagnitudes = [Float](repeating: 0.0, count: inputCount)
    vDSP_vsmul(sqrt(x: magnitudes), 1, [2.0 / Float(inputCount)],
               &normalizedMagnitudes, 1, vDSP_Length(inputCount))


    for f in 0..<normalizedMagnitudes.count
    {
        print("\(f), \(normalizedMagnitudes[f])")
    }


    vDSP_destroy_fftsetup(fftSetup)

}
1

There are 1 best solutions below

1
On

Basically, instead of making

frameCount = UInt32(audioFile.length)

you want a to use a much smaller for frameCount (such as 4096, for roughly 1/10th of a second of audio), and then loop through the audio file, reading and processing each smaller chunk of data of frameCount length (doing shorter windowed FFTs) separately, instead of processing the entire file in one huge FFT.

Note that when looping over the audio file sample data and doing a series of FFTs of the same length, you only need to do the fftSetup once.

If you want, you can vector sum sets of resulting magnitude vectors over a longer time period to reduce the time resolution and length of your printout. This is a form of Welch's method of spectral density estimation.