Decoding
Once you have activated your grammars and
sent audio to a channel on the speech port, you can begin decoding.
The decode process sends audio and grammars to the Engine to be decoded for meaning.
Batched Audio
When using audio that is sent directly into a speech port's voice channel, you can explicitly
call Decode, and wait for results to come back:
C Code
HPORT hport;
// If you wish to use the LumenVox Semantic Interpretation process
// this flag needs to be present.
unsigned long flags = LV_DECODE_SEMANTIC_INTERPRETATION;
// voice_channel is wherever you loaded the audio
int voice_channel = 1;
// you should use the LV_ACTIVE_GRAMMAR_SET if you are using SRGS grammars.
// It is the grammar set that holds all of your active grammars.
int grammar_set = LV_ACTIVE_GRAMMAR_SET;
// wait a max of 3 seconds before abandoning hope for the Engine to return an answer
int timeout = 3000;
if (code == LV_TIME_OUT) {
// do some clean up and exit
}else{
// process the answers contained in the voice channel
}
C++ Code
LVSpeechPort port;
unsigned long flags = LV_DECODE_SEMANTIC_INTERPRETATION;
int voice_channel = 1;
int grammar_set = LV_ACTIVE_GRAMMAR_SET;
int timeout = 3000;
port.
Decode(voice_channel, grammar_set, flags
);
if (code == LV_TIME_OUT) {
// do some clean up and exit
} else {
// process the answers contained in the voice channel
}
If you are streaming the audio into the speech port, you can elect to have the speech port handle
the decode process automatically, as we did in the section on
adding audio when we wrote the line:
port.SetStreamParameter(STREAM_PARM_AUTO_DECODE,1);
In order to wait for the Engine to return with results, we need to modify the callback function:
C++ Code
void ProcessResults(SimpleRecognizer* reco)
{
reco->audio.StopStream();
int code = reco->port.WaitForEngineToIdle(3000, voice_channel);
if (code == LV_TIME_OUT) {
// do some clean up and exit
}else{
// process the answers contained in the voice channel
}
}
static void PortCB(long new_state, unsigned long total_bytes,
unsigned long recorded_bytes, void* user_data)
{
SimpleRecognizer* self = (SimpleRecognizer*)user_data;
switch (new_state)
{
case STREAM_STATUS_READY:
self->audio.StartStream(AudioCB,self);
break;
case STREAM_STATUS_STOPPED:
case STREAM_STATUS_END_SPEECH:
ProcessResults(self);
break;
case STREAM_STATUS_BARGE_IN:
//stop playing prompt
break;
}
}
Getting The Return Value
When WaitForEngineToIdle returns successfully, you can get answers out of the port. If you are using
semantic interpretation inside of
your grammar, you retrieve LVInterpretation objects (see
Using the Interpretation Object).
The decode results will remain available for a given channel until another interaction occurs with
the audio in that channel.
C Code
if (code == LV_TIME_OUT)
// do some clean up and exit
}
else
{
for (int i = 0; i < num_interp; ++i)
{
printf("interpretation %i:\n", i);
printf("utterance matched grammar %s with confidence %i\n",grammar,score);
// contained in this interpretation object by example
// release the interpretation handle when finished with it
}
}
C++ Code
if (code == LV_TIME_OUT){
// do some clean up and exit
}
else
{
for (int i = 0; i < num_interp; ++i)
{
cout <<"interpretation "<< i <<":"<<endl;
int score
= interp.
Score( );
cout <<"utterance matched grammar "<<grammar<<" with confidence "<<score<<endl;
// contained in this interpretation object by example
}
}
If you are not using semantic interpretation, you can receive LVParseTree objects from the Engine
(see Using the Parse Tree).
C Code
if (code == LV_TIME_OUT) {
// do some clean up and exit
}
else
{
for (int i = 0; i < num_parses; ++i)
{
printf("interpretation %i:\n", i);
// the parse tree by example
// release the parse tree when finished with it
}
}
C++ Code
if (code == LV_TIME_OUT) {
// do some clean up and exit
}
else
{
for (int i = 0; i < num_parses; ++i)
{
cout <<"interpretation "<< i <<":"<<endl;
// the parse tree by example
}
}
See Also