How to VoIP using NAUDIO - c#

I'm developing a voip server-client app using NAUDIO and Sockets.
I've read the naudio's documentation and I have tried alot to get the data from the microphone then send it to the client, the thing that you can get the data, but you have to save it to a byte array first then send it which is almost like sending a file using TCP.
How can I get data from naudio and send it at the same time "Stream it" to the client using UDP protocol.
Thanks in advance.

NAudio has a Network Chat Demo within the Examples if you download the source code, which does a good job of showing how to implement a very simple Chat application.
Basically though what you want the client to do is this:
void Initialize()
{
waveIn = new WaveIn();
waveIn.BufferMilliseconds = 50;
waveIn.DeviceNumber = inputDeviceNumber;
waveIn.WaveFormat = codec.RecordFormat;
waveIn.DataAvailable += waveIn_DataAvailable;
waveIn.StartRecording();
...
}
void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
//Encode and send e.Buffer
}
With this you get a byte array every 50 ms (or however long you set you buffer to) and send it to the server. You'll need to encode it however, since sending the sound un-encoded will take up too much bandwidth. NAudio has codecs of its own, so that shouldn't be much of a problem. See here for NAudio's network chat demo.
Another thing to consider, if you plan to implement a client to client voip (either via p2p or streamed through the server itself) is a good networking library to handle all the communications. I've used Lidgren on a similar project which worked pretty well. It's open source, but can easily be set up to fit your needs.

There is a demo in the NAudioDemo app called "Network Chat", which records from the microphone, compresses the audio with a codec, and sends it out via UDP. It also receives audio from UDP, decompresses it and plays it. So looking at that code should point you in the right direction. What it doesn't show is the use of any protocol on top of UDP, so just the raw compressed audio is being sent over the network with no timestamps or indications of what codec is being used.

Related

play audio from TCP/IP server in UWP client on PI3

I'm trying to make an uwp app which will be a client and will run on PI3. The server is a C# Winforms app, that runs on my Windows 10 computer, which I've found here: https://www.codeproject.com/Articles/482735/TCP-Audio-Streamer-and-Player-Voice-Chat-over-IP. The server can stream audio from microphone device to all the connected clients. Although the project has its own client and I can run both server and client on my local machine. Now I want to build a similar client app in UWP C#. By using the UWP StreamSocketActivity sample, I can connect to the server. But I don't know how to receive the audio data and play it on UWP client. Could anyone give me a hand?
Blow is the screenshot of running server which has one connection from uwp client:
Client connects to the server
Thanks in advance!
As mentioned in the article, the protocol used to transfer the audio data is customized.
Note !!! This is a proprietary project. You can't use my servers or
clients with any other standardized servers or clients. I don't use
standards like RTCP or SDP.
You can find the code in TcpProtocols.cs. In UWP client app, you need to convert the code for UWP. This document shows how to build a basic TCP socket client in UWP. But you also need to modify the code for receive data from server continuously. Following code may be helpful for you.
private async void StartClient()
{
try
{
// Create the StreamSocket and establish a connection to the echo server.
using (var streamSocket = new Windows.Networking.Sockets.StreamSocket())
{
// The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
var hostName = new Windows.Networking.HostName(TxtHostName.Text);
await streamSocket.ConnectAsync(hostName, TxtPortNumber.Text);
while(true)
{
using (var reader = new DataReader(streamSocket.InputStream))
{
reader.InputStreamOptions = InputStreamOptions.Partial;
uint numAudioBytes = await reader.LoadAsync(reader.UnconsumedBufferLength);
byte[] audioBytes = new byte[numAudioBytes];
reader.ReadBytes(audioBytes);
//Parse data to RTP packet
audioBytes = Convert_Protocol_LH(audioBytes);
var pcmStream = audioBytes.AsBuffer().AsStream().AsRandomAccessStream();
MediaElementForAudio.SetSource(pcmStream, "audio/x-wav");
MediaElementForAudio.Play();
}
}
}
}
catch (Exception ex)
{
Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
}
}
UPDATE:
RTP Packet
RTSP for living audio is recommended and wide used.The Real Time Streaming Protocol (RTSP) is a network control protocol designed for use in entertainment and communications systems to control streaming media servers. The protocol is used for establishing and controlling media sessions between end points. There are some advantages of RTSP. In this solution, you need to build a RTSP server and then use VLC.MediaElement library or other library which support on Windows IoT Core in your UWP app. But i am not sure this library supports RTP.
In addition, this document shows supported codecs on Windows IoT Core.

