Я - программист среднего уровня C #, но я абсолютный новичок в System.Speech. Я работаю над некоторыми примерами, чтобы понять, как работает API, и я уже зациклен на первом примере ... Я пытаюсь создать грамматику, которая возвращает семантику по умолчанию для одного или нескольких ожидаемых вариантов выбора. если пользователь явно не предоставляет значение для одного из этих вариантов. (Извините, если моя терминология не совсем верна ...) Я нахожусь на Windows Vista с Visual Studio 2010 (пробная версия) и установлен .NET 4.0.
Я начал с примера «заказа пиццы» в следующей статье, которая, похоже, довольно часто встречается на форумах:
http://msdn.microsoft.com/en-us/magazine/cc163663.aspx#S5
Код, с которого я начал, приведен на рисунке 9 этой статьи. К сожалению, по какой-то причине (возможно, из одной версии SAPI в другую?) Ряд вызовов функций на самом деле недопустим в .NET 4.0 / SAPI 5.3, например, GrammarBuilder.AppendChoices () и GrammarBuilder.AppendResultKeyValue () , Последний вызов - это то, что должно дать нам выбор по умолчанию для клавиш «size» и «crust», если пользователь указывает только начинки (то есть «Пицца с сыром, пожалуйста», передает обратно размер = большой, crust = толстый и topping = сыр) ... так что я пытаюсь выяснить, как сделать эту работу.
Вот соответствующий раздел моего кода (который должен быть просто переписать код в статье выше):
// [I'd like] a [< size >] [< crust >] [< topping >] pizza [please]
// build the core set of choices
GrammarBuilder grbSizes = new GrammarBuilder(new Choices("small", "regular", "large"));
GrammarBuilder grbCrusts = new GrammarBuilder(new Choices("thin crust", "thick crust"));
GrammarBuilder grbToppings = new GrammarBuilder(new Choices("vegetarian", "pepperoni", "cheese"));
// Wrap them in semantic result keys
SemanticResultKey skeySize = new SemanticResultKey("size", grbSizes);
SemanticResultKey skeyCrust = new SemanticResultKey("crust", grbCrusts);
SemanticResultKey skeyTopping = new SemanticResultKey("topping", grbToppings);
// And some default values for later on...
SemanticResultKey skeyDefaultSize = new SemanticResultKey("size", new GrammarBuilder(new SemanticResultValue("large")));
SemanticResultKey skeyDefaultCrust = new SemanticResultKey("crust", new GrammarBuilder(new SemanticResultValue("thick crust")));
// [...snip...]
// Here's the builder for one of several sub-grammars, the one with two default
// values... This should allow "cheese" in "A cheese pizza" to be intepreted
// as large+thick-crust+cheese
//choose topping only, and assume the rest
GrammarBuilder toppingOnly = new GrammarBuilder();
toppingOnly += skeyTopping;
toppingOnly += skeyDefaultSize;
toppingOnly += skeyDefaultCrust;
// [...snip...]
// Later code builds up the full pattern just as in the original article
Мне известно, что страница MSDN для конструктора SemanticResultKey включает предупреждение о том, что «в объектах GrammarBuilder, указанных строителями * 1016, должен быть один и только один непомеченный экземпляр SemanticResultValue * параметр ", иначе вы получите исключение. И действительно, я получаю исключение TargetInvocationException, когда говорю что-то вроде «сырной пиццы» в распознаватель.
Итак, мой первый вопрос: может ли кто-нибудь объяснить мне, что здесь происходит? Я не обязательно ожидал, что это ограничение будет применено здесь, так как (а) я думал, что мои объявления для skeyDefaultSize и skeyDefaultCrust действительно связывают SemanticResultValues с SemanticResultKeys, поэтому эти значения не следует рассматривать как «непомеченные»; и (b) два рассматриваемых значения SemanticResult на самом деле принадлежат разным GrammarBuilders, которые, в свою очередь, находятся внутри различных ключей SemanticResult, что, по-видимому, не является сценарием, описанным на странице MSDN.
Тогда мой второй вопрос: почему работает следующий код? Разница лишь в том, что я переставил некоторые строки, чтобы две клавиши «по умолчанию» не добавлялись к грамматике последовательно.
//choose topping only, and assume the rest
GrammarBuilder toppingOnly = new GrammarBuilder();
toppingOnly += skeyDefaultSize;
toppingOnly += skeyTopping;
toppingOnly += skeyDefaultCrust;
Это дает точный желаемый результат, когда я говорю, например, «Пицца с сыром» - все ключи («размер», «корочка», «посыпка») присутствуют в SemanticValue, который я улавливаю в своем обработчике SpeechRecognized, с желаемыми значениями по умолчанию для размера и корки плюс пользовательские значение для начинки.
Полагаю, третий и самый важный вопрос: есть ли способ сделать это правильно? Очевидно, что изменение порядка добавления слишком «волшебно» и не всегда будет жизнеспособным решением.
Извините за огромный вопрос, и большое спасибо за вашу помощь!