1

I want to make an app to transfer Audio from the microphone in a laptop or PC live, in real time, like a YouTube stream but without video. I will describe my process:

  1. I transfer a normal file by converting it to byte then back again to origin.
  2. I change the file type to MP3 or wav then use NAudio. Works fine also I can play the file if transferred or while receiving
  3. I change the input file to Microphone and receive the audio.

Here is the problem: NAudio is unable to put the live stream from the mic then send it automatically. Always, the buffer gives me a null pointer exception while debugging ,then it gives me another error that the decoder of NAudio did not receive any data, "not acceptable by the way".

It should listen or keep receiving data until the port or connection closes.

I've tried to search about any library about VoIP but found nothing except Ozeki, but no tutorial to handle. All I found is old videos that do not work. I searched about that over a week but no result. I don't want a fully developed project because I already found one, but it is too complex -- about 2K lines of code. All I need is to know what to do or to be given the code that solves the problem.

This is client side code:

   public void client()
    {
        try
        {
            //byte[] send_data = Audio_to_byte(); // ORIGINAL WORK CODE
            byte[] send_data = new byte [BufferSize]; // 100M buffer size 
            TcpClient client = new TcpClient(serverip, port);
            NetworkStream stream = client.GetStream();
            // sourceStream and wavein is global vars
            sourceStream = new NAudio.Wave.WaveIn();
            sourceStream.DeviceNumber = 1;
            sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(1).Channels);
            wavein = new NAudio.Wave.WaveInProvider(sourceStream);
            //wavein.Read(send_data, 0, send_data.Length); // this buffer not work some times give me full buffer
            BufferedWaveProvider pro = new BufferedWaveProvider(wavein.WaveFormat);
            pro.AddSamples(send_data, 0, send_data.Length); // Empty buffer or error full buffer
            stream.Write(send_data, 0, send_data.Length);
            stream.Close();
            client.Close();

        }
        catch (Exception e)
        {
            MessageBox.Show("Server is offline" + e, "Error");
// Here the message is buffer is full or send it empty then the decoder did not receive anything give exception error or of them happen first
        }
    }

and this server side code with MP3 reader code

 IPAddress ip = Dns.GetHostEntry(serverip).AddressList[0];
        TcpListener server_obj = new TcpListener(ip,port);
        TcpClient client = default(TcpClient);
        try
        {
            server_obj.Start();
            while (true)
            {
                // accept all client
                client = server_obj.AcceptTcpClient();
                // make byte storage from network
                byte[] received_buffer = new byte[BufferSize];
                //get data from cst
                NetworkStream stream = client.GetStream();
                //save data from network to memory till finish then save with playing
                MemoryStream ms = new MemoryStream();

                int numBytesRead = 0;
               
                while ((numBytesRead = stream.Read(received_buffer, 0, received_buffer.Length)) > 0)
                {
                    // THIS STEP TO RECEIVE ALL DATA FROM CLIENT
                    ms.Write(received_buffer, 0, numBytesRead);
                    //receive sound then play it direct
                    WaveOut(ms.ToArray());
                }

                Byte_to_audio(ms.ToArray()); // YOU can make or allow override
            }
        }
        catch(Exception e)
        {
           MessageBox.Show("Error Message : " + e, "Error");
        }
    }

this is Method that read stream receiving data from network

       private void WaveOut(byte[] mp3Bytes)
    {
        // MP3 Format
        mp3Stream = new MemoryStream(mp3Bytes);
        mp3FileReader = new Mp3FileReader(mp3Stream);
        wave32 = new WaveChannel32(mp3FileReader, 0.3f, 3f);
        ds = new DirectSoundOut(); // but declration up global
        ds.Init(wave32);
        ds.Play(); // work code*/ 
    }
Wyck
  • 10,311
  • 6
  • 39
  • 60
  • I am afraid it is not as simple as it looks like. Audio creating (mic) and playing is real time. Audio streaming, like VoIP uses the RTP protocol for this. It uses fixed buffer of e.g. 20 ms and send it every 20 ms. This way you could be sure that always enough audio is received to play. – H.G. Sandhagen Jun 19 '20 at 16:17
  • Okay and you provide me any source to start develop this in C# ? – Mustafa Mohamed Jun 19 '20 at 16:21
  • 1
    I'm sorry, I didn't implement something like this myself. But I found [this](https://stackoverflow.com/questions/57563843/choppy-audio-with-naudio-and-tcp-stream-buffer-full-exception?rq=1]). Sounds like a similar problem. Maybe it would help. – H.G. Sandhagen Jun 19 '20 at 16:31
  • Thanks sir that was helpful i transferred real sound over TCP/IP – Mustafa Mohamed Jun 19 '20 at 18:30

1 Answers1

0

I recommend using UDP, if it has to be in real time.

As I use Naudio with vb.net, I based this post.

Client Example:

waveIn = new WaveIn();
waveIn.BufferMilliseconds = 50; //Milissecondes Buffer
waveIn.DeviceNumber = inputDeviceNumber;
waveIn.WaveFormat = HEREWaveFormatHERE;
waveIn.DataAvailable += waveIn_DataAvailable; //Event to receive Buffer
waveIn.StartRecording();

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
   //e -> BUFFER

stream.Write(send_data, 0, send_data.Length);
            stream.Close();
            client.Close();

}
  • RECEIVE:

1 - Create WaveOut and BufferProvider Global

WOut = New WaveOut(WaveCallbackInfo.FunctionCallback());

BufferedWaveProvider pro = new BufferedWaveProvider(HEREWaveFormatHERE);
pro.BufferLength = 20 * 1024;      //Max Size BufferedWaveProvider
pro.DiscardOnBufferOverflow = True;
WOut.Init(pro);
WOut.Play();

As long as there is no audio BufferedWaveProvider will provide silence for WaveOut or other outputs, it will also queue everything that arrives, for continuous playback.

2 - Play and Enqueue

while ((numBytesRead = stream.Read(received_buffer, 0, received_buffer.Length)) > 0)
                {
                   pro.AddSamples(received_buffer, 0, numBytesRead);
                }

My knowledge of naudio is limited to that

English from google translator