Course 1 / Lecture 2

How to develop a softphone in C#

How to use media handlers

In Ozeki VoIP SIP SDK, using the MediaHandler is very simple and since there is an enormous amount of MediaHandler classes available in Ozeki VoIP SIP SDK, you can accomplish almost anything you wish to. With the help of MediaHandler, we can share various multimedia contents. You can use this not only in the case of calls but you can even build an arbitrary media application. For instance, by using Ozeki VoIP SIP SDK, you can build a videoplayer, an audioplayer, even an audiorecorder or a videorecorder application.

Solution:

In order to be able to solve this task, you should create a new console program in Visual Studio.

Classes:

  • Program.cs

    The class contains the Main function, controls the console window and provides a connection with the user.

Source code analysis

To be able to understand the source code, you should examine the details in the functionalities of the used classes. In the "using section" we need to add some extra lines, like:

using Ozeki.Media.MediaHandlers;
using Ozeki.Media.MediaHandlers.Video;
using System.Threading;
using System.IO;

Without these lines we would have to use the namespace information as a label for all tools of Ozeki VoIP SIP SDK.

Program.cs

In the program, we will show you 5 examples numbered from 1-5. The user can have access to the given feature by providing the particular number. The following funtionalities are available:

  1. Connecting the Microphone to the Speaker.
  2. Playing an mp3 file with the Speaker.
  3. Connecting the audio of the microphone and the mp3 file simultaneously to the Speaker.
  4. Reading written text out loud.
  5. Record voice and save that to a wav file
  6. Recording the audio and the video of the webcamera in mp4 format

Main function

The Main function controls the whole program. All you need to do is to choose the proper number and afterwards, you can make use of the chosen functionality:

static void Main(string[] args)
        {

            Console.WriteLine("This application show you how to connect the media handlers.");
            Console.WriteLine("");

            Console.WriteLine("1: Connect the microphone to the speaker");
            Console.WriteLine("2: Play mp3 file with the speaker");
            Console.WriteLine("3: 1 and 2 at same time");
            Console.WriteLine("4: Read a text");
            Console.WriteLine("5: Record voice and save that to a wav file");
            Console.WriteLine("6: Record a webcamera view and voice and save that to an mp4 file");

            Console.WriteLine("");
            Console.WriteLine("Please give me the number, which you choose:");

            var param = Console.ReadLine();

            Console.WriteLine("");

            switch (param)
            {
                case "1":
                    MicrophoneToSpeaker();
                    break;

                case "2":
                    MP3ToSpeaker();
                    break;

                case "3":
                    MicrophoneAndMP3ToSpeaker();
                    break;

                case "4":
                    TextToSpeaker();
                    break;

                case "5":
                    RecordVoice();
                    break;

                case "6":
                    CameraToMPEG4();
                    break;

                default:
                    Console.WriteLine("The selected number is not valid.");
                    Console.ReadLine();
                    break;
            }

        }

Functions:

1. static void MicrophoneToSpeaker()

In the present example, we will play the recorded content with the Speaker.

Objects

You should create the following objects: a Microphone, a Speaker and a mediaConnector. The mediaConnector will provide the connection between the source and the target.

Microphone microphone;
Speaker speaker;
MediaConnector mediaConnector;

In this example, we will use the default devices. This can be done by calling the static methods which will return the default device. If there is no default device, null value will be returned. Please keep in mind to check this while the program runs. It is possible to use multiple devices. The GetDevices() function will return the device information in a collection. Using this, the GetDevices() function will return the given device. Afterwards, we will call the default constructor of the MediaConnector.

microphone = Microphone.GetDefaultDevice();
speaker = Speaker.GetDefaultDevice();
mediaConnector = new MediaConnector();

Connecting the objects

You can connect the Microphone and the Speaker with the help of mediaConnector in the following manner. This function connects the source to the target.

mediaConnector.Connect(microphone, speaker);

The device can be started with the following lines. This can always be called in the code.

microphone.Start();
speaker.Start();

After this, we should accomplish that the program should not close itself. This can be accessed by querying a simple line. The connection established between the devices should be terminated. The mediaConnector Dispose method terminates all connections.

Console.ReadLine();
mediaConnector.Dispose();

Stop, similarly to Start can be called any time. Using Stop, you stop the sending/receiving of data.

microphone.Stop();
speaker.Stop();

It is essential to terminate the operation of the media devices. You can do this in the following way, just like in the case of mediaConnector:

microphone.Dispose();
speaker.Dispose();

2. static void MP3ToSpeaker()

In the example below, we will play the mp3 file with the Speaker.

Objects

The following objects should be created: an mp3Player, a Speaker and a mediaConnector.

MP3StreamPlayback mp3Player;
Speaker speaker;
MediaConnector mediaConnector;

We use the default constructor of the MP3StreamPlayback class in which first you should provide the path and then the file name. If you only provide a file name, it will look for the file in the default directory. The other object should be provided as before:

MP3StreamPlayback mp3Player = new MP3StreamPlayback("../../Resources/test.mp3");
Speaker speaker = Speaker.GetDefaultDevice();
mediaConnector = new MediaConnector();

Connecting the objects

You can play the mp3 file with the Speaker in the following manner. You establish the connection as it can be seen above.

mediaConnector.Connect(mp3Player, speaker);

The devices should be started in a similar manner:

mp3Player.Start();

You can stop the devices similarly:

mp3Player.Stop();

3. static void MicrophoneAndMP3ToSpeaker()

In this example, we will play the recorded audio and the mp3 file with the Speaker at the same time.

Objects

You should create the following objects: a microphone, an mp3Player, a Speaker and a mediaConnector.

Microphone microphone;
MP3StreamPlayback mp3Player;
Speaker speaker;
MediaConnector mediaConnector;

The objects mentioned above are used in a similar way. If you wish to connect a medium coming from multiple sources to another one, you should have connect them one by one. This will ensure that the audio of the mp3 and that of the Microphone will be mixed.

mediaexception
Figure 1 - MediaException

microphone = Microphone.GetDefaultDevice();
MP3StreamPlayback mp3Player = new MP3StreamPlayback("../../Resources/test.mp3");
Speaker speaker = Speaker.GetDefaultDevice();
mediaConnector = new MediaConnector();

Connecting objects

You can play the audio of what you recorded with the Microphone and the mp3 file with the Speaker in the following manner. You should connect the microphone and the mp3Player to the speaker. The mediaConnector will maintain the connection between the source and the target.

mediaConnector.Connect(microphone, speaker);
mediaConnector.Connect(mp3Player, speaker);

4. static void TextToSpeaker()

In the example below, the text provided by the user will be read out loud.

Objects

You should create a TextToSpeech, a Speaker and a mediaConnector objects.

Speaker speaker;
TextToSpeech textToSpeech;
MediaConnector mediaConnector;

The objects mentioned in this section are used just like it is explained above. The default constructor of TextToSpeech should be called. This will convert the text to audio.

speaker = Speaker.GetDefaultDevice();
textToSpeech = new TextToSpeech();
mediaConnector = new MediaConnector();

Connecting the objects

You can connect the objects similarly.

mediaConnector.Connect(textToSpeech, speaker);

Adding the text you wish to have read:

textToSpeech.AddAndStartText("Please read this text.");

5. static void RecordVoice()

In the example below, we will save the the content recorded by the microphone in a wav file.

Objects

You should create a microphone and a mediaConnector objects. The objects mentioned in this section are used just like it is explained above.

Microphone microphone = Microphone.GetDefaultDevice();
MediaConnector mediaConnector = new MediaConnector();

You will need a WaveStreamRecoder object as well. With this, you can record the voice which will be saved in a file provided as a parameter.

var recorder = new WaveStreamRecorder("../../Resources/" + filename);

Connecting the objects

You can connect the objects similarly.

mediaConnector.Connect(microphone, recorder);

And finally start the recording.

recorder.Start();

6. static void CameraToMPEG4()

In the example below, we will save the the content recorded by the webcamera in an mp4 file.

Objects

You should create the following objects: a Microphone, a Speaker and a mediaConnector.

WebCamera webCamera;
Microphone microphone;
MPEG4Recorder mpeg4Recorder;
MediaConnector mediaConnector;

The default constructor of MPEG4Recorder class works in a similar way as the MP3StreamPlayback does. The others work as described above.

webCamera = WebCamera.GetDefaultDevice();
microphone = Microphone.GetDefaultDevice();
mpeg4Recorder = new MPEG4Recorder("../../Resources/test.mp4");
mediaConnector = new MediaConnector();

Connecting the objects

The webCamera should be connected to the video part of the mpeg4Recorder and the Microphone should be connected to the audio part of the mpeg4Recorder in the previously described manner.

mediaConnector.Connect(webCamera, mpeg4Recorder.VideoRecorder);
mediaConnector.Connect(microphone, mpeg4Recorder.AudioRecorder);

You should make it write what happens at the moment and determine the length of the video you wish to record in miliseconds. You can do this using the Thread.Sleep() command. After the recording is made, you should stop the devices in the manner we described before.

Console.WriteLine("Mpeg4 recording started.");
Thread.Sleep(5000);
Console.WriteLine("Multiplexing in progress.");

After the recording is finished, you should do the multiplexing. Multiplexing is necessary because the recording of the audio and that of the video bands take place separately. As a result of this process, the two bands will be converted into one and thus create an mp4 file. You should subscribe to the ending of the multiplexing event this way:

mpeg4Recorder.MultiplexFinished += (sender, e) => {
                                                      mpeg4Recorder.Dispose();
                                                      Console.WriteLine("The mpeg4 is ready.");
                                                  };
mpeg4Recorder.Multiplex();
Console.ReadLine();

Attaching MediaHandlers to calls

As you can see, MediaHandlers can be connected to each other, so you can hear your voice through a microphone, from a speaker (for example). In the case, if you would like to send your voice through a microphone to the called party's speaker, you have to attach the MediaHandlers to the call.

The following example will introduce how to send voice data through a microphone, to the other party's speaker.
Things, you'll need:

  • a Microphone object (called "microphone" in this example)
  • a PhoneCallAudioSender object (called "mediaSender" in this example). If you would like to send video data, you have to use a PhoneCallVideoSender object. To learn more about media senders and receivers, please visit the Ozeki VoIP SIP SDK Refecence documentation.
  • an IPhoneCall object, which is the call itself (called "call" in this example)
  • a MediaConnector object (called "connector" in this example)

Please note that, you need to set up the call object itself too (phone line, events etc.), if you would like to test it. You can find examples about setting up call objects and much more at the Making and accepting calls chapter.

As you can see below, you have to connect the Microphone object to the PhoneCallAudioSender oject, and you have to Attach the PhoneCallAudioSender object to the IPhoneCall:

	// Connecting the microphone to the mediaSender
	connector.Connect(microphone, mediaSender); 
	
	// Attaching the mediaSender to the call
	mediaSender.AttachToCall(call);

Related Pages

More information