This project has moved. For the latest updates, please go here.

Network Chat Multi-Client Program

Feb 5, 2013 at 8:06 PM

I've been working on expanding the Network Chat demo to allow multiple clients to connect to the host computer and voice chat. Seeing that I need to keep track of the clients and the audio data sent over, I created a Client struct that keeps track of who the client is and their BufferedWaveProvider object data.

For the host, I add their BufferedWaveProvider object to a MixingSampleProvider, which then I used that to create a IWaveProvider object. Finally, I used the IWaveProvider for my WaveOut object and use that to play audio.

For my Recieve method that I'm using to obtain audio data, I check to see whether or not the data came from the host or another client. If it's from the host, I just add the data to the host's BufferedWaveProvider object. Otherwise, I need to check to see if the client is connecting to the host IP for the first time. If it is, I create a new Client object with it's own BufferedWaveProvider object and add it to my MixingSampleProvider. Finally, I pull the correct Client object based on its IP address, add the data to its BufferedWaveProvider, and then update the BufferedWaveProvider so that it has the added sample data.

When I applied this logic to actual code and tested it, the audio from the host's mic works correctly. When a client connects to the host's IP from another computer, the audio gets choppy. I can hear what's being said from the client, but it's delayed by a few seconds.

Perhaps my logic isn't correct when trying to receive and play what's been sent over by clients. What could be causing the choppy audio?

Feb 11, 2013 at 2:19 PM
choppy audio is usually because you can't fill the bufferedwaveprovider fast enough. Maybe your netwrok connection is not good enough. You also might need to allow some buffering time to give smoother playback.
Feb 11, 2013 at 9:25 PM
For testing purposes, I'm using LAN for sending audio between multiple clients. Is there a way to delay the audio while waveOut.Play() is active? Maybe it's expecting all audio to be available to play and since my Receiver() method is adding the data to the bufferedwaveproviders (either client or host) that it can't keep up. What I would like to do is have the audio be delayed until a certain percentage of the data is filled in the bufferedwaveprovider.
Feb 12, 2013 at 6:58 AM
one cheat to avoid having to pause while the buffer fills is to stick a couple of seconds of silence into it whenever it empties.
Feb 13, 2013 at 9:02 PM
Is it also possible to check the buffer to see if a certain percentage of it is filled before playing the audio? For example, if a client's bufferedwaveprovider isn't 25% - 75% filled, then the waveOut is paused and once I received sufficient data I can resume playing.
Feb 18, 2013 at 3:38 PM
you can ask the BufferedWaveProvider how much data it has queued. This is how the Network streaming demo works - goes into auto-pause when there is not enough..
Feb 25, 2013 at 3:55 PM
Can this also work if I have more than one client connected to the server? As long as one client has enough data in their bufferedwaveprovider, I should be able to have waveOut play the audio while still collecting data from other clients. I'm thinking all I would have to do is create a while loop to find a client that has sufficient data and then play the audio. Would that be sufficient or do you think there's more to it than that?
Feb 25, 2013 at 7:40 PM
well if you're mixing them with a MixingSampleProvider, then you need to create an intermediate stream between the BufferedWaveProvider and the Mixer so that it can return 0s in its Read method while buffering is still working. The mixer will always try to read out of all the inputs so they have to return something.
Feb 26, 2013 at 5:13 PM
Are there any samples from the naudio demos that deal with adding intermediate streams? I'm confused how adding another stream would work if I've already added a client's waveprovider to the MixingSampleProvider.
Feb 28, 2013 at 9:17 PM
Can I at least show you the pseudocode for my Receiver() method so that I can explain where I'm at with obtaining the data from clients and trying to fill each client's BufferedWaveProvider and adding them to the MixingSampleProvider?
Mar 2, 2013 at 6:57 AM
you can make a class that inherits from ISampleProvider or IWaveProvider and in its Read method you can either read from a source provider or just return 0s if there isn't enough buffered audio in the source