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

  1. HPORT hport;
  2.  
  3. // If you wish to use the LumenVox Semantic Interpretation process
  4. // this flag needs to be present.
  5. unsigned long flags = LV_DECODE_SEMANTIC_INTERPRETATION;
  6.  
  7. // voice_channel is wherever you loaded the audio
  8. int voice_channel = 1;
  9.  
  10. // you should use the LV_ACTIVE_GRAMMAR_SET if you are using SRGS grammars.
  11. // It is the grammar set that holds all of your active grammars.
  12. int grammar_set = LV_ACTIVE_GRAMMAR_SET;
  13.  
  14. // wait a max of 3 seconds before abandoning hope for the Engine to return an answer
  15. int timeout = 3000;
  16.  
  17. LV_SRE_Decode(hport, voice_channel, grammar_set, flags);
  18.  
  19. int code = LV_SRE_WaitForEngineToIdle(hport,timeout,voice_channel);
  20.  
  21. if (code == LV_TIME_OUT) {
  22. // do some clean up and exit
  23. }else{
  24. // process the answers contained in the voice channel
  25. }

C++ Code

  1. LVSpeechPort port;
  2.  
  3. unsigned long flags = LV_DECODE_SEMANTIC_INTERPRETATION;
  4. int voice_channel = 1;
  5. int grammar_set = LV_ACTIVE_GRAMMAR_SET;
  6. int timeout = 3000;
  7.  
  8. port.Decode(voice_channel, grammar_set, flags);
  9. int code = port.WaitForEngineToIdle(timeout,voice_channel);
  10.  
  11. if (code == LV_TIME_OUT) {
  12. // do some clean up and exit
  13. } else {
  14. // process the answers contained in the voice channel
  15. }

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

  1. void ProcessResults(SimpleRecognizer* reco)
  2. {
  3. reco->audio.StopStream();
  4. int code = reco->port.WaitForEngineToIdle(3000, voice_channel);
  5.  
  6. if (code == LV_TIME_OUT) {
  7. // do some clean up and exit
  8. }else{
  9. // process the answers contained in the voice channel
  10. }
  11. }
  12.  
  13. static void PortCB(long new_state, unsigned long total_bytes,
  14. unsigned long recorded_bytes, void* user_data)
  15. {
  16. SimpleRecognizer* self = (SimpleRecognizer*)user_data;
  17. switch (new_state)
  18. {
  19. case STREAM_STATUS_READY:
  20. self->audio.StartStream(AudioCB,self);
  21. break;
  22. case STREAM_STATUS_STOPPED:
  23. case STREAM_STATUS_END_SPEECH:
  24. ProcessResults(self);
  25. break;
  26. case STREAM_STATUS_BARGE_IN:
  27. //stop playing prompt
  28. break;
  29. }
  30. }

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

  1. if (code == LV_TIME_OUT)
  2. // do some clean up and exit
  3. }
  4. else
  5. {
  6. int num_interp = LV_SRE_GetNumberOfInterpretations(hport,voice_channel);
  7. for (int i = 0; i < num_interp; ++i)
  8. {
  9. printf("interpretation %i:\n", i);
  10. H_SI interp = LV_SRE_CreateInterpretation(hport,voice_channel,i);
  11.  
  12. const char* grammar = LVInterpretation_GetGrammarLabel(interp);
  13. int score = LVInterpretation_GetScore(interp);
  14.  
  15. printf("utterance matched grammar %s with confidence %i\n",grammar,score);
  16.  
  17. // See "Using the Interpretation Object" to see how to handle the semantic data
  18. // contained in this interpretation object by example
  19.  
  20. // release the interpretation handle when finished with it
  21. }
  22. }

C++ Code

  1. if (code == LV_TIME_OUT){
  2. // do some clean up and exit
  3. }
  4. else
  5. {
  6. int num_interp = port.GetNumberOfInterpretations(voice_channel);
  7. for (int i = 0; i < num_interp; ++i)
  8. {
  9. cout <<"interpretation "<< i <<":"<<endl;
  10. LVInterpretation interp = port.GetInterpretation(voice_channel,i);
  11.  
  12. const char* grammar = interp.GrammarLabel( );
  13. int score = interp.Score( );
  14.  
  15. cout <<"utterance matched grammar "<<grammar<<" with confidence "<<score<<endl;
  16.  
  17. // See "Using the Interpretation Object" to see how to handle the semantic data
  18. // contained in this interpretation object by example
  19.  }
  20. }

If you are not using semantic interpretation, you can receive LVParseTree objects from the Engine (see Using the Parse Tree).

C Code

  1. if (code == LV_TIME_OUT) {
  2. // do some clean up and exit
  3. }
  4. else
  5. {
  6. int num_parses = LV_SRE_GetNumberOfParses(hport,voice_channel);
  7. for (int i = 0; i < num_parses; ++i)
  8. {
  9. printf("interpretation %i:\n", i);
  10. H_PARSE_TREE parse = LV_SRE_CreateParseTree(hport,voice_channel,i);
  11.  
  12. // See "Using the Parse Tree" to see how to handle
  13. // the parse tree by example
  14.  
  15. // release the parse tree when finished with it
  16. }
  17. }

C++ Code

  1. if (code == LV_TIME_OUT) {
  2. // do some clean up and exit
  3. }
  4. else
  5. {
  6. int num_parses = port.GetNumberOfParses(voice_channel);
  7. for (int i = 0; i < num_parses; ++i)
  8. {
  9. cout <<"interpretation "<< i <<":"<<endl;
  10. LVParseTree parse = port.GetParseTree(voice_channel,i);
  11.  
  12. // See "Using the Parse Tree" to see how to handle
  13. // the parse tree by example
  14. }
  15. }

See Also

© 2012 LumenVox LLC. All rights reserved.