Sending a binary byte stream over serial using C# and .net 4.0

I have an application which I want to communicate over a serial link to an embedded device. The communication protocol is binary - meaning that I have a structured message that I want to copy from memory into the serial byte stream unaltered (no encoding).
I am using Microsoft VS 2012 writing the application in C# with the .NET framework. I inherited a shell of an app which appears to be using the System.IO.Ports.SerialPort class to read/write to the com port.
Several coworkers have told me that I would have problems because modern communication libraries, or even the drivers for USB and serial, will assume you are communicating using some form of encoding like ASCII or Unicode. If anyone has an idea of how to start this please let me know. I appreciate any help.
The starting point you are probably looking for is the Write(byte\[\], int, int) method which allows you send an arbitrary chunk of binary data to the serial port.
And no, it's not true that serial (RS-232) communication requires character data. The physical communication like doesn't care of what data you send through it. Whether you can send 'raw binary' data or text commands (such as the so-called AT commands used by modems) is a matter of the actual application protocol (if any) used on top of that communication link.
C# makes it pretty simple.
using System.IO.Ports;
public void TestSerialPort()
{
SerialPort serialPort = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
serialPort.Open();
byte[] data = new byte[] { 1, 2, 3, 4, 5 };
serialPort.Write(data, 0, data.Length);
serialPort.Close();
}
And as mentioned, you can send any raw binary values you want, it doesn't need to be character data.

Is it possible to create C# client to connect to a specific JVM-based server (Netty)?

I am working on a C# client for a server that wraps Netty. It is a TCP/IP server and I have tried using C# class TcpClient, but could not write anything onto the server or receive a printed response.
The Netty socket classes include the following: http://docs.jboss.org/netty/3.2/api/org/jboss/netty/channel/socket/nio/NioClientSocketChannelFactory.html http://docs.jboss.org/netty/3.2/api/org/jboss/netty/bootstrap/ClientBootstrap.html
The message is encoded as a byte[] in Java. Part of class PingSerializer, in the server code, reads as follows:
public byte[] requestToBytes(Ping message) {
return NorbertExampleProtos.Ping.newBuilder().setTimestamp(message.timestamp).build().toByteArray();
}
public Ping requestFromBytes(byte[] bytes) {
try {
return new Ping(NorbertExampleProtos.Ping.newBuilder().mergeFrom(bytes).build().getTimestamp());
} catch (InvalidProtocolBufferException e) {
System.out.println("Invalid protocol buffer exception " + e.getMessage());
throw new IllegalArgumentException(e);
}
}
I would like to know whether it is possible for a client written in C# to connect to the socket, ping the server and print out the server's response, without modifying the server code or using a cross-language development tool such as Apache Thrift or IKVM to handle the messages. Thanks, I would appreciate any help.
Judging by the code sample you've given, it looks like the data is encoded using Protocol Buffers, Google's serialization format.
Fortunately, there are at least two libraries implementing Protocol Buffers for .NET:
protobuf-net: Written for .NET from the ground up, this is a good choice if you don't particularly need the C# code to look like the equivalent Java/C++ code.
protobuf-csharp-port: This is a port from the Java client code, with some .NET idioms added - so if you're working with Protocol Buffers on multiple platforms, this may be more appropriate. (Disclaimer: I did most of the coding for this port.)
The good news is that the wire format for the two is the same, because it's the standard Protocol Buffer wire format. So if you decide later on that you've made the wrong choice, you don't need to worry about the data format changing.
In terms of communicating with the server, TcpClient should be absolutely fine. You'll need to find out exactly what the protocol is - for example, whether it's Protocol Buffers over HTTP, or something similar. (If it is over HTTP, WebClient would be a simpler approach.) However, beyond that it's straight TCP/IP: you write the bytes to the server, and it should write a reply. You can use Wireshark to look at the traffic between the client and the server, if you need to trace where problems are occurring.
There is an application called CS2J that will convert all of your C# code directly over to Java. However, you cannot expect it to be perfect and you will have a bit of debugging to do. It is supposed to very accurate.

How to see what port was opened by router

If I do the following:
UdpClient c = new UdpClient();
c.Connect(new System.Net.IPEndPoint(IPAddress.Parse("69.65.85.125"), 9900));
c.Send(new byte[] { 1,2,3,4,5 }, 5);
then I will be sending a packet to my router then my router will send that packet to the ip "69.65.85.125".
If I where to capture that packet on the computer that has the ip "69.65.85.125" I will be able to see the port that was oppened by the router (client.RemoteEndpoint). How will it be possible to see that information without capturing the packet at the other enpoint? Is there a way to query the router?
If your router supports it you can query it via UPnP. Here is a wrapper library for UPnP I found for .NET, I have never used it so I cant give you any advice if it is good or not.
Look at the ComponetsTest program for example code in the zip for the library. You will need to reference the UPnP documentation to find out what calls you will need to make to the service.
From the message board of the library of someone asking a how to find port mappings.
The WANPPPConnection and WANIPConnection services have actions called
GetSpecificPortMappingEntry, simply call this iterating through the
indexes from 0 until an error is returned, each call will return
another UPnP port mapping, you can also get the static mappings with a
different service.
In order to get the public IP, the remote device should respond by sending a UDP packet back to you that contains the IP address and port it saw. This is one of the most fundamental concepts behind a STUN server, commonly used in UDP hole-punching algorithms.
There are several free STUN servers available that do exactly this. Send one of them a "binding" request, and you will get back a response with your public IP address and port.
stun.l.google.com:19302
stun1.l.google.com:19302
stun2.l.google.com:19302
stun3.l.google.com:19302
stun4.l.google.com:19302
stun01.sipphone.com
stun.ekiga.net
stun.fwdnet.net
stun.ideasip.com
stun.iptel.org
stun.rixtelecom.se
stun.schlund.de
stunserver.org
stun.softjoys.com
stun.voiparound.com
stun.voipbuster.com
stun.voipstunt.com
stun.voxgratia.org
stun.xten.com
If you are truly interested in doing proper UDP hole-punching, check out ICE (Interactive Connectivity Establishment). It's a brilliant algorithm that uses STUN and another protocol called TURN to guarantee a successful connection between peers. (Apple uses it for Facetime video calls, among others.)
If you're interested, the company I work for has developed a product called IceLink that uses ICE/STUN/TURN to establish direct data streams between peers. SDKs are available for .NET, Mac, iOS, Android, Java, Windows Phone, Windows 8, Unity, Xamarin, and more, and it even includes full support for WebRTC audio/video streams.

Streaming RS-232 Output to the browser

Is this possible? If so, what is the industry standard as far as software goes? Specifically, I am referring to .net controls.
Thank you
EDITED:
Here is what I need. I have a thin client with a balance where RS-232 is used to interact with the thin client. Currently, it is a compact framework app. What I would like to know id whether it is possible to have the same set up in a web application. So that would entail that the RS-232 is NOT the server RS-232 - it is the user's computer RS-232 - RS-232 is on the client. So when the RS-232 spits out input, it should go to the browser. Is it possible in a web application?
Two ways I can think of;
Buffer the serial data in an application object, and then use an ajax call triggered by a timer to grab and display the latest data.
For shorter streams of data, you could, instead of using asp.net controls per se, do something like;
Response.ContentType = "text/plain";
Response.Clear();
String serialData;
while(serialData = getSerialData() {
Response.Write(serialData);
Response.Flush();
}
This will write text content to the web browser in real time. You probably wouldn't want to keep this session open for too long though.
If you wanted to display the stream of data within another page, then just place the page with the above code within an iFrame.
Also note that the above would best be done in an ashx handler rather than an aspx page.
Sure, you can do it. You'd read from a System.IO.Ports.SerialPort instance, and output it via an HttpListener.
The trick will be knowing what you want to do with the page that the HttpListener serves up. Since data will be coming in on the COM port in real time, you'll probably want to buffer it between HTTP requests to your server, since otherwise, if you try to read the port without data waiting, you'll hang the listener. You can also miss data if you don't read it regularly and it fills the SerialPort read buffer.

Categories

Resources