How to detect a specified frequency tone in C#

To be able to send and receive Contact ID alerts with your own C#.NET application there is a need for generating and detecting DTMF (Dual Tone Multi Frequency) signals. The following guide is intended to explain how to detect 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 detection? When is it needed?

While communicating by using the Contact ID protocol, you can send and receive such frequencies as handshake and kissoff. (Learn more about the Contact ID protocol.) These frequency tones can be detected by using the frequency detector. The following example demonstrates how to use this detector for detecting any frequencies. This way, you can even create your own protocol if you want.

This example detects the received frequency through a VoIP call. You can generate this frequency by using the Frequency tone generation example program. For better understanding it is needed to be able to accept a call. You can learn more in this topic at the Accept incoming call page.

How to implement a specified frequency detector using C#?

The DTMF frequencies may be distorted during the communication between the alarm system and the Central Station, if you do not use a codec applying lossless compression. Therefore, you need to use PCMA or PCMU codecs (check lines 26-30 below).

You need a FrequencyToneDetector type object, and you need to subscribe to the FrequencyDetected and FrequencyNotFound events.

  • When the FrequencyNotFound event occurs, it means that the detection of the frequency is failed. For instance you can received another frequency, or nothing in the timeout.
  • When the FrequencyDetected event occurs, it means that the detection of the frequency has been successful.

To achieve that the tone generation works properly, the frequencyToneDetector object should be connected to the phoneCallAudioReceiver object when the call is established. It makes it possible that the incoming communication will be carried out through the frequencyToneDetector.

Now you need to call its Detect() method. This method has two parameters: with the first one you can define what kind of frequencies you want to detect (how many Hz), and the second one specifies the lenght of the timeout (how long to wait and try to detect the specified frequency before the FrequencyNotFound state).

When the call is finished, you need to disconnect the established connections.

Frequency tone detector example in C#

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

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

        static PhoneCallAudioReceiver phoneCallAudioReceiver;
        static MediaConnector mediaConnector;
        static FrequencyToneDetector frequencyToneDetector;

        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"; //1001
            var displayName = "sipdisplayname"; //1001
            var authenticationId = "authenticationid"; //1001
            var registerPassword = "Password"; //1001
            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();
            phoneCallAudioReceiver = new PhoneCallAudioReceiver();

            frequencyToneDetector = new FrequencyToneDetector();
            frequencyToneDetector.FrequencyDetected += frequencyToneDetector_FrequencyDetected;
            frequencyToneDetector.FrequencyNotFound += frequencyToneDetector_FrequencyNotFound;

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

        static void frequencyToneDetector_FrequencyNotFound(object sender, EventArgs e)
        {
            Console.WriteLine("Frequency not found!");
        }

        static void frequencyToneDetector_FrequencyDetected(object sender, EventArgs e)
        {
            Console.WriteLine("Frequency detected!");
        }

        static void RegisterAccount(SIPAccount account)
        {
            try
            {
                phoneLine = softphone.CreatePhoneLine(account);
                softphone.IncomingCall += softphone_IncomingCall; // subscribing to the event to get notified about incoming calls
                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!");
        }

        private static void softphone_IncomingCall(object sender, VoIPEventArgs<IPhoneCall> e)
        {
            call = e.Item;  // initializes the call
            call.CallStateChanged += call_CallStateChanged; // subscribes to the event to get notified about the call's states
            
            call.Answer();  // accepts the call (sends back the 200 OK SIP message)
        }

        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.IsCallEnded())
                StopDevices(); // detach and disconnect the devices by calling the proper method
        }

        static void SetupDevices()
        {
            phoneCallAudioReceiver.AttachToCall(call); // attach the phoneCallAudioSender to the call
            mediaConnector.Connect(phoneCallAudioReceiver, frequencyToneDetector);
            frequencyToneDetector.Detect(1400, 6000); // 1400Hz in 6 second
        }

        static void StopDevices()
        {
            mediaConnector.Disconnect(phoneCallAudioReceiver, frequencyToneDetector);
            phoneCallAudioReceiver.Detach();
        }
    }
}

Related Pages

More information