Browse
 
Tools
Rss Categories

Using CPA on a Voice Platform

Reference Number: AA-02277 Views: 98 0 Rating/ Voters

Asterisk

To use CPA on Asterisk, you must make of use the Asterisk-UniMRCP modules (see our Asterisk documentation article for details). CPA does not work with the older, deprecated "connector bridge" module (res_speech_lumenvox.so). 

Once UniMRCP is installed and working within Asterisk, CPA and tone detection works just like any other speech Asterisk application. As mentioned in our Asterisk documentation, there are two methods for performing ASR in Asterisk: MRCPRecog() and SpeechBackground(). Depending on which method you prefer to use, your code will look a little different. 

CPA with SpeechBackground

Here is a very simple dialplan to perform CPA with SpeechBackground. This assumes you have a CPA grammar in /etc/grammars/ called cpa.grxml

[simple-cpa-example] 
exten => s,1,Answer() 
exten => s,n,SpeechCreate() 


exten => s,n,SpeechLoadGrammar(cpa,/etc/grammars/cpa.grxml)
exten => s,n,SpeechActivateGrammar(cpa)
exten => s,n,SpeechBackground(silence,10) 


exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Human Residence"]?Live)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Human Business"]?Live)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Unknown Silence"]?Machine)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Unknown Speech"]?Machine) 


exten => s,n(Live),Playback(you-are-a-human) 
exten => s,n,Hangup 
 
exten => s,n(Machine),Playback(you-are-a-machine) 
exten => s,n,Hangup 

As you can see, this application loads the CPA grammar, activates it, calls SpeechBackground, checks the result, and performs a goto based on the return. 

Tone detection with SpeechBackground

Here is a very simple dialplan to perform tone detection with SpeechBackground. This assumes you have a tone detection grammar in /etc/grammars/ called tone_detect.grxml

[simple-amd-example] 
exten => s,1,Answer() 
exten => s,n,SpeechCreate() 
 
exten => s,n,SpeechLoadGrammar(tone_detect,/etc/grammars/tone_detect.grxml)
exten => s,n,SpeechActivateGrammar(tone_detect)
exten => s,n,SpeechBackground(greeting,60) 
 
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "AMD"]?Machine)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "FAX"]?Fax)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "SIT"]?SIT) 
 
exten => s,n(Machine),Playback(you-are-a-machine)
exten => s,n,Hangup 
 
exten => s,n(Fax),Hangup 
 
exten => s,n(SIT),Hangup 

The application loads the grammar, activates it, and calls SpeechBackground. It then evaluates the return and plays a message out if a tone is detected and hangs up if a fax or SIT is detected. 

CPA and Tone Detection with MRCPRecog

Using CPA with MRCPRecog is practically a single line: 

[MRCPRecog CPA] 
exten => s,n,MRCPRecog(/etc/grammars/cpa.grxml

The application would simply need to evaluate the contents of the ${RECOG_RESULT} channel variable, as described in our documentation on MRCPRecog

The tone detection example looks similar: 

exten => s,n,MRCPRecog(/etc/grammars/tone_detection.grxml

However, as we note in our introduction to Asterisk speech development article, the MRCPRecog() application currently returns an NLSML-formatted XML string that the application must parse. For that reason, it may be easier for CPA developers to favor SpeechBackground until that issue is resolved. 

Mixing Tone Detection and CPA

There are several ways to mix tone detection and CPA together. Here is a sample with comments included: 

[simple-cpa-plus-tone-detection-example]
exten => s,n,SpeechCreate() 
 
; Load our grammars
exten => s,n,SpeechLoadGrammar(cpa,/etc/grammars/cpa.gram)
exten => s,n,SpeechLoadGrammar(tone_detect,/etc/grammars/tone_detect.grxml
 
; We are going to use both for the initial prompt
exten => s,n,SpeechActivateGrammar(cpa)
exten => s,n,SpeechActivateGrammar(tone_detect) 
 
; We want to play silence at first as we listen to the initial greeting
exten => s,n,SpeechBackground(silence,10) 
 
; SpeechBackground returns and we deactivate both grammars
exten => s,n,SpeechDeactivateGrammar(cpa)
exten => s,n,SpeechDectivateGrammar(tone_detect) 


; We now evaluate the result
; If we got a tone, act accordingly
exten => s,n(toneDetected),GotoIf($[ ${SPEECH_TEXT(0) = "AMD"]?AMD)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "FAX"]?Fax)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "SIT"]?SIT) 
 
; If it's a live human, we act accordingly
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Human Residence"]?Live)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Human Business"]?Live) 
 
; If it's not a live human, we're going to wait for a tone to be detected
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Unknown Silence"]?WaitForMachine)
exten => s,n,GotoIf($[ ${SPEECH_TEXT(0) = "Unknown Speech"]?WaitForMachine) 
 
; This is our WaitForMachine area. Here we're just going to wait for a tone while playing silence
exten => s,n,SpeechActivateGrammar(tone_detect)
exten => s,n,SpeechBackground(silence,120)
exten => s,n,DeactivateGrammar(tone_detect)
exten => s,n,Goto(toneDetected) 
 
; Here's where we would do something for a human
; Start writing your custom application here:
exten => s,n(Live),Playback(you-are-a-human) 
exten => s,n,Hangup 
 
; Here we can leave a customized message for an answering machine
exten => s,n(AMD),Playback(you-are-a-machine) 
exten => s,n,Hangup 
 
; Just hangup on a Fax or SIT
exten => s,n(Fax),Hangup
exten => s,n(SIT),Hangup 



Avaya Aura Experience Portal

LumenVox and Avaya have tested CPA on Avaya Aura Experience Portal versions 6 and later. CPA and tone detection work as described. You can follow the instructions in the VXML Platforms section below, for sample code that has been tested on AAEP. 


VXML Platforms

Simple CPA VXML 

The following VoiceXML code should work on any VXML platform: 

<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.w3.org/2001/vxml
                 http://www.w3.org/TR/voicexml20/vxml.xsd"> 


    <form id="main">
<property name="completetimeout" value="1200ms"/>
<property name="incompletetimeout" value="10s"/>
<property name="maxspeechtimeout" value="10s"/>
<property name="timeout" value="10s"/>
<field name="CPAValue">
  <grammar src="cpa.grxml" type="application/srgs+xml"/>
</field>
<filled>
  <prompt>
              We detected a
              <value expr="application.lastresult$.interpretation"/>
  </prompt>
  <exit />
</filled> 
    </form>
</vxml>

This VXML relies on the following grammar being stored on the same server as the VXML file: 

<?xml version='1.0'?> 

<!-- ********************************************************************** -->
<!-- This is a special grammar used to switch decode modes to Call Progress
     Analysis mode                                                          --> 

<grammar xml:lang="en-US" version="1.0" root="root" mode="voice"
          xmlns="http://www.w3.org/2001/06/grammar"
          tag-format="semantics/1.0.2006">  

<!-- ************************************************************** -->
<!-- This value changes the detection mode to Call Progress Analysis -->
<!-- ************************************************************** -->
<meta name="STREAM|DETECTION_MODE" content="CPA"/> 


<!-- ************************************************************** -->
<!-- These values may be changed to customize CPA timeouts for 
             certain states                                                 -->
<!-- ************************************************************** -->
<meta name="STREAM|CPA_HUMAN_RESIDENCE_TIME"  content="1800"/>
<meta name="STREAM|CPA_HUMAN_BUSINESS_TIME"  content="3000"/>
<meta name="STREAM|CPA_UNKNOWN_SILENCE_TIMEOUT" content="5000"/>
<!-- ************************************************************** -->
<!-- These values may be changed to modify the semantic
             interpretations returned                                       -->
<!-- ************************************************************** --> 

<meta name="HUMAN_RESIDENCE_CUSTOM_INPUT_TEXT"
            content="HUMAN RESIDENCE"/>
<meta name="HUMAN_BUSINESS_CUSTOM_INPUT_TEXT"
            content="HUMAN BUSINESS"/>
<meta name="UNKNOWN_SPEECH_CUSTOM_INPUT_TEXT"
            content="UNKNOWN SPEECH"/>
<meta name="UNKNOWN_SILENCE_CUSTOM_INPUT_TEXT"
            content="UNKNOWN SILENCE"/>    
<rule id="root" scope="public">
    <one-of>
        <item>HUMAN RESIDENCE<tag>out="RESIDENCE"</tag>
        </item>
        <item>HUMAN BUSINESS<tag>out="BUSINESS"</tag>
        </item>
        <item>UNKNOWN SPEECH<tag>out="MACHINE"</tag>
        </item>
        <item>UNKNOWN SILENCE<tag>out="SILENCE"</tag>
        </item> 
    </one-of>
</rule> 
</grammar>


Simple Tone Detection VXML

The following is a very simple VXML script to do tone detection: 

<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/2001/vxml
    http://www.w3.org/TR/voicexml20/vxml.xsd">
  
    <form id="main">
<property name="timeout"   value="120s"/>
<property name="completetimeout"  value="120s"/>
<property name="incompletetimeout"  value="120s"/>
<property name="maxspeechtimeout"  value="120s"/> 

<field name="toneDetection">
    <grammar src="tone_detection.grxml" type="application/srgs+xml"/>
    <prompt>
        You can customize an outbound message here.     
    </prompt>
    <catch event="noinput">
        <exit />
    </catch>
</field> 

<filled>
    <prompt>      
        A tone was detected. Here is where you could customize
        a message to be left on a voicemail.
    </prompt>
    <exit />
</filled>
    </form>               
</vxml>

It depends on having the following grammar as tone_detection.grxml in the same location as the VXML document: 

<?xml version='1.0'?> 


<!-- ****************************************************************** -->
<!-- special grammar used to switch decode modes to tone detection mode -->
<!-- ****************************************************************** -->

<grammar xml:lang="en-US" version="1.0" root="root" mode="voice"
          xmlns="http://www.w3.org/2001/06/grammar"
          tag-format="semantics/1.0.2006">  

<!-- ************************************************************ -->
<!-- This value changes the detection mode to tone detection mode -->
<!-- ************************************************************ -->
<meta name="STREAM|DETECTION_MODE"  content="Tone"/> 

<!-- ************************************************************ -->
<!-- Activate/Deactivate AMD, FAX, SIT detection                  -->
<!-- ************************************************************ -->
<meta name="AMD_CUSTOM_ENABLE"   content="true"/>
<meta name="FAX_CUSTOM_ENABLE"   content="true"/>
<meta name="SIT_CUSTOM_ENABLE"   content="true"/>
<!-- ************************************************************ -->
<!-- These values may be changed to modify the semantic
             interpretations returned -->
<!-- ************************************************************ --> 

<!--
         The below meta tags map each state (AMD/FAX/SIT) to an input
         text in the SRGS grammar below. This is the mechanism used to map
         each of the states to an input text in the grammar.
  **************************************************************** --> 

<meta name="AMD_CUSTOM_INPUT_TEXT"    content="AMD"/>
<meta name="FAX_CUSTOM_INPUT_TEXT"    content="FAX"/> 

<meta name="SIT_REORDER_LOCAL_CUSTOM_INPUT_TEXT"
            content="SIT REORDER LOCAL"/>
<meta name="SIT_VACANT_CODE_CUSTOM_INPUT_TEXT"
            content="SIT VACANT CODE"/>
<meta name="SIT_NO_CIRCUIT_LOCAL_CUSTOM_INPUT_TEXT"
            content="SIT NO CIRCUIT LOCAL"/>
<meta name="SIT_INTERCEPT_CUSTOM_INPUT_TEXT"
            content="SIT INTERCEPT"/>
<meta name="SIT_REORDER_DISTANT_CUSTOM_INPUT_TEXT"
            content="SIT REORDER DISTANT"/> 

<meta name="SIT_NO_CIRCUIT_DISTANT_CUSTOM_INPUT_TEXT"
            content="SIT NO CIRCUIT DISTANT"/>
<meta name="SIT_OTHER_CUSTOM_INPUT_TEXT"
            content="SIT OTHER"/>   

<!--
         Below is the SRGS grammar. If the input text is changed in any
         of them, the appropriate changes need to be made to the above
         states to input text mapping. The semantic interpretation can
         be changed as necessary by modifying the out tags below.
*********************************************************** -->
<rule id="root" scope="public">
    <one-of>
        <item>AMD<tag>out="AMD"</tag>
        </item>
        <item>FAX<tag>out="FAX"</tag>
        </item>
        <item>SIT REORDER LOCAL<tag>out="SIT"</tag>
        </item>
        <item>SIT VACANT CODE<tag>out="SIT"</tag>
        </item>
        <item>SIT NO CIRCUIT LOCAL<tag>out="SIT"</tag>
        </item>
        <item>SIT INTERCEPT<tag>out="SIT"</tag>
        </item>
        <item>SIT REORDER DISTANT<tag>out="SIT"</tag>
        </item>
        <item>SIT NO CIRCUIT DISTANT<tag>out="SIT"</tag>
        </item>
        <item>SIT OTHER<tag>out="SIT"</tag>
        </item>
    </one-of>
</rule>
</grammar> 


Attachments
cpa.grxml 2.1 Kb Download File
simple-amd-example.txt 566 b Download File
Simple-AMD.vxml 942 b Download File
simple-cpa-example.txt 654 b Download File
simple-cpa-plus-tone-detection-example.txt 1.9 Kb Download File
Simple-CPA.vxml 756 b Download File
tone_detection.grxml 3.4 Kb Download File