Asked by:
Play output audio in Naudio

Question
-
Hi everyone!
I implement FFT with input audio from mic but when i play audio from mic with waveout the audio is breakdow and i can't speak it. This my code:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using NAudio.Wave; using NAudio.CoreAudioApi; namespace ScottPlotMicrophoneFFT { public partial class Form1 : Form { // MICROPHONE ANALYSIS SETTINGS private int RATE = 44100; // sample rate of the sound card private int BUFFERSIZE = (int)Math.Pow(2, 11); // must be a multiple of 2 public BufferedWaveProvider bufferedWaveProvider; // prepare class objects public BufferedWaveProvider bwp; public WaveOut player; public Form1() { InitializeComponent(); SetupGraphLabels(); StartListeningToMicrophone(); timerReplot.Enabled = true; } void AudioDataAvailable(object sender, WaveInEventArgs e) { bwp.AddSamples(e.Buffer, 0, e.BytesRecorded); } private void Form1_Load(object sender, EventArgs e) { } public void SetupGraphLabels() { scottPlotUC1.fig.labelTitle = "Microphone PCM Data"; scottPlotUC1.fig.labelY = "Amplitude (PCM)"; scottPlotUC1.fig.labelX = "Time (ms)"; scottPlotUC1.Redraw(); scottPlotUC2.fig.labelTitle = "Microphone FFT Data"; scottPlotUC2.fig.labelY = "Power (raw)"; scottPlotUC2.fig.labelX = "Frequency (Hz)"; scottPlotUC2.Redraw(); } public void StartListeningToMicrophone(int audioDeviceNumber = 0) { WaveIn wi = new WaveIn(); wi.BufferMilliseconds = 50; wi.DeviceNumber = audioDeviceNumber; wi.WaveFormat = new NAudio.Wave.WaveFormat(RATE, 16,1); //wi.BufferMilliseconds = (int)((double)BUFFERSIZE / (double)RATE * 1000.0); wi.DataAvailable += new EventHandler<WaveInEventArgs>(AudioDataAvailable); bwp = new BufferedWaveProvider(wi.WaveFormat); bwp.BufferLength = BUFFERSIZE * 2; bwp.DiscardOnBufferOverflow = true; player = new WaveOut(); player.Init(bwp); player.Play(); try { wi.StartRecording(); } catch { string msg = "Could not record from audio device!\n\n"; msg += "Is your microphone plugged in?\n"; msg += "Is it set as your default recording device?"; MessageBox.Show(msg, "ERROR"); } } private void Timer_Tick(object sender, EventArgs e) { // turn off the timer, take as long as we need to plot, then turn the timer back on timerReplot.Enabled = false; PlotLatestData(); timerReplot.Enabled = true; } public int numberOfDraws = 0; public bool needsAutoScaling = true; public void PlotLatestData() { // check the incoming microphone audio int frameSize = BUFFERSIZE; var audioBytes = new byte[frameSize]; bwp.Read(audioBytes, 0, frameSize); textBox1.Text = BitConverter.ToString(audioBytes); // return if there's nothing new to plot if (audioBytes.Length == 0) return; if (audioBytes[frameSize - 2] == 0) return; // incoming data is 16-bit (2 bytes per audio point) int BYTES_PER_POINT = 2; // create a (32-bit) int array ready to fill with the 16-bit data int graphPointCount = audioBytes.Length / BYTES_PER_POINT; // create double arrays to hold the data we will graph double[] pcm = new double[graphPointCount]; double[] fft = new double[graphPointCount]; double[] fftReal = new double[graphPointCount/2]; // populate Xs and Ys with double data for (int i = 0; i < graphPointCount; i++) { // read the int16 from the two bytes Int16 val = BitConverter.ToInt16(audioBytes, i * 2); // store the value in Ys as a percent (+/- 100% = 200%) pcm[i] = (double)(val) / Math.Pow(2,16) * 200.0; } // calculate the full FFT fft = FFT(pcm); // determine horizontal axis units for graphs double pcmPointSpacingMs = RATE / 1000; double fftMaxFreq = RATE / 2; double fftPointSpacingHz = fftMaxFreq / graphPointCount; // just keep the real half (the other half imaginary) Array.Copy(fft, fftReal, fftReal.Length); // plot the Xs and Ys for both graphs scottPlotUC1.Clear(); scottPlotUC1.PlotSignal(pcm, pcmPointSpacingMs, Color.Blue); scottPlotUC2.Clear(); scottPlotUC2.PlotSignal(fftReal, fftPointSpacingHz, Color.Blue); // optionally adjust the scale to automatically fit the data if (needsAutoScaling) { scottPlotUC1.AxisAuto(); scottPlotUC2.AxisAuto(); needsAutoScaling = false; } //scottPlotUC1.PlotSignal(Ys, RATE); numberOfDraws += 1; lblStatus.Text = $"Analyzed and graphed PCM and FFT data {numberOfDraws} times"; // this reduces flicker and helps keep the program responsive Application.DoEvents(); } private void autoScaleToolStripMenuItem_Click(object sender, EventArgs e) { needsAutoScaling = true; } private void infoMessageToolStripMenuItem_Click(object sender, EventArgs e) { string msg = ""; msg += "left-click-drag to pan\n"; msg += "right-click-drag to zoom\n"; msg += "middle-click to auto-axis\n"; msg += "double-click for graphing stats\n"; MessageBox.Show(msg); } private void websiteToolStripMenuItem_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start("https://github.com/swharden/Csharp-Data-Visualization"); } public double[] FFT(double[] data) { double[] fft = new double[data.Length]; System.Numerics.Complex[] fftComplex = new System.Numerics.Complex[data.Length]; for (int i = 0; i < data.Length; i++) fftComplex[i] = new System.Numerics.Complex(data[i], 0.0); Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward); for (int i = 0; i < data.Length; i++) fft[i] = fftComplex[i].Magnitude; return fft; } private void textBox1_TextChanged(object sender, EventArgs e) { } } }
Please help me! Thanks everyone!
- Moved by Jack J JunMicrosoft contingent staff Wednesday, October 14, 2020 7:55 AM
Thursday, October 8, 2020 10:00 AM
All replies
-
This forum is for C#-specific questions only. We do not provide support for third party libraries like NAudio. Please post your question in their support forums.
Michael Taylor http://www.michaeltaylorp3.net
Thursday, October 8, 2020 2:13 PM