상세 컨텐츠

본문 제목

C# The way to make Real-time audio communication RTC in WPF with WebSocket-Sharp

Go

by 경밤 2020. 4. 12. 16:13

본문

반응형

In this post , We are going to make a Real-Time audio communication.

First, We have to use NAudio to RTA.

Second, Know the specificity of "IWaveProvier".

 

Let's make some appliction.

 

There will be created 3 classes.

The frist we're going to code is EndlessProvider. This class will work like that provide sample which get other computer all the time and wrtie them on the stream that passed on contructor.

 

EndlessProvider.cs

    public class EndlessProvider: IWaveProvider, IDisposable
    {
        public WaveFormat WaveFormat { get { return waveProvider.WaveFormat; } }

        private readonly IWaveProvider waveProvider;
        private readonly WaveFileWriter waveWriter;
        private bool isWriterDisposed;

        public EndlessProvider(IWaveProvider provider, Stream waveStream)
        {
            this.waveProvider = provider;
            waveWriter = new WaveFileWriter(waveStream, provider.WaveFormat);
        }

        public int Read(byte[] buffer, int offset, int count)
        {
            var read = waveProvider.Read(buffer, offset, count);
            if (count > 0 && !isWriterDisposed)
            {
                waveWriter.Write(buffer, offset, read);
            }

            if (count == 0)
                Dispose();

            return read;
        }
        public void Dispose()
        {
            if (!isWriterDisposed)
            {
                isWriterDisposed = true;
                waveWriter.Dispose();
            }
        }
    }

In short, The Contructor of EndlessProvider will get a kind of MemoryStream and IWaveProvider that would be BufferedWaveProvider and The 'Read' method will used by WaveOut.

 

The next is SharpRTA. 

SharpRTA class will use EndlessProvider to play the real-time read samples and pass the sample data to the use WebSocket-Sharp's Send in the main class.

 

SharpRTA.cs

    public class SharpRTA
    {
        private WaveIn recorder;
        private BufferedWaveProvider bufferedWaveProvider;
        private EndlessProvider endlessProvider;
        private WaveOut player;

        private Action<SampleRTA> bufferSendingHandler;
        public bool Active;

        public SharpRTA()
        {
            Active = false;
        }

        public void Start(Action<SampleRTA> bufferHandler)
        {
            bufferSendingHandler = bufferHandler;

            Active = true;
            recorder = new WaveIn();
            recorder.DataAvailable += recordDataAvailable;

            bufferedWaveProvider = new BufferedWaveProvider(recorder.WaveFormat);
            endlessProvider = new EndlessProvider(bufferedWaveProvider, new MemoryStream() );

            player = new WaveOut();
            player.Init(endlessProvider);

            player.Play();
            recorder.StartRecording();
        }
        public void Stop()
        {
            Active = false;
            recorder.StopRecording();
            player.Stop();
            endlessProvider.Dispose();
        }
        public void Keep(byte[] samples)
        {
            bufferedWaveProvider.AddSamples(samples, 0, samples.Length);
        }
        private void recordDataAvailable(object sender, WaveInEventArgs eventArgs)
        {
            bufferSendingHandler(new SampleRTA(eventArgs.Buffer, eventArgs.BytesRecorded));
        }

    }

In short, SharpRTA create another IWaveProvider that would be passed on EndlessProvider and the WaveIn record all the times. Also The recorded data convey for every data available event trigging.

Using the WaveOut to play with EndlessProvider.Read and The Keep method used to add audio samples the bufferedWaveProvider.

The SharpRTA, EndlessProvider and the methods works images.

 

The last, SampleRTA It's simple. I think this don't need to explain.

    public class SampleRTA
    {
        public byte[] Sample { get; private set; }
        public int Size { get; private set; }

        public SampleRTA(byte[] sample, int sampleSize)
        {
            Sample = sample;
            Size = sampleSize;
        }
    }

 

MainWindow.xaml.cs

client.On(Headers.BroadcastAudio.ToStringValue(), (packet) =>
{
	var data = packet.Body;
	Stream ms = new MemoryStream(Convert.FromBase64String(data));
	rta.Keep(ms.ToByteArray());
});

When got the audio samples from other, SharpRTA.Keep,

private void sampleHandler(SampleRTA sample)
{
	if(!microphoneMute) client.Emit("AudioMessage", sample.Sample);
}

private SharpRTA rta;

public MainWindow()
{
	rta = new SharpRTA();
	rta.Start(sampleHandler);
}

Initalize SharpRTA and start playing and recording (you can manipulate recording in handler. in this code, block the sending samples to declare microphoneMute.)

 

Now, Done.

 

Thank you for reading.

 

It's my simple chat project

You can find more codes in here. I made my own websocket client to use Websocket-Sharp.

반응형

관련글 더보기