2017-02-15 1 views
6

J'ai réussi à obtenir avec succès un flux de données audio allant vers un périphérique de sortie (haut-parleur) en utilisant NAudio:Convertir flux audio à la fréquence

private void OnDataAvailable(object sender, WaveInEventArgs e) 
     { 
      var buffer = e.Buffer; 
      var bytesRecorded = e.BytesRecorded; 
      Debug.WriteLine($"Bytes {bytesRecorded}"); 

Et l'exemple de sortie:

Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 23040 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 
Bytes 19200 

Je transforme ensuite (FFT) à cette valeurs x et y en utilisant https://stackoverflow.com/a/20414331:

var buffer = e.Buffer; 
      var bytesRecorded = e.BytesRecorded; 
      //Debug.WriteLine($"Bytes {bytesRecorded}"); 
      var bufferIncrement = _waveIn.WaveFormat.BlockAlign; 

      for (var index = 0; index < bytesRecorded; index += bufferIncrement) 
      { 
       var sample32 = BitConverter.ToSingle(buffer, index); 
       _sampleAggregator.Add(sample32); 
      } 

Avec un exemple de sortie de:

x: -9.79634E-05, y: -9.212703E-05 
x: 6.897306E-05, y: 2.489315E-05 
x: 0.0002080683, y: 0.0004317867 
x: -0.0001720883, y: -6.681971E-05 
x: -0.0001245111, y: 0.0002880402 
x: -0.0005751926, y: -0.0002682915 
x: -5.280507E-06, y: 7.297558E-05 
x: -0.0001143928, y: -0.0001156801 
x: 0.0005231025, y: -0.000153206 
x: 0.0001011164, y: 7.681748E-05 
x: 0.000330695, y: 0.0002293986 

Je ne sais pas si cela est même possible ou si je suis juste mal compris ce que le courant revient, mais je voudrais obtenir la fréquence du flux audio afin de faire des choses avec Philips Hue. Les valeurs x, y ci-dessus sont très petites à utiliser dans l'espace colorimétrique CIE. Suis-je en train de faire quelque chose de mal ou suis-je complètement incompréhension de ce que les données sont dans le tampon dans OnDataAvailable?

Merci!

Edit:

J'ai modifié mon code OnDataAvailable basé sur les commentaires et le tutoriel pour le programme Autotune d'être le ci-dessous:

private void OnDataAvailable(object sender, WaveInEventArgs e) 
     { 
      var buffer = e.Buffer; 
      float sample32 = 0; 

      for (var index = buffer.Length > 1024 ? buffer.Length - 1024 : buffer.Length; index < e.BytesRecorded; index += 2) 
      { 
       var sample = (short) ((buffer[index + 1] << 8) | buffer[index + 0]); 
       sample32 = sample/32768f; 
       Debug.WriteLine(sample32); 
       LightsController.SetLights(Convert.ToByte(Math.Abs(sample32) * 255)); 
       _sampleAggregator.Add(sample32); 
      } 
      var floats = BytesToFloats(buffer); 

      if (sample32 != 0.0f) 
      { 
       var pitchDetect = new FftPitchDetector(sample32); 
       var pitch = pitchDetect.DetectPitch(floats, floats.Length); 
       Debug.WriteLine($"Pitch {pitch}"); 
      } 
     } 

L'espoir est que je n'utilise que la dernière série de éléments du buffer car il ne semble pas se dégager et je ne suis intéressé que par le dernier ensemble de données disponible afin d'obtenir la fréquence de l'audio actuel. Cependant, je reçois encore une exception d'index ocassionally lorsque la méthode DetectPitch est appelée. Où vais-je mal? J'espérais utiliser la fréquence pour changer la couleur et la luminosité des ampoules de teinte.

+1

Avez-vous vu ce post: http://stackoverflow.com/questions/15009084/implementing-fftpitchdetector-in-c-sharp? –

+0

@DavidTansey Je n'ai pas. Se penchera sur cela et rendra compte. –

+0

@DavidTansey J'ai modifié mon code OnDataAvailable pour qu'il corresponde et transmette "floats" et "floats.Length" à pitchDetect.DetectPitch mais j'obtiens une exception d'index hors plage à 'SmbPitchShift.smbFft (fftBuffer, frames, -1);' et s'il est commenté, à 'float real = fftBuffer [bin * 2]; Des idées? –

Répondre

1

Utilisez

fPeak = SamplingRate * BinNumberOfPeak/FFTLength ;

+0

Qu'est ce que "BinNumberOfPeak"? Et où est "FFTLength"? Votre réponse ne fournit pas beaucoup de détails. Je voudrais comprendre ce que les données que NAudio renvoie représente ainsi que comment obtenir la fréquence (s) à partir des données? –

+0

FFT Longueur = 4096 (= N nombre de points de calcul) et numéro de bac est index dans le tableau FFT 0, 1, 2. Le calcul de crête de fréquence est délicat sur la base de spectres unilatéraux ou bilatéraux. Vous devez suivre [le point 4 ici] (http://www.gaussianwaves.com/2014/07/how-to-plot-fft-using-matlab-fft-of-basic-signals-sine-and-cosine-waves /) pour comprendre des calculs authentiques. – SACn