2016-12-04 12 views
1

私はプログラミングの初心者です。 私の学校のためにプロジェクトを作らなければなりません。目標は、マイクでレコーディングを行い、ハイパスフィルターをかけてm4aファイルに保存することです。swift 3 FFT音の周波数を取得m4a

このサイトと他の多くのサイトでは、同じコードが多数見つかりましたが、すぐに3のコードが到着するとコードは機能しなくなりました。

AVAudioPlayerでマイクから出てくるものを録音して保存することから始めます。

私はmpcバッファでファイルを読みました。

フロート配列のバッファからデータを取得します。

最後に、私が見つけた例のようにFFTを適用します。

バッファのデータ(バッファから来るフロートのテーブル)を表示すると、何かが含まれています。

私のVDSPベクトルを表示すると、データが含まれています。

しかし、私がFFTを適用すると、リールと虚数部を含むVDSP出力の結果が "ナノ"値を返します。

ここでは、FFTの機能を理解していないため、resutatの「出力」に周波数が含まれているかどうか、またはそれを含むVDSPのパラメータの1つだけの場合はわかりません。

次に、これらの結果にフィルタを適用し、変更を加えてm4aファイルを再構成するために値を逆FFTに戻すことを考えました。

私の方法が偽であるか、それは私のコードであれば

// recupere le lien du fichier audio a analysé 
     let url = getDocumentsDirectory().appendingPathComponent("recording.m4a") 
     // lancé l'audio dans le core AVaudioFile 
     let audioFile = try! AVAudioFile(forReading: url) 

     // nombre de frame dans l'audio 
     let frameCount = UInt32(audioFile.length) 

     print("frame count\(frameCount)") 
     //remplis un buffer avec les information du son et le nombre de framme 
     let buffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: frameCount) 
     do { 
      //lecture de l'audio dans le buffer 
      try audioFile.read(into: buffer, frameCount:frameCount) 
      print("lecture ok") 
     } catch { 
      //lecture échouer 

     } 

     print(buffer.floatChannelData?.pointee ?? "aucune valeur float") 

     // printer le buffer de byte de l'audio 
     print("\n buffer: \n"); 
     for k in 1...frameCount 
     { 
      print("value buffer \(buffer.floatChannelData?.pointee[Int(k)])"); 
     } 


     // définit un fonction log2n 
     let log2n = UInt(round(log2(Double(frameCount)))) 

     // définit la taille de buffer final potentiel 
     let bufferSizePOT = Int(1 << log2n) 

     //crée une structure FFT 
     //Si zéro est renvoyé, la routine n'a pas réussi à allouer de stockage 
     let fftSetup = vDSP_create_fftsetup(log2n, Int32(kFFTRadix2)) 

     //print fft 
     print("valeur du fftSetup \(fftSetup)") 


     // create packed real input 
     // séparation des buffer en nombre réel et imaginaire : 

     var realp = [Float](repeating: 0.0, count: bufferSizePOT/2) 
     var imagp = [Float](repeating: 0.0, count: bufferSizePOT/2) 

     /* 
     print("\n real and image: \n"); 
     for k in 0..<realp.count 
     { 
     print("value real \(realp[k]) et value imaginaire \(imagp[k])"); 
     } 
     */ 

     // construit un vecteur double contenant les real et les imaginaire 
     var output = DSPSplitComplex(realp: &realp, imagp: &imagp) 

     buffer.floatChannelData?.withMemoryRebound(to: DSPComplex.self, capacity: bufferSizePOT/2) { 
      /* 
      Copie le contenu d'un vecteur complexe intercalé C vers un vecteur complexe divisé Z; Précision unique. 

      void vDSP_ctoz(const DSPComplex *__C, vDSP_Stride __IC, const DSPSplitComplex *__Z, vDSP_Stride __IZ, vDSP_Length __N); 
      Paramètres 
      __C 
      Vecteur d'entrée complexe entrelacé à simple précision. 
      __IC 
      Stride pour C; Doit être un nombre pair. 
      __Z 
      Vecteur de sortie complexe à division simple. 
      za 
      Stride pour Z. 
      __N 
      Le nombre d'éléments à traiter. 

      */ 
      dspComplexStream in vDSP_ctoz(dspComplexStream, 2, &output, 1, UInt(bufferSizePOT/2)) 
     } 

     /* 
     calcul la série de fourier discrette du domaine temporel ver le domaine fréquentielle 
     paramètre : 

     func vDSP_fft_zrip(_ __Setup: 
     - --FFTSetup: l'objet FFTsetup 
     _ __C:   pointeur sur le vecteur complex de sortie 
     _ __IC:  pas entre les elements de --C, (a 1 pour des meilleures performance) 
     _ __Log2N:  Il base 2 exposant du nombre d'éléments à traiter. Par exemple, pour traiter 1024 éléments, 
         spécifiez 10 pour le paramètre Log2N. 
     _ __Direction: FFTDirection : donne la direction de la discretisations. 
         time domain to the frequency domain = (forward). 
         frequency domain to the time domain (inverse). 
     )*/ 
     vDSP_fft_zrip(fftSetup!, &output, 1, log2n, Int32(FFTDirection(FFT_FORWARD))) 


     print("\nSpectrum:\n"); 
     for i in 0..<realp.count 
     { 
      print("value de i \(i), réel : \(output.realp[i]), imaginaire : \(imagp[i])"); 
     } 

     var fft = [Float](repeating:0.0, count:Int(bufferSizePOT/2)) 
     let bufferOver2: vDSP_Length = vDSP_Length(bufferSizePOT/2) 

     vDSP_zvmags(&output, 1, &fft, 1, bufferOver2) 
     for i in 0..<bufferSizePOT/2 
     { 
      print("value de buff2 \(fft[i])"); 
     } 
     // termine le processus FFT 
     vDSP_destroy_fftsetup(fftSetup) 

そのEDIT場合、あなたは私に説明できる場合は、次のフィルタをローパスとジュスト遊び歌と

engine = AVAudioEngine() 
     player = AVAudioPlayerNode() 
     player.volume = 1.0 

     let path = Bundle.main.path(forResource: "audio10to1000", ofType: "wav")! 
     let url = NSURL.fileURL(withPath: path) 

     let file = try? AVAudioFile(forReading: url) 

     var mainMixer = AVAudioMixerNode() 

     mainMixer = engine.mainMixerNode 

     engine.attach(player) 

     EQNode = AVAudioUnitEQ(numberOfBands: 1) 




     var filterParams = EQNode.bands[0] as AVAudioUnitEQFilterParameters 

     filterParams.filterType = .lowPass 
     filterParams.frequency = 500.0 
     filterParams.bypass = false 
     engine.attach(EQNode) 


     engine.connect(player, to: EQNode, format: file?.processingFormat) 
     engine.connect(EQNode, to: mainMixer, format: file?.processingFormat) 


     // engine.connect(player, to: mainMixer, format: file?.processingFormat) 

     player.scheduleFile(file!, at: nil, completionHandler: nil) 

     engine.prepare() 
     do { 
      try engine.start() 
     } catch _ { 
      print("******************* erreur *************") 
     } 

     player.play() 
+1

は、この典型的なフィルタ応答from Wikipediaを参照してください。 'AVAudioUnitEQ'のためのGoogle。あなた自身で実装したい場合は、まずFIRまたはIIRソリューションに進んでください:https://en.wikipedia.org/wiki/Low-pass_filter楽しいことを! – shallowThought

+0

hiii ご協力いただきありがとうございます。私はAVAudioUnitEQを使用するのに苦労しました。それがmixernodeで使用するすべてのエフェクト(例のスピッチ)はうまく動作します。 Eqノードは機能しません。それは私のコードです: 3日後には何もしません... –

+0

変更することはありません...あなたの助けをもう一度お願いします 私は理解していることを確かめてください。 500Hzのローパスフィルタを使用するとき。私のオーディオが10hzで始まり10hで1000hzで終了する生成用の曲であれば、半分の時間でもう何も聞こえませんか? EQのgainGlobalを変更すると、filterParamsのゲインは変わりません。 –

答えて

1

あなたのコードをいけない仕事は働いている。あなたの設定はあなたのニーズに合っていません。

  • セットfilterParams.gain = -96.0(mininimal可能値)

  • ローパスフィルタ無しbandwidthを有していない、それを削除します。カットオフより上の100%の切断(ローパスフィルタの結果に

    • filterParams.frequency = 100.0

    あなたの期待:より多くのラジカルの結果は最初の100 Hzにカットオフ周波数を設定するため

周波数)はフィルタの現実に合わない。実装(アルゴリズムと順序の使用)によっては、フィルタが多かれ少なかれカットオフになります。あなたはハイカットフィルタを適用するためにFFTを必要としない

+0

こんにちは、申し訳ありませんが、もう一度あなたの助けが必要です。私は、オーディオのマグニチュードタブを持っています。私は必要なすべてのフィルタを適用していました。しかし、騒音が始まり、終わったときに、私のオーディオでどのように時間をとることができるのか分かりません。 アイデアはありますか? –

+0

振幅(音量値)がスレッショルドを超えたときに、あなたがしたいことを理解する方法がわかります。私はこの権利を得ましたか?あなたが実際に聴覚/聴音を停止するとき。 – shallowThought

+0

基本的に、私が助けが必要なのは、サンプル内の特定のサウンドを拾うことです。私が探している情報は、サンプル内のそのサウンドが時間単位(ms、sなど)で始まり、終了する時刻です。 私のサンプルは、呼吸器を服用している人の記録音です。私は周囲の騒音を減衰させるので、人が薬を飲んでいる部分だけを得ることができます。その人が薬を飲んだり、音が止まったりすると、タイムスタンプが欲しい。 –

関連する問題