Analyseur de spectre avec NAudio & WPFSoundVisualizationLib

Je suis en train de travailler sur un C#4.0/WPF en temps Réel de l'Analyseur de Spectre (en tant que base d'un autre projet). J'utilise NAudio dernière version afin d'obtenir une sortie en temps réel sur la carte son, et WPFSoundVisualizationLib (http://wpfsvl.codeplex.com/) pour l'Analyseur de Spectre Contrôle WPF. Avec cette incroyable d'outils, le travail est presque terminé, mais il ne fonctionne pas bien 🙁

J'ai un Spectre fonctionnel, mais les informations ne sont pas des droits, et je ne comprends pas d'où le problème viens de... (j'ai pu comparer mon Spectre avec Equalify, un Spectre/égaliseur pour Spotify, et je n'ai pas le même comportement)

C'est ma classe principale :

using System;
using System.Windows;
using WPFSoundVisualizationLib;
namespace MySpectrumAnalyser
{
public partial class MainWindow : Window
{
private RealTimePlayback _playback;
private bool _record;
public MainWindow()
{
InitializeComponent();
this.Topmost = true;
this.Closing += MainWindow_Closing;
this.spectrum.FFTComplexity = FFTDataSize.FFT2048;
this.spectrum.RefreshInterval = 60;
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (this._record)
{
this._playback.Stop();
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (this._playback == null)
{
this._playback = new RealTimePlayback();
this.spectrum.RegisterSoundPlayer(this._playback);
}
if (!this._record)
{
this._playback.Start();
this.Dispatcher.Invoke(new Action(delegate
{
this.btnRecord.Content = "Stop";
}));
}
else
{
this._playback.Stop();
this.Dispatcher.Invoke(new Action(delegate
{
this.btnRecord.Content = "Start";
}));
}
this._record = !this._record;
}
}
}

Et mon bouclage de l'analyseur (qui implémente ISpectrumPlayer pour l'utilisation avec le WPFSoundVisualizationLib de contrôle du Spectre).

LoopbackCapture hérite NAudio.CoreAudioApi.WasapiCapture.

Données reçues Wasapi est un tableau d'octets (32 bits PCM, 44.1 kHz, 2 canaux, 32 bits par échantillon)

using NAudio.Dsp;
using NAudio.Wave;
using System;
using WPFSoundVisualizationLib;
namespace MySpectrumAnalyser
{
public class RealTimePlayback : ISpectrumPlayer
{
private LoopbackCapture _capture;
private object _lock;
private int _fftPos;
private int _fftLength;
private Complex[] _fftBuffer;
private float[] _lastFftBuffer;
private bool _fftBufferAvailable;
private int _m;
public RealTimePlayback()
{
this._lock = new object();
this._capture = new LoopbackCapture();
this._capture.DataAvailable += this.DataAvailable;
this._m = (int)Math.Log(this._fftLength, 2.0);
this._fftLength = 2048; //44.1kHz.
this._fftBuffer = new Complex[this._fftLength];
this._lastFftBuffer = new float[this._fftLength];
}
public WaveFormat Format
{
get
{
return this._capture.WaveFormat;
}
}
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] = BitConverter.ToSingle(array, i * 4);
}
return floatArr;
}
private void DataAvailable(object sender, WaveInEventArgs e)
{
//Convert byte[] to float[].
float[] data = ConvertByteToFloat(e.Buffer, e.BytesRecorded);
//For all data. Skip right channel on stereo (i += this.Format.Channels).
for (int i = 0; i < data.Length; i += this.Format.Channels)
{
this._fftBuffer[_fftPos].X = (float)(data[i] * FastFourierTransform.HannWindow(_fftPos, _fftLength));
this._fftBuffer[_fftPos].Y = 0;
this._fftPos++;
if (this._fftPos >= this._fftLength)
{
this._fftPos = 0;
//NAudio FFT implementation.
FastFourierTransform.FFT(true, this._m, this._fftBuffer);
//Copy to buffer.
lock (this._lock)
{
for (int c = 0; c < this._fftLength; c++)
{
this._lastFftBuffer[c] = this._fftBuffer[c].X;
}
this._fftBufferAvailable = true;
}
}
}
}
public void Start()
{
this._capture.StartRecording();
}
public void Stop()
{
this._capture.StopRecording();
}
public bool GetFFTData(float[] fftDataBuffer)
{
lock (this._lock)
{
//Use last available buffer.
if (this._fftBufferAvailable)
{
this._lastFftBuffer.CopyTo(fftDataBuffer, 0);
this._fftBufferAvailable = false;
return true;
}
else
{
return false;
}
}
}
public int GetFFTFrequencyIndex(int frequency)
{
int index = (int)(frequency / (this.Format.SampleRate / this._fftLength / this.Format.Channels));
return index;
}
public bool IsPlaying
{
get { return true; }
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
}
}

GetFFTData est appelé par le contrôle WPF tous les 60ms pour la mise à jour du Spectre.

Ce qui ne fonctionne pas? Les messages d'erreur? Si oui, laquelle et où qu'ils se produisent? Vous devez décrire l'erreur(s) plus en détail.
Vous avez vraiment besoin de dire ce qui vous attend à obtenir vs ce que vous avez ou personne ne sera en mesure de vous aider.
Savez-vous ce que le type de donnée est en avant de la convertir à float? Si elle n'est pas float déjà, je ne sais pas si votre fonction de conversion fonctionne.
Je n'ai pas toutes les erreurs, comme je l'ai dit, "j'ai un Spectre fonctionnel, mais les informations ne sont pas des droits". Je compare mon Spectre avec Equalify (un Spectre/égaliseur) pour Spotify) et je n'ai pas le même comportement.
Oups, Entrez envoyer immédiatement le commentaire... je reçois un tableau d'octets dans le DataAvailable méthode, et je la convertir en float[] avec la ConvertByteToFloat méthode. Le tableau d'octets représente le dernier tampon lus en Wasapi (PCM 16bits / 44.1 KHhz je pense)

OriginalL'auteur Floyd | 2012-11-15