Volume 6, Issue 2 - Mar/Apr 2006
 
   
 

In this monthly column, an industry expert will answer common questions about VoiceXML and related technologies. Readers are encouraged to submit questions about VoiceXML, including development, voice-user interface design, and speech technology in general, or how VoiceXML is being used commercially in the marketplace. If you have a question about VoiceXML, e-mail it to and be sure to read future issues of VoiceXML Review for the answer.

By Matt Oshry

Q: In your August 2005 column, you demonstrated how to implement a list using the
<foreach> and <mark> tags specified in VoiceXML 2.1.
What if the platform my voice application will be running on doesn't support bargein?

A: If your chosen platform is bargein-challenged, you're going to have to implement your list by
toying with the Form Interpretation Algorithm (FIA). Here's the basic algorithm for implementing
a FIA-based list:

1) Declare a variable to maintain the current index
2) Queue one item in the array at a time
3) Enter a listen state for the currently queued item
4) When a noinput event occurs, determine if you're at the end of the list. If not, increment the index
and set the interpreter's reprompt flag (by executing a &lt;reprompt&gt; tag).
otherwise, set the guard condition on the &lt;field&gt; so that field is not revisited
during the next iteration of the FIA.

Here's some code:

<vxml version="2.1"xmlns="
  http://www.w3.org/2001/vxml">

<form>
  <var name="items" expr="new Array('apple', 'orange', 'pear', 'banana')"/>
  <var name="idx" expr="0"/>

  <block name="intro">
  Here's the list of fruits.
  </block>

  <field name="choice">
    <catch event="onnext">
      <if cond="idx &lt; items.length">
        <assign name="idx" expr="idx+1"/>
        <reprompt/>
      <else/>
        that's all the items
        <assign name="choice" expr="'done'"/>
      </if>
    </catch>
                                
    <property name="timeout" value="0s"/>
    <property name="inputmodes" value="dtmf"/>
    <prompt>
      <value expr="items[idx]"/>
      <break time="300ms"/>
    </prompt>
    <grammar type="application/srgs+xml" src="empty.grxml"/>
    <nomatch>
      <reprompt/>
    </nomatch>
    <noinput>
      <throw event="onnext"/>
    </noinput>
    <filled>
      <!-- add navigation support here -->
      <log>not expected filled just yet</log>
      <clear namelist="choice"/>
    </filled>
  </field>
                                
  <field name="again" type="boolean">
    <prompt>
      wanna hear the list again?
    </prompt>
    <catch event="nomatch noinput">
      do you wanna hear the list again? say yes or no.
    </catch>
    <filled>
      <if cond="again">
        <!-- reset counter and form item -->
        <assign name="idx" expr="0"/>
        <clear namelist="choice again"/>
      <else/>
        <exit/>
      </if>
    </filled>
  </field>
</form>

</vxml>                          

Q: What if I want to allow my user to navigate through the list using commands like
'next', 'previous', 'stop', and 'repeat'?

A: Adding navigation is easy. Simply specify the commands you want to support in
a grammar, and handle those commands in a &lt;filled&gt; tag.
Be sure to provide some hints to your users so that they understand the navigation
capabilities of your list. The following example provides some simple instruction in the list
introduction. More extensive instructions are provided via a help handler.

<vxml version="2.1"
  xmlns="http://www.w3.org/2001/vxml">

<link event="help">
  <grammar type="application/srgs+xml" mode="voice" version="1.0" root="h1">
    <rule id="h1" scope="public">
      <one-of>
        <item>help</item>
      </one-of>
    </rule>
  </grammar>
</link>
                              
<form>
  <script><![CDATA[
  var items = ['apple', 'orange', 'pear', 'banana'];
  var descriptions = ['a fruit with thin skin and firm flesh that great for 
  making pies',
         'a citrus fruit great for making juice',
         'a fruit great for making classic french kla foo tee',
         'a tropical fruit that gets sweeter as it ripens'];
  var idx = 0;
  ]]></script>

  <block name="intro">
  Here's the list of fruits.
  You can say next, previous, stop, or repeat.
  </block>

  <field name="choice">
    <catch event="onnext">
      <if cond="idx &lt; items.length">
        <assign name="idx" expr="idx+1"/>
        <reprompt/>
      <else/>
        that's all the items
        <assign name="choice" expr="'done'"/>
      </if>
    </catch>
    <catch event="onprev">
      <if cond="idx &gt; 0">
        <assign name="idx" expr="idx-1"/>
        <reprompt/>
      <else/>
        you're at the beginning of the list
        <break time="300ms"/>
        <reprompt/>
      </if>
    </catch>
    <catch event="onstop">
      <!-- goto elsewhere in a real app -->
      <exit/>
    </catch>

    <property name="timeout" value="0s"/>
    <property name="bargeintype" value="hotword"/>
    <prompt>
<value expr="items[idx]"/> <break time="300ms"/> <value expr="descriptions[idx]"/> <break time="300ms"/> </prompt> <grammar type="application/srgs+xml" mode="voice" version="1.0" root="r1"> <rule id="r1" scope="public"> <one-of> <item>next</item> <item>previous</item> <item>stop</item> <item>repeat</item> </one-of> </grammar> <nomatch> Sorry. Didn't get that. <break time="300ms"/> you can say next, previous, repeat or stop to navigate through the list. <break time="300ms"/> </nomatch> <noinput> <throw event="onnext"/> </noinput> <help> you're listening to a list of fruits. to navigate through the list you can say next, previous, repeat, and stop </help> <filled> <!-- handle commands --> <if cond="choice == 'next'"> <clear namelist="choice"/> <throw event="onnext"/> <elseif cond="choice == 'previous'"/> <clear namelist="choice"/> <throw event="onprev"/> <elseif cond="choice == 'stop'"/> <throw event="onstop"/> <elseif cond="choice == 'repeat'"/> <clear namelist="choice"/> <else/> <log> unexpected choice <value expr="choice"/> </log> <assign name="choice" expr="undefined"/> <throw event="nomatch"/> </if> </filled> </field> <field name="again" type="boolean"> <prompt> wanna hear the list again? </prompt> <catch event="nomatch noinput"> do you wanna hear the list again? say yes or no. </catch> <filled> <if cond="again"> <!-- reset counter and form item --> <assign name="idx" expr="0"/> <clear namelist="choice again"/> <else/> <exit/> </if> </filled> </field> </form> </vxml>

In the above example, observe the careful manipulation of the FIA. If the user says a keyword in
the grammar (e.g. 'next'), the guard condition of the form item ('choice') is satisfied, and
the interpreter won't re-enter the corresponding &lt;field&gt; unless that form item variable
is cleared.

Q: How can I make my list DTMF accessible?

A: Simply add a DTMF grammar that supports each of the commands defined in your speech grammar.
You should beef up your prompts to educate users on the DTMF keys they can use to navigate
the list. By returning the same semantic interpretation for each item
in your DTMF grammar as in your speech grammar, you won't have to modify any of the other code in your list.

<grammar type="application/srgs+xml" mode="dtmf" version="1.0" root="r2">
<rule id="r2" scope="public">
<one-of>
<item>6<tag>next</tag></item>
<item>previous<tag>4</tag></item>
<item>* 7<tag>stop</tag></item>
<item>* 5<tag>repeat</tag></item>
</one-of>
</rule>
</grammar>

 

 


back to the top

Copyright © 2001-2006 VoiceXML Forum. All rights reserved.
The VoiceXML Forum is a program of the
IEEE Industry Standards and Technology Organization (IEEE-ISTO).