2

i just want to hear what i say to microphone using NAudio and this is my code so far but the problem is i can't hear anything. any help would be appreciated.

public partial class frmMain : Form
    {
        private WaveIn waveIn; // Gets an audio from microphone
        private WaveOut waveOut; // Sends audio to speaker
        private BufferedWaveProvider waveProvider; // Gets an audio from stream

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            waveOut = new WaveOut();
            waveIn = new WaveIn();
            waveProvider = new BufferedWaveProvider(waveIn.WaveFormat);

            waveOut.Init(waveProvider);             

            waveIn.DataAvailable += waveIn_DataAvailable;

            waveOut.Play();            
        }

        private void waveIn_DataAvailable(object sender, WaveInEventArgs e)
        {
            waveProvider.Read(e.Buffer, 0, e.BytesRecorded);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            waveIn.StopRecording();
            waveIn.Dispose();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            waveIn.StartRecording();
        }
    }

i will use this scenario in network programming on which i send the data from microphone to the socket then on the client side the BufferedWaveProvider will read the data then send it to the speaker. Please put also some comment if what is the better way to do it.

TIA

Vincent Dagpin
  • 3,581
  • 13
  • 55
  • 85
  • 1
    You are reading from the wrong stream in the DataAvailable event. And then you don't do anything with it. – Hans Passant Feb 27 '13 at 00:21
  • 1
    Your `waveIn_DataAvailable` method is trying to read from `waveProvider` instead of writing to it. Change `waveProvider.Read` to `waveProvider.AddSamples` and see if that helps. Also your initialization of the `waveIn` object doesn't seem to be complete... you haven't called `waveIn.StartRecording`. – Corey Feb 27 '13 at 00:31
  • i do the StartRecording on btnStart_Click event – Vincent Dagpin Feb 27 '13 at 00:48
  • @VincentDagpin Sorry, missed that. I've created a simple test app that does passthrough from mic to speakers... will post code in an answer. – Corey Feb 27 '13 at 00:54
  • @Corey waveProvider.AddSamples do work but kinda delay upon receiving to mic.. – Vincent Dagpin Feb 27 '13 at 00:57
  • why do they keep down voting my post? is there a problem with it? – Vincent Dagpin Feb 27 '13 at 00:57
  • how can i compact the data available from WaveIn? so i can send it to the network then decompress it upon receiving to the other side. – Vincent Dagpin Feb 27 '13 at 01:00
  • 2
    The delay is inherent in the way NAudio's `WaveIn` and `WaveOut` classes are accessing the devices and data. NAudio isn't really designed for low-latency stuff, but you can reduce it by setting `waveIn.BufferedMilliseconds` to a lower value (10 for instance) and `waveOut.DesiredLatency` to 100 or so. If you go too low on `DesiredLatency` it will start to break up on you, so go easy on this setting. – Corey Feb 27 '13 at 01:31
  • 1
    @VincentDagpin NAudio apparently has some compression classes to use the ACM codecs. I've never played with them, but they might give you a reasonable place to start. ACM codecs aren't usually very good with low-latency stuff, so look around for a good audio compression library like https://github.com/JohnACarruthers/Opus.NET – Corey Feb 27 '13 at 01:54
  • waveIn and waveOut APIs are not good for low latency. For speech compression, some of the ACM codecs that come with Windows should be fine. The NAudioDemo project actually comes with an example of a network chat app using ACM and sending packets via UDP – Mark Heath Feb 27 '13 at 11:22

1 Answers1

9

Sample code as promised. Code is for a form with two buttons (named StartBtn and StopBtn).

public partial class Form1 : Form
{
    private WaveIn waveIn = null;
    private BufferedWaveProvider waveProvider = null;
    private WaveOut waveOut = null;

    public Form1()
    {
        InitializeComponent();
    }

    private void StartBtn_Click(object sender, EventArgs e)
    {
        if (waveIn != null)
            return;

        // create wave input from mic
        waveIn = new WaveIn(this.Handle);
        waveIn.BufferMilliseconds = 25;
        waveIn.RecordingStopped += waveIn_RecordingStopped;
        waveIn.DataAvailable += waveIn_DataAvailable;

        // create wave provider
        waveProvider = new BufferedWaveProvider(waveIn.WaveFormat);

        // create wave output to speakers
        waveOut = new WaveOut();
        waveOut.DesiredLatency = 100;
        waveOut.Init(waveProvider);
        waveOut.PlaybackStopped += wavePlayer_PlaybackStopped;

        // start recording and playback
        waveIn.StartRecording();
        waveOut.Play();
    }

    void waveIn_DataAvailable(object sender, WaveInEventArgs e)
    {
        // add received data to waveProvider buffer
        if (waveProvider != null)
            waveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded);
    }

    private void StopBtn_Click(object sender, EventArgs e)
    {
        if (waveIn != null)
            waveIn.StopRecording();
    }

    void waveIn_RecordingStopped(object sender, StoppedEventArgs e)
    {
        // stop playback
        if (waveOut != null)
            waveOut.Stop();

        // dispose of wave input
        if (waveIn != null)
        {
            waveIn.Dispose();
            waveIn = null;
        }

        // drop wave provider
        waveProvider = null;
    }

    void wavePlayer_PlaybackStopped(object sender, StoppedEventArgs e)
    {
        // stop recording
        if (waveIn != null)
            waveIn.StopRecording();

        // dispose of wave output
        if (waveOut != null)
        {
            waveOut.Dispose();
            waveOut = null;
        }
    }
}

Note especially the waveIn.BufferMilliseconds and waveOut.DesiredLatency settings to reduce the lag times.

For compressing the data for network transmission I suggest using a different library to process the data blocks. You might need to tune the BufferMilliseconds value to reduce the overheads and get better compression ratios.

The Opus Codec looks like a reasonable option, with Opus.NET for C#.

Corey
  • 15,524
  • 2
  • 35
  • 68
  • Woa... 2013 answer! My question is, can we apply VST Plugin to that "heard" from mic and play it back in speaker? – swdev Mar 04 '21 at 14:15