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

Voice chat application using WMA possible?

Jul 27, 2011 at 10:31 PM

I'm experimenting with NAudio (pretty much my only choice) in an attempt to create a voice chat program that streams audio from two users' microphones back and forth, using WMA (not MP3 or WAV) as its encoder. I've only had little success with this so far, and I would like to ask for some guidance as to how this can be achieved.

Right now, I'm trying to make an "offline version," that is, where I just hear myself. My program consists of a simple button that's supposed to start and stop playing back your voice, encoded in WMA, and not just play back the raw audio.

What I currently have is a button that records and saves a WAV file. This is code for when the button is pressed:

global.waveInStream = new WaveIn();

global.waveInStream.DeviceNumber = global.inputDevice;
global.waveInStream.WaveFormat = new WaveFormat(44100, 1);

global.writer = new WaveFileWriter("test.wav", global.waveInStream.WaveFormat);
global.waveInStream.DataAvailable += new EventHandler<WaveInEventArgs>(waveInStream_DataAvailable);

global.waveInStream.StartRecording();

 

When button is released:

global.waveInStream.StopRecording();
global.waveInStream.Dispose();
global.waveInStream = null;
global.writer.Close();
global.writer = null;

 

And of course the event handling code further down, outside the button's code:

void waveInStream_DataAvailable(object sender, WaveInEventArgs e) {
    global.writer.Write(e.Buffer, 0, e.BytesRecorded);
}

 

("global" is a class that I use to hold global variables)

How can I make it record encoded WMA audio to the memory and then play that back instead? As far as I understand, you can make a Stream that you record into, which you *somehow* play later. I'm not experienced with this, though. The reason I wanna do this is of course so I can write the data to a buffer, but I don't need help with that (writing to buffer).

From what I've seen through search, it doesn't look very difficult to encode to the MP3 format, but when it comes to WMA, there are suddenly things like WMProfiles and CodecFormats, which I have no idea what to do with. I just want to encode to WMA.

Please help. =/

Editor
Jul 28, 2011 at 6:36 AM

Recipe for building a voice chat application that streams compressed data:

1) Define a compression format for audio stream (you have chosen WMA).

2) Ensure that both client and server connections have the same format expectations. In the scenario where it is a voice chat application, consider the 'server' being the end of the connection that is recording the audio & the 'client' being the end that is going to receive the audio and then play back on to the user (assuming speakers). For a full duplex audio chat application - where multiple people can chat at the same time, you will need multiple streams - each with a 'server' for the sending person and a 'client' to receive the data from the stream.

3) On the server, record raw uncompressed audio to a memory stream.

4) Chunk up the data and encode a component of the recorded data (you will need work out how much data to encode at any one time & if you can do this on the fly with your chosen compression method).

5) In effect you will need 2 pointers for a memory stream. 1) which is the current write position, so that you are keeping track of how much data is being written in and 2) a read position so that you know what's been read in to the stream. Normally this memory stream will need to be considered circular, even through it's obviously just an array but you will need to use it as such and write data back at the beginning of the stream when you have run out of space at the end. If you just kept increasing the length of the stream then you would run out of memory. The reason for the 2 pointers is to ensure that you don't read beyond what is written, because if you did you would just get junk data - well to be exact the data that was left over in the stream.

6) Assuming that you have successfully recorded the data to a memory stream, taken a small chunk of it, compressed it using whatever chosen compression routine to an expected format - then you need to send it over the network to the 'client'. To do this you will need the client to be listening on a TCP port or have some awesome UDP networking code written; either way not something that this instruction will go in to detail for.

7) On the client, save the incoming data to a memory stream (or to disk if you want to include the additional latency but I wouldn't recommend it). Again with a similar 2 pointer situation (keeping a location that represents where we are up to with writing and another with where we are at with reading).

8) Uncompress the data from the stream using your chosen decompression algorithm, thanking someone for ensuring that you have pre-established a format for your program; otherwise you would also need some code here somewhere to work out what the current format of the stream is.

9) Play the uncompressed audio stream (Assuming to speakers).

10) In the scenario where multiple people can chat, rinse and repeat the above instructions, if you are building a party chat type of application, open up some more goodness and repeat a few more times and work out a process for mixing the incoming audio streams – also consider UDP.

11) Mmm, chocolate.

 

So, there’s a bit of work to go. I would suggest you look at how to encode and transmit a WMA audio stream to get a grounding; perhaps have a look at this question on stack overflow as a starting point: http://stackoverflow.com/questions/64303/convert-wav-to-wma-using-net

Jul 29, 2011 at 10:59 PM

@opensebj

Thanks for laying out the theory. There were indeed a few things I hadn't fully thought of. I'll be sure to check back to this page often.

I'll convert the WMA Compressor code to C# using a converter, then try to modify it to record to a Stream... At least, I'll attempt. >_<

Do you think you could provide a small piece of code for recording to a Stream or a piece of code for playing a Stream, if you can be bothered to? It would be a great help as well. I hope I'm not annoying you as I feared my entry here would get no replies to begin with.