Кто-нибудь создал привязку MonoTouch для Nuance Dragon Mobile Speech SDK для iOS? - PullRequest
3 голосов
/ 21 февраля 2012

У меня прекрасно работает Dragon Mobile SDK на Windows Phone 7, и я хотел бы, чтобы аналогичная функциональность работала для iOS. Поскольку SDK оборачивает микрофон, на самом деле невозможно использовать сборки .NET в моем проекте MonoTouch (даже если у меня был источник). Похоже, что лучший способ сделать это - создать библиотеку привязок (как Мигель описывает здесь ).

Это, конечно, кажется большой работой, и я хотел бы использовать ее повторно, а не заново изобретать колесо, если кто-то уже сделал это ...

Ответы [ 3 ]

9 голосов
/ 25 марта 2012

Вот еще несколько подробностей о том, как я заставил это работать.

  1. Я скачал пример переплета . Возможно, вы захотите пропустить этот шаг, но вам действительно нужно начать с этого проекта, если вы хотите, чтобы это сработало.
  2. Я создал цель-c библиотеку с Xcode (которую я назвал SpeechKitLibrary), которая имеет двойное назначение - одна из них - определить SpeechKitApplicationKey (которая является зависимостью extern, которая нужна SpeechKit):

    const unsigned char SpeechKitApplicationKey[] = {...};
    

    , а другой - определить класс, который использует каркас SpeechKit и связывается с ним. (в Xcode добавьте платформу SpeechKit в разделе фреймворков проекта).

    Файл .m, который я написал, выглядит примерно так ... (вы можете понять, что файл .h - очень простой). Я не уверен на 100%, что вам нужно все это, но я хотел убедиться, что библиотека статических архивов, которая появилась на этом этапе, будет импортировать правильные символы. Возможно, вы сможете как-то избежать этого, но в своих экспериментах я обнаружил, что мне нужно сделать что-то подобное ...

    // the SpeechKitWrapper isn't actually used - rather, it is a way to exercise all the API's that 
    // the binding library needs from the SpeechKit framework, so that those can be linked into the generated .a file.
    
    @implementation SpeechKitWrapper
    @synthesize status;
    
    - (id)initWithDelegate:(id <SKRecognizerDelegate>)delegate
    {
        self = [super init];
        if (self) {
            del = delegate;
            [self setStatus:@"initializing"];
            SpeechKit setupWithID:@"NMDPTRIAL_ogazitt20120220010133"
                          host:@"sandbox.nmdp.nuancemobility.net"
                          port:443
                        useSSL:NO
                      delegate:nil];
    
        NSString *text = [NSString stringWithFormat:@"initialized.  sessionid = %@", [SpeechKit sessionID]];
        [self setStatus:text];        
    
        SKEarcon* earconStart   = [SKEarcon earconWithName:@"beep.wav"];
        [SpeechKit setEarcon:earconStart forType:SKStartRecordingEarconType];
    
        voiceSearch = [[SKRecognizer alloc] initWithType:SKDictationRecognizerType
                                               detection:SKLongEndOfSpeechDetection
                                                language:@"en_US" 
                                                delegate:delegate];
    
        text = [NSString stringWithFormat:@"recognizer connecting.  sessionid = %@", [SpeechKit sessionID]];
        [self setStatus:text];  
        }
    
        return self;
    }
    
    @end
    
  3. Затем я скомпилировал / связал этот статический архив для трех разных архитектур - i386, arm6 и arm7. Makefile в BindingSample - это шаблон того, как это сделать. Но в итоге вы получаете три библиотеки - libSpeechKitLibrary- {i386, arm6, arm7} .a. Затем make-файл создает универсальную библиотеку (libSpeechKitLibraryUniversal.a) с использованием инструмента OSX lipo (1).

  4. Только теперь вы готовы к созданию библиотеки привязок. Вы можете повторно использовать AssemblyInfo.cs в образце связывания (который покажет, как создать импорт в универсальной библиотеке для всех архитектур - и примет некоторые флаги компиляции) ...

    [assembly: LinkWith ("libSpeechKitLibraryUniversal.a", LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7, ForceLoad = true)]
    
  5. Вы компилируете файл ApiDefinition.cs с помощью btouch согласно Makefile (я думаю, что мне нужно было повторить некоторую информацию в StructsAndEnums.cs, чтобы она работала). Обратите внимание - единственная функциональность, которую я не получил, - это "SetEarcon" - поскольку это архивная библиотека, а не фреймворк, я не могу связать wav как файл ресурсов ... и я не могу понять узнать, как заставить метод SetEarcon принять ресурс из моего пакета приложений.

    using System;
    using MonoTouch.Foundation;
    
    namespace Nuance.SpeechKit
    {
    // SKEarcon.h
    public enum SKEarconType
    {
        SKStartRecordingEarconType = 1,
        SKStopRecordingEarconType = 2,
        SKCancelRecordingEarconType = 3,
    };
    
    // SKRecognizer.h
    public enum SKEndOfSpeechDetection 
    {
        SKNoEndOfSpeechDetection = 1,
        SKShortEndOfSpeechDetection = 2,
        SKLongEndOfSpeechDetection = 3,
    };
    
    public static class SKRecognizerType
    {
        public static string SKDictationRecognizerType = "dictation";
        public static string SKWebSearchRecognizerType = "websearch";
    };
    
    // SpeechKitErrors.h
    public enum SpeechKitErrors
    {
        SKServerConnectionError = 1,
        SKServerRetryError = 2,
        SKRecognizerError = 3,
        SKVocalizerError = 4,
        SKCancelledError = 5,
    };
    
    // SKEarcon.h
    [BaseType(typeof(NSObject))]
    interface SKEarcon 
    {
        [Export("initWithContentsOfFile:")]
        IntPtr Constructor(string path);
    
        [Static, Export("earconWithName:")]
        SKEarcon FromName(string name);
    }   
    
    // SKRecognition.h
    [BaseType(typeof(NSObject))]
    interface SKRecognition
    {
        [Export("results")]
        string[] Results { get; }
    
        [Export("scores")]
        NSNumber[] Scores { get; }
    
        [Export("suggestion")]
        string Suggestion { get; }
    
        [Export("firstResult")]
        string FirstResult();
    }
    
    // SKRecognizer.h
    [BaseType(typeof(NSObject))]
    interface SKRecognizer
    {
        [Export("audioLevel")]
        float AudioLevel { get; }
    
        [Export ("initWithType:detection:language:delegate:")]
        IntPtr Constructor (string type, SKEndOfSpeechDetection detection, string language, SKRecognizerDelegate del);
    
        [Export("stopRecording")]
        void StopRecording();
    
        [Export("cancel")]
        void Cancel();
    
        /*
        [Field ("SKSearchRecognizerType", "__Internal")]
        NSString SKSearchRecognizerType { get; }
    
        [Field ("SKDictationRecognizerType", "__Internal")]
        NSString SKDictationRecognizerType { get; }
        */
    }
    
    [BaseType(typeof(NSObject))]
    [Model]
    interface SKRecognizerDelegate
    {
        [Export("recognizerDidBeginRecording:")]
        void OnRecordingBegin (SKRecognizer recognizer);
    
        [Export("recognizerDidFinishRecording:")]
        void OnRecordingDone (SKRecognizer recognizer);
    
        [Export("recognizer:didFinishWithResults:")]
        [Abstract]
        void OnResults (SKRecognizer recognizer, SKRecognition results);
    
        [Export("recognizer:didFinishWithError:suggestion:")]
        [Abstract]
        void OnError (SKRecognizer recognizer, NSError error, string suggestion);
    }   
    
    // speechkit.h
    [BaseType(typeof(NSObject))]
    interface SpeechKit
    {
        [Static, Export("setupWithID:host:port:useSSL:delegate:")]
        void Initialize(string id, string host, int port, bool useSSL, [NullAllowed] SpeechKitDelegate del);
    
        [Static, Export("destroy")]
        void Destroy();
    
        [Static, Export("sessionID")]
        string GetSessionID();
    
        [Static, Export("setEarcon:forType:")]
        void SetEarcon(SKEarcon earcon, SKEarconType type);     
    }
    
    [BaseType(typeof(NSObject))]
    [Model]
    interface SpeechKitDelegate
    {
        [Export("destroyed")]
        void Destroyed();   
    }   
    
    [BaseType(typeof(NSObject))]
    interface SpeechKitWrapper
    {
        [Export("initWithDelegate:")]
        IntPtr Constructor(SKRecognizerDelegate del);
    
        [Export("status")]
        string Status { get; set; }
    }
    }
    
  6. Теперь у вас есть сборка, на которую может ссылаться ваш проект приложения monotouch. Теперь важно помнить, что нужно связывать все фреймворки, которые являются зависимостями (не только SpeeckKit, но и зависимости SK) - вы делаете это, передавая mtouch некоторые дополнительные аргументы:

    -gcc_flags "-F<insert_framework_path_here> -framework SpeechKit -framework SystemConfiguration -framework Security -framework AVFoundation -framework AudioToolbox"
    

Вот и все, ребята! Надеюсь, это было полезно ...

Если кто-нибудь (kos или иным образом) заставляет работать метод SetEarcon, пожалуйста, опубликуйте решение: -)

2 голосов
/ 22 февраля 2012

Соглашение SDK Nuance недостаточно для того, чтобы кто-либо даже опубликовал привязки для своего iOS SDK для использования с MonoTouch.Но сама библиотека должна работать нормально.

При этом SDK имеет только несколько типов для отображения и будет довольно тривиальным для повторения работы, которую мог бы выполнять кто-либо другой.уже сделано.Вы можете проверить, как связать сборки, используя справочное руководство здесь:

http://docs.xamarin.com/ios/advanced_topics/binding_objective-c_types

Есть также проект BindingSample, который помогает пользователям лучше понять, как связывать собственные компоненты с помощью btouch:

https://github.com/xamarin/monotouch-samples/tree/master/BindingSample

0 голосов
/ 22 февраля 2012

Еще раз спасибо Anuj за ваш ответ. Я думал, что оставлю пару советов о том, как это сделать. Библиотеку связывания не составило труда (все еще ее настраивают, но это не сложная задача).

Более непонятной частью было выяснить, как связать каркас SpeechKit. Примеры показывают только, как связать .a или .dylib. Потратив немного времени на man-страницу ld (1) в OSX, похоже, что следующие правильные аргументы ld (и, следовательно, gcc) для связи со структурой следующие:

-gcc_flags "-F<insert_framework_path_here> -framework SpeechKit"

Вы помещаете это в текстовое поле в свойствах проекта - под Build :: iPhone Build :: Дополнительные аргументы mtouch

Обратите внимание, что -L не работает, потому что это не библиотека; также обратите внимание, что -force_load и -ObjC, на которые здесь ссылаются , здесь не кажутся необходимыми, потому что, опять же, это фреймворк, а не библиотека.

...