有没有人为Nuance Dragon Mobile Speech SDK for iOS创建了MonoTouch绑定?

时间:2012-02-21 05:55:49

标签: ios xamarin.ios speech-recognition

我在Windows Phone 7上运行了很好的Dragon Mobile SDK,我想获得适用于iOS的等效功能。由于SDK包装了麦克风,因此在我的MonoTouch项目中使用.NET程序集是不可能的(即使我确实有源代码)。看来最好的方法是创建一个绑定库(正如Miguel所描述的那样here)。

虽然看起来确实有很多工作,如果有人已经完成它,我很乐意重复使用而不是重新发明轮子......

3 个答案:

答案 0 :(得分:9)

以下是有关我如何使其工作的更多细节。

  1. 我下载了binding sample。你可能想跳过这一步,但如果你想让它工作,你真的必须从这个项目开始。
  2. 我创建了一个带有Xcode(我称之为SpeechKitLibrary)的objective-c库,它具有双重目的 - 一个是定义SpeechKitApplicationKey(这是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。 BindingSample中的Makefile是如何执行此操作的模板。但网络是你得到三个库 - libSpeechKitLibrary- {i386,arm6,arm7} .a。然后,makefile使用OSX lipo(1)工具创建通用库(libSpeechKitLibraryUniversal.a)。

  4. 现在才准备好创建一个绑定库。您可以在绑定示例中重用AssemblyInfo.cs(它将显示如何在通用库上为所有体系结构创建导入 - 并将驱动一些编译标志)...

    [assembly: LinkWith ("libSpeechKitLibraryUniversal.a", LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7, ForceLoad = true)]
    
  5. 你根据Makefile用btouch编译ApiDefinition.cs文件(我想我需要在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"
    
  7. 这就是全部,伙计们!希望这有用......

    如果有人(kos或其他)获得SetEarcon方法,请发布解决方案: - )

答案 1 :(得分:2)

Nuance的SDK协议不允许任何人为他们的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

答案 2 :(得分:0)

再次感谢Anuj的回答。我以为我会留下一两个关于如何做到这一点。绑定库并不难构建(仍在调整它,但这不是一项艰巨的任务)。

更加模糊的部分是弄清楚如何将SpeechKit框架链接起来。示例仅显示如何链接.a或.dylib。在OSX上使用ld(1)手册页花了一点时间后,看起来用于链接框架的正确ld(以及gcc)参数如下:

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

你把它放在项目属性的文本框中 - 在Build :: iPhone Build :: Additional mtouch arguments

请注意-L不起作用,因为它不是库;另请注意,引用here的-force_load和-ObjC似乎没有必要,因为这是一个框架而不是库。