2017-06-02 2 views
0

Je souhaite séparer les fréquences basses, moyennes et hautes du fichier .wav. pour cela j'ai utilisé FFT pour convertir les données du domaine temporel au domaine fréquentiel.Comment séparer la fréquence d'un fichier audio (.wav)

Code

pour la lecture du fichier et l'application de transformée de Fourier rapide avec l'aide de NAudio est comme

OpenFileDialog file = new OpenFileDialog(); 
     file.ShowDialog(); 
     WaveFileReader reader = new WaveFileReader(file.FileName); 
     int samepleRate = reader.WaveFormat.SampleRate; 
     double ts = 1.0/samepleRate; 
     int _fftLength = 4096; 
     double time = reader.TotalTime.TotalSeconds; 
     int channels = reader.WaveFormat.Channels; 
     int _m = (int)Math.Log(_fftLength, 2.0); 
     float fileSize = (float)reader.Length/1048576; 
     if (fileSize < 2) 
      window = 8; 
     else if (fileSize > 2 && fileSize < 4) 
      window = 16; 
     else if (fileSize > 4 && fileSize < 8) 
      window = 32; 
     else if (fileSize > 8 && fileSize < 12) 
      window = 128; 
     else if (fileSize > 12 && fileSize < 20) 
      window = 256; 
     else if (fileSize > 20 && fileSize < 30) 
      window = 512; 
     else 
      window = 2048; 


     byte[] readBuffer = new byte[reader.Length]; 

     reader.Read(readBuffer,0,readBuffer.Length); 
     float[] data = ConvertByteToFloat(readBuffer,readBuffer.Length);    

     Complex[] fftBuffer= new Complex[_fftLength]; 
     int fftPos = 0; 
     for (int i = 0; i < _fftLength; i++) 
     { 
      fftBuffer[fftPos].X = (float)(data[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i,_fftLength)); 
      fftBuffer[fftPos].Y = 0; 
      fftPos++; 
     } 
     NAudio.Dsp.FastFourierTransform.FFT(true, _m, fftBuffer); 

private float[] ConvertByteToFloat(byte[] array, int length) 
    { 
     int samplesNeeded = length/4; 
     float[] floatArr = new float[samplesNeeded]; 

     for (int i = 0; i < samplesNeeded; i++) 
     { 
      floatArr[i] = (float)BitConverter.ToInt32(array, i * 4); 
     } 

     return floatArr; 
    } 

//ZedGraph code 
     GraphPane myPane = zedGraphControl1.GraphPane; 
     myPane.Title.Text = "Frequency domain output"; 
     PointPairList list1 = new PointPairList(); 
     PointPairList list2 = new PointPairList(); 
     for (int i = 0; i < fftBuffer.Length; i++) 
     { 
      list1.Add(i, fftBuffer[i].Y); 
     } 
     list2.Add(0, 0); 
     //list2.Add(time, 0);uncomment this and remove below to plot time domain graph 
     var maxIndex = -1; 
     var maxValue = 0f; 
     for (var j = 0; j < _fftLength/2; j++) 
     { 
      var value = fftBuffer[j].X * fftBuffer[j].X 
       + fftBuffer[j].Y * fftBuffer[j].Y; 

      if (value > maxValue) 
      { 
       maxIndex = j; 
       maxValue = value; 
      } 
      var freq = maxIndex == -1 ? 0 
      : (ushort)Math.Round((_fftLength - maxIndex)/(_fftLength * ts)); 
      list2.Add(freq, 0); 
     } 
     if (myCurve1 != null && myCurve2 != null) 
     { 
      myCurve1.Clear(); 
      myCurve2.Clear(); 
     } 

     myCurve1 = myPane.AddCurve(null, list1, Color.Blue, SymbolType.None); 
     myCurve1.IsX2Axis = true; 
     myCurve2 = myPane.AddCurve(null, list2, Color.Black, SymbolType.None); 
     myPane.XAxis.Scale.MaxAuto = true; 
     myPane.XAxis.Scale.MinAuto = true; 
     myPane.YAxis.Title.Text = "Amplitude"; 
     myPane.XAxis.Title.Text = "Frequency"; 
     zedGraphControl1.AxisChange(); 
     zedGraphControl1.Invalidate(); 

Maintenant, je suis les données de domaine de fréquence et je l'ai tracé sur ZedGraph avec une amplitude sur l'axe Y et fréquence sur X -axe. Maintenant j'ai des données complexes comme FFT avec moi, mais comment séparer ci-dessous les fréquences énumérées à partir de données données et comment générer ou lire un fichier de cette fréquence particulière.

  1. bas - 20Hz à 500Hz
  2. Mid - 500 Hz à 4 kHz
  3. à 20KHz 4KHz High-

Tout conseil ou d'orientation serait grandement apprécié .. !!

Répondre

0

Si vous souhaitez simplement filtrer un flux audio, vous devez adopter une approche coûteuse. Les FFT sont parfaits pour identifier les signatures spectrales. Mais si vous voulez aller à temps de fréquence et de temps en temps, c'est beaucoup de nombre croquant (et vous n'aurez probablement pas aimé ce que vous entendez). Si vous conservez le chemin actuellement indiqué, vous devrez effectuer une certaine forme de masquage dans le domaine fréquentiel, puis le convertir à nouveau. Quand vous convertissez en temps réel (un vrai produit) ça va sonner "sale" (vous aurez besoin d'implémenter une forme imaginaire à une fusion réelle). Dans votre code, vous formez une grandeur au carré pour revenir à une série en temps réel (notez - cela vous donnera un signal rectifié - ce qui devrait sembler hissy).

Si vous souhaitez isoler une bande particulière, commencez par une forme de filtre passe-bande FIR. Si vous voulez entendre le résultat en cours de développement, consultez des exemples d'utilisation de la classe Android AudioTrack.

+0

Mon but de séparer ces fréquences à utiliser dans une application de mixage (pour faire du mixage dj). J'ai essayé une fonction de filtre passe-bas et passe-haut dans C# mais pas sûr si les données que je reçois après cette fonction de filtre est valide ou non j'ai aussi essayé de créer un fichier .wav à partir de données filtrées avec n'importe quel lecteur audio. enregistrer .wav et lire l'audio n'est pas ma cible mais doit vérifier si les données sont valides ou non. J'ai juste besoin d'un tableau de données filtré avec des positions de lecture (essentiellement le domaine temporel) pour pouvoir mixer deux chansons avec leur basse => basse, moyenne => moyenne et haute => haute. – Nitin