且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Swift FFT - 复杂分裂问题

更新时间:2022-01-02 23:00:43

您的代码存在以下几个问题:

There were a couple of problems with your code:


  1. 您没有阅读音频文件样本

  2. channelSamples包装不正确

  3. vDSP_fft_zrip 正在超出数组末尾读取。它预计2 ^ log2n样本

  4. vDSP_fft_zrip 的输出是已打包并且您的计算结果是unpacked

  1. you weren't reading in the audio file samples
  2. channelSamples was packed incorrectly
  3. vDSP_fft_zrip was reading beyond the end of the array. it expects 2^log2n samples
  4. vDSP_fft_zrip's output is packed and your calculations expect unpacked

let fileURL:NSURL = NSBundle.mainBundle().URLForResource("foo", withExtension: "mp3")!
let audioFile = try!  AVAudioFile(forReading: fileURL)
let frameCount = UInt32(audioFile.length)

let buffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: frameCount)
do {
    try audioFile.readIntoBuffer(buffer, frameCount:frameCount)
} catch {

}
let log2n = UInt(round(log2(Double(frameCount))))

let bufferSizePOT = Int(1 << log2n)

// Set up the transform
let fftSetup = vDSP_create_fftsetup(log2n, Int32(kFFTRadix2))

// create packed real input
var realp = [Float](count: bufferSizePOT/2, repeatedValue: 0)
var imagp = [Float](count: bufferSizePOT/2, repeatedValue: 0)
var output = DSPSplitComplex(realp: &realp, imagp: &imagp)

vDSP_ctoz(UnsafePointer<DSPComplex>(buffer.floatChannelData.memory), 2, &output, 1, UInt(bufferSizePOT / 2))

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


// you can calculate magnitude squared here, with care 
// as the first result is wrong! read up on packed formats
var fft = [Float](count:Int(bufferSizePOT / 2), repeatedValue:0.0)
let bufferOver2: vDSP_Length = vDSP_Length(bufferSizePOT / 2)
vDSP_zvmags(&output, 1, &fft, 1, bufferOver2)


// Release the setup
vDSP_destroy_fftsetup(fftSetup)