2015-10-11 28 views
8

FFTオーディオファイルでAccelerateフレームワークを使用して周波数を検索しようとしています。 'スペクトルは' ''、 'INF' または 'ナン'、および 'のいずれかですから、大きさ、がSpectrogram from AVAudioPCMBuffer using Accelerate framework in SwiftSwift FFT - 複雑な分割問題

:私はこの質問からコードを(おそらく間違っている)ようになってきました 'と' imag 'の複合スプリットのコンポーネントが同様の結果を出力します。これはのように問題の原因であることを示す:「大きさ= SQRT(POW(リアル、2)+ POW(IMAG、2)」私が間違っているなら、私を修正して、私は残りの部分だと思います

なぜ私はこれらの結果を受け取り、どのように修正することができますか(分割コンポーネントはどうなりますか)、何が間違っていますか?私は非常に新しいですFFTとサンプリングして、オーディオファイルのためにこれを設定する方法の手がかりを得ていないので、どんな助けも非常に高く評価されるでしょう。

私が使用しているコードはここにあります:

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

    let buffer = AVAudioPCMBuffer(PCMFormat: fileFormat, frameCapacity: frameCount) 
    let audioEngine = AVAudioEngine() 
    let playerNode = AVAudioPlayerNode() 
    audioMixerNode = audioEngine.mainMixerNode 

    let bufferSize = Int(frameCount) 
    let channels: NSArray = [Int(buffer.format.channelCount)] 
    let channelCount = channels.count 
    let floats1 = [Int(buffer.frameLength)] 
    for var i=0; i<channelCount; ++i { 
     channelSamples.append([]) 
     let firstSample = buffer.format.interleaved ? i : i*bufferSize 
     for var j=firstSample; j<bufferSize; j+=buffer.stride*2 { 
      channelSamples[i].append(DSPComplex(real: buffer.floatChannelData.memory[j], imag: buffer.floatChannelData.memory[j+buffer.stride])) 
     } 
    } 

    // connect node 
    audioEngine.attachNode(playerNode) 
    audioEngine.connect(playerNode, to: audioMixerNode, format: playerNode.outputFormatForBus(0)) 

    // Set up the transform 
    let log2n = UInt(round(log2(Double(bufferSize)))) 
    let fftSetup = vDSP_create_fftsetup(log2n, Int32(kFFTRadix2)) 

    // Create the complex split value to hold the output of the transform 
    // why doesn't this work? 
    var realp = [Float](count: bufferSize/2, repeatedValue: 0) 
    var imagp = [Float](count: bufferSize/2, repeatedValue: 0) 
    var output = DSPSplitComplex(realp: &realp, imagp: &imagp) 

    vDSP_ctoz(UnsafePointer(channelSamples), 2, &output, 1, UInt(bufferSize/2)) 

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

    // Convert the complex output to magnitude 
    var fft = [Float](count:Int(bufferSize/2), repeatedValue:0.0) 
    let bufferOver2: vDSP_Length = vDSP_Length(bufferSize/2) 
    vDSP_zvmags(&output, 1, &fft, 1, bufferOver2) 

    var spectrum = [Float]() 
    for var i=0; i<bufferSize/2; ++i { 
     let imag = output.imagp[i] 
     let real = output.realp[i] 
     let magnitude = sqrt(pow(real,2)+pow(imag,2)) 
     spectrum.append(magnitude) } 

    // Release the setup 
    vDSP_destroy_fftsetup(fftSetup) 

答えて

3

あなたのコードに問題がいくつかありました:の終わりを超えて読んでいた

  • channelSamplesが間違って
  • vDSP_fft_zrip
  • を充填したオーディオファイルのサンプルでは読んでいないし、

    1. は、アレイ。それは2^log2nサンプル
    2. vDSP_fft_zripの出力がpackedであり、あなたの計算はアンパック

      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) 
      
    を期待して期待してい