How to generate a tone with specified frequency in C#

For sending and receiving Contact ID alerts by using your C# application, you need to generate and detect DTMF (Dual Tone Multi Frequency) signals. This article focuses on the beginning of this process, so it describes how to generate a specified frequency tone in C# using Ozeki VoIP SIP SDK.

To use this example, you need to have an Ozeki VoIP SIP SDK installed, and a reference to ozeki.dll should be added to your Visual Studio project.

What is the frequency tone generation? When is it needed?

During the communication using Contact ID protocol, you can send and receive different kind of frequencies, such as handshake and kissoff. (For more information please visit the Contact ID protocol page.) These frequency tones can be generated by using the frequency generator. The following example presents how to use this generator that can be used to generate any frequencies. This way, you can even create your own protocol if you want.

How to implement a specified frequency tone generator using C#?

In order to avoid the distortion of the DTMF frequencies during the communication with the Contact ID protocol, you need to use a codec applying lossless compression. It is recommended to use PCMA or PCMU codecs. It can be seen in lines 26-30.

This example sends the generated frequency through a VoIP call. You can detect this frequency by using the Frequency tone detection example program. For better understanding it is needed to be able to make a call. You can learn more in this topic at the How to make a SIP voice call using C# page.

You need a FrequencyToneGenerator type object, and you need to call its Generate() method. This method has two parameters: with the first one you can define what kind of frequencies you want to generate (how many Hz), and the second specifies the lenght of that frequency (duration).

In order to ensure that the tone generation works properly, the frequencyToneGenerator object should be connected to the phoneCallAudioSender object when the call is established. This ensures that the outgoing communication will be carried out through the frequencyToneGenerator.

After that, you need to run the frequencyToneGenerator, so you need to call the Start() method. When the call is finished, you need to disconnect the established connections, and stop the frequencyToneGenerator by calling the Stop() method.

Frequency tone generator example in C#

using System;
using Ozeki.Media;
using Ozeki.VoIP;


namespace FrequencyToneGeneration
{
    class Program
    {
        static ISoftPhone softphone; // softphone object
        static IPhoneLine phoneLine; // phoneline object
        static IPhoneCall call; // call object

        static PhoneCallAudioSender phoneCallAudioSender;
        static MediaConnector mediaConnector;
        static FrequencyToneGenerator frequencyToneGenerator;

        private static void Main(string[] args)
        {
            // Create a softphone object with RTP port range 5000-10000
            softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000);

            foreach (var s in softphone.Codecs)
            {
                softphone.DisableCodec(s.PayloadType);
            }
            softphone.EnableCodec(8); //only PCMA codec enabled

            // SIP account registration data, (supplied by your VoIP service provider)
            var registrationRequired = true;
            var userName = "sipusername"; //1000
            var displayName = "sipdisplayname"; //1000
            var authenticationId = "authenticationid"; //1000
            var registerPassword = "Password"; //1000
            var domainHost = "pbxip.voipprovider.com";
            var domainPort = 5060;

            var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort);

            // Send SIP regitration request
            RegisterAccount(account);

            mediaConnector = new MediaConnector();
            phoneCallAudioSender = new PhoneCallAudioSender();

            frequencyToneGenerator = new FrequencyToneGenerator();
            frequencyToneGenerator.Generate(1400, 5000); // generate an 1400Hz frequency tone, 5 second duration

            // prevents the termination of the application
            Console.ReadLine();
        }

        static void RegisterAccount(SIPAccount account)
        {
            try
            {
                phoneLine = softphone.CreatePhoneLine(account);
                phoneLine.RegistrationStateChanged += sipAccount_RegStateChanged;
                softphone.RegisterPhoneLine(phoneLine);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error during SIP registration: " + ex);
            }
        }

        private static void sipAccount_RegStateChanged(object sender, RegistrationStateChangedArgs e)
        {
            if (e.State == RegState.Error)
                Console.WriteLine("Registration failed!");

            if (e.State == RegState.RegistrationSucceeded)
            {
                Console.WriteLine("Registration succeeded - Online!");
                CreateCall();
            }
        }

        static void CreateCall()
        {
            var numberToDial = "1001";
            call = softphone.CreateCallObject(phoneLine, numberToDial);
            call.CallStateChanged += call_CallStateChanged;
            call.Start();   // SIP INVITE request is being sent
        }

        static void call_CallStateChanged(object sender, CallStateChangedArgs e)
        {
            Console.WriteLine("Call state: {0}.", e);

            if (e.State == CallState.Answered)
                SetupDevices(); // set up the devices by calling the proper method

            if (e.State == CallState.Completed)
                StopDevices(); // detach and disconnect the devices by calling the proper method
        }

        static void SetupDevices()
        {
            phoneCallAudioSender.AttachToCall(call); // attach the phoneCallAudioSender to the call
            mediaConnector.Connect(frequencyToneGenerator, phoneCallAudioSender);
            frequencyToneGenerator.Start(); //start the timer
        }

        static void StopDevices()
        {
            frequencyToneGenerator.Stop();
            mediaConnector.Disconnect(frequencyToneGenerator, phoneCallAudioSender);
            phoneCallAudioSender.Detach();
        }
    }
}

Related Pages

More information