Avoiding clipping with outbound UCMA calls

One of the more common uses of UCMA is to create outbound dialer applications. Unfortunately, many people run into a frustrating problem at first when building dialers in UCMA: the first few seconds of audio seem to get lost somehow. When someone picks up the phone and says "Hello," the first few seconds of audio back to the dialer get clipped, and there is often a delay before the recipient of the call hears the UCMA application play its message. This leads to a whole host of serious problems:

  • Delays in playing the message with an outbound dialer can lead to legal issues.
  • Clipping of the first few seconds of audio can mess up voicemail detection.
  • Calls that are recorded, where laws permit, end up missing the first few seconds of audio.

Luckily, there is a solution for this problem that will work in most cases, depending on how your PSTN gateway or SIP trunk is configured. The solution uses early media, which was the subject of a previous post that dealt mainly with inbound calls. As a bonus, it will also allow you to hear the sounds from the PSTN while the call is being connected (ringing, busy signals, etc.).

The first step is to create an event handler for the AudioVideoFlowConfigurationRequested event, before you call BeginEstablish on your new outbound AudioVideoCall object. While you're at it, you can also create an event handler for ProvisionalResponseReceived, so that you can take a look at the 183 response that kicks off early media.

Here's an example of the code to subscribe to the events:

[csharp] avCall.ProvisionalResponseReceived +=new EventHandler< CallProvisionalResponseReceivedEventArgs>( OnProvisionalResponseReceived); avCall.AudioVideoFlowConfigurationRequested += new EventHandler( OnAudioVideoFlowConfigurationRequested);

try { avCall.BeginEstablish("tel:+10000000000", null, establishAsyncResult => { try { avCall.EndEstablish(establishAsyncResult); } catch (RealTimeException ex) { Console.WriteLine(ex); } }, null); } catch (InvalidOperationException ex) { Console.WriteLine(ex); } [/csharp]

The reason you need this AudioVideoFlowConfigurationRequested event is that the Flow property on an AudioVideoCall instance will be null when the AudioVideoCall object is first created. Needless to say, this makes it a bit challenging to subscribe to events on the AudioVideoFlow. When the flow is instantiated, the UCMA runtime calls this AudioVideoFlowConfigurationRequested event, allowing you to hook up event handlers or do whatever else you need to do to the flow.

In our case, what we want to do in the event handler is simple: subscribe a new event handler to watch for state changes in the flow:

[csharp] void OnAudioVideoFlowConfigurationRequested(object sender, AudioVideoFlowConfigurationRequestedEventArgs e) { Console.WriteLine("flow configuration requested"); e.Flow.StateChanged += new EventHandler(OnFlowStateChanged); } [/csharp]

So what do we do when the flow state changes? Well, here's an example event handler:

[csharp] void OnFlowStateChanged(object sender, MediaFlowStateChangedEventArgs e) { Console.WriteLine("Flow state changed from {0} to {1}", e.PreviousState, e.State);

if (e.State == MediaFlowState.Active) { AudioVideoFlow flow = sender as AudioVideoFlow;

// Audio is flowing between application and // call recipient, so play a message or whatever } else if (e.State == MediaFlowState.Terminated) { if (_recorder.State == RecorderState.Started) { _recorder.Stop(); } } } [/csharp]

And just for good measure, here's an event handler for ProvisionalResponseReceived, to show you when a provisional response comes in offering early media:

[csharp] void OnProvisionalResponseReceived(object sender, CallProvisionalResponseReceivedEventArgs e) { if (e.IsEarlyMedia) { Console.WriteLine("early media offer"); } } [/csharp]

If you place an outbound call to a PSTN number with these event handlers in place, and do whatever it is that your dialer does in the OnFlowStateChanged event when the flow becomes active, you'll eliminate that troublesome delay in every case where your PSTN infrastructure supports early media.

Leave a comment if you have questions!