Play output audio in Naudio

  • Thread starter Thread starter hungcui
  • Start date Start date
H

hungcui

Guest
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 = (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("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 = new System.Numerics.Complex(data, 0.0);
Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward);
for (int i = 0; i < data.Length; i++)
fft = fftComplex.Magnitude;
return fft;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{

}
}
}



Please help me! Thanks everyone!

Continue reading...
 
Back
Top