Important: The information in this document is obsolete and should not be used for new development.
Building a Language Model
You specify the words and phrases you want recognized by assigning a language model to a recognizer. Listing 1-5 illustrates one way to construct a language model. It calls theSRNewLanguageModel
function to create a new empty language model and then calls other routines to add words and phrases to that model. The functionMyBuildLanguageModel
defined in Listing 1-5 constructs a language model for the BNF diagram shown on page 1-11.
The function
- IMPORTANT
- There are many other ways to create language models. For example, you might read the basic words and phrases from resources of type
'STR#'
, or you might read language objects from a resource or data file using the functionsSRNewLanguageObjectFromHandle
orSRNewLanguageObjectFromDataFile
(as shown later, in "Saving and Loading Language Objects" on page 1-35). The techniques used in Listing 1-5 are intended only to illustrate one way of building embedded language models and a top-level language model.![]()
MyBuildLanguageModel
takes an existing recognition system as a parameter. See "Opening Recognition Systems and Recognizers" on page 1-16 for information on opening recognition systems.Listing 1-5 Creating a language model
SRLanguageModel MyBuildLanguageModel (SRRecognitionSystem mySystem); /* creates a language model for the following BNF: <TopLM>= <call> <person> | schedule meeting with <person> |view today's schedule; <call>= call | phone | dial; <person>= Arlo | Brent | Matt | my wife; */ const long kTopLMRefCon = 'top '; const long kCallPersonRefCon = 'call'; const char kCallLMName[] = "<call>"; const char *kCallSynonyms[] = {"call", "phone", "dial", NULL}; const char kPersonLMName[] = "<person>"; const char *kPersonNames[] = {"Arlo", "Brent", "Matt", "my wife", NULL}; const char kTopLMName[] = "<TopLM>"; const char kScheduleMeetingWith[] = "schedulemeeting with"; const char kViewTodaysSchedule[] = "view today's schedule"; SRLanguageModel MyBuildLanguageModel (SRRecognitionSystem mySystem) { OSErr myErr = noErr; SRLanguageModelmyCallLM = 0, myPersonLM = 0, myTopLM = 0; SRPath myPath; char ** myStringArray; char * myCurrString; /* create an embedded language model named "<call>" */ myErr = SRNewLanguageModel(mySystem, &myCallLM, kCallLMName, strlen(kCallLMName)); if (!myErr) { SRPhrase myPhrase; myStringArray = (char **) kCallSynonyms; while ((myCurrString = *myStringArray) != NULL) { /* note that we call SRNewPhrase instead of SRNewWord */ /* so that we don't have to know if any of the synonyms */ /* is more than one word */ myErr = SRNewPhrase(mySystem, &myPhrase, myCurrString, strlen(myCurrString)); if (!myErr) { myErr = SRAddLanguageObject(myCallLM, myPhrase); SRReleaseObject(myPhrase); /* balances SRNewPhrase */ } myStringArray++; } } /* create an embedded language model named "<person>" */ /* Note that this code uses SRAddText, */ /* a useful shortcut that calls SRNewPhrase internally. */ if (!myErr) myErr = SRNewLanguageModel(mySystem, &myPersonLM, kPersonLMName, strlen(kPersonLMName)); if (!myErr) { long myRefCon = 0; myStringArray = (char **) kPersonNames; while ((myCurrString = *myStringArray) != NULL) { myErr = SRAddText(myPersonLM, myCurrString, strlen(myCurrString), myRefCon++); /* Note that by setting the refcon in the SRAddText call, */ /* we can use it later when processing the search result. */ myStringArray++; } } /* create a top-level language model named "<TopLM>" */ if (!myErr) myErr = SRNewLanguageModel(mySystem, &myTopLM, kTopLMName,strlen(kTopLMName)); /* we set the refcon of the top-level language model, */ /* so that we can identify it in the recognition result */ if (!myErr) myErr = SRSetProperty(myTopLM, kRefCon, &kTopLMRefCon, sizeof(kTopLMRefCon)); /* create a path for "<call> <person>" and add to "<TopLM>" */ if (!myErr) myErr = SRNewPath(mySystem, &myPath); if (!myErr){ if (!myErr) myErr = SRAddLanguageObject(myPath, myCallLM); if (!myErr) myErr = SRAddLanguageObject(myPath, myPersonLM); if (!myErr) myErr = SRAddLanguageObject(myTopLM, myPath); /* we set the refcon of the path, */ /* so that we can identify it in the search result */ if (!myErr) myErr = SRSetProperty(myPath, kSRRefCon, &kCallPersonRefCon, sizeof(kCallPersonRefCon)); SRReleaseObject(myPath); /* balances SRNewPath */ } /* create path for "schedule meeting with <person>" and add to "<TopLM>" */ if (!myErr) myErr = SRNewPath(mySystem, &myPath); if (!myErr) myErr = SRAddText(myPath, kScheduleMeetingWith, strlen(kScheduleMeetingWith), 0); if (!myErr) myErr = SRAddLanguageObject(myPath, myPersonLM); if (!myErr) myErr = SRAddLanguageObject(myTopLM, myPath); SRReleaseObject(myPath); /* balances SRNewPath */ } /* add "view today's schedule" to "<TopLM>" */ if (!myErr) myErr = SRAddText(myTopLM, kViewTodaysSchedule, strlen(kViewTodaysSchedule), 0); if (myCallLM) myErr = SRReleaseObject(myCallLM);/* balances SRNewLanguageModel */ if (myPersonLM) myErr = SRReleaseObject(myPersonLM);/* balances SRNewLanguageModel */ return myTopLM; }TheMyBuildLanguageModel
function creates the embedded language models used in the example language model and then adds them to the top-level language modelmyTopLM
. As you can see, you can add a word or a phrase to a language model in several ways. You can use the sequence of functionsSRNewPhrase
,SRAddLanguageObject
, andSRReleaseObject
. Alternatively, you can use the functionSRAddText
, which adds some text directly to a language model without having you explicitly create objects for that text. Also, notice that calls toSRNewObject
are balanced with calls to SRReleaseObject for any object reference that won't be needed outside the routine (namely, all objects exceptmyTopLM
, which is returned at the end of the routine).Note particularly that the
MyBuildLanguageModel
function defined in Listing 1-5 sets thekSRRefCon
property of the various language objects it creates to known values. For example,MyBuildLanguageModel
sets thekSRRefCon
property of a name to an index into the array of names, like this:
myErr = SRAddText(myPersonLM, myCurrString, strlen(myCurrString), myRefCon++);Later, when interpreting recognition results, you can read a language object'skSRRefCon
property to determine what the user said. See "Interpreting Recognition Results," beginning on page 1-31 for details.Often, you'll want to designate certain words or phrases as optional. For example, you might wish to let the user say "meeting with Arlo" in addition to "schedule meeting with Arlo" (that is, making the word "schedule" optional). You can designate any language object as optional by setting its optional property, as illustrated in Listing 1-6.
Listing 1-6 Making a word optional
/* suppose that the word myWord has already been created */ Boolean myVal = TRUE; myErr = SRSetProperty(myWord, kSROptional, &myVal, sizeof(myVal));