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.
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
Vous devez vous connecter pour publier un commentaire.
Je suis peut-être un peu tard pour répondre, mais nous sommes ici.
Vous y êtes presque. Vous avez juste besoin de fournir de l'amplitude des nombres complexes que FFT retourne au lieu de la valeur de X.
Donc dans la boucle for, au lieu de cela:
ce faire:
Cheers!
OriginalL'auteur max_force
Je suppose que c'est une norme IEEE float... ce n'est pas expliqué dans MSDN Ici
J'ai essayé de convertir mon tableau d'octets dans un array Int32 (coulé en float) mais le résultat est pire :
OriginalL'auteur Floyd
J'ai un travail de l'analyseur de spectre à l'aide du code à une autre question. C'est un très brut de version, mais vous serez capable de l'utiliser avec des modifications mineures.
Je n'ai aucune idée de ce qui se fait, le problème avec votre code, mais au moins le code fourni est de travailler pour moi. Le problème est ailleurs, si vous avez encore un mauvais spectre lors de son utilisation.
OriginalL'auteur Typhus