【问题标题】:Has anyone created a MonoTouch binding for the Nuance Dragon Mobile Speech SDK for iOS?是否有人为适用于 iOS 的 Nuance Dragon 移动语音 SDK 创建了 MonoTouch 绑定?
【发布时间】:2012-06-14 03:17:26
【问题描述】:

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

不过,这确实看起来需要做很多工作,如果有人已经做过,我更愿意重复使用而不是重新发明轮子......

【问题讨论】:

  • Dragon/Nuance 是否适合在移动设备上进行一般听写?你的代码是我在一个小时的搜索中遇到的唯一代码,所以我想知道对 Xamarin 开发人员的支持是否有所改进,以及这些天该技术有多大用处。

标签: ios xamarin.ios speech-recognition


【解决方案1】:

这里有一些关于我如何让它工作的更多细节。

  1. 我下载了binding sample。你可能会想跳过这一步,但如果你想让它工作,你真的必须从这个项目开始。
  2. 我使用 Xcode(我称之为 SpeechKitLibrary)创建了一个具有双重目的的 Objective-c 库 - 一个是定义 SpeechKitApplicationKey(这是 SpeechKit 需要的外部依赖项):

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

    另一个是定义一个利用 SpeechKit 框架的类,并与之链接。 (在 Xcode 中,在项目的 frameworks 部分添加 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. 您现在有了一个可以被单点触控应用程序项目引用的程序集。现在重要的是要记住链接所有依赖的框架(不仅是 SpeeckKit,还有 SK 的依赖)——你可以通过传递 mtouch 一些额外的参数来做到这一点:

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

就是这样,伙计们!希望这对您有所帮助...

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

【讨论】:

  • Omri,非常感谢。只是为了在第 2 步中澄清 - 库包含 SpeechKitWrapper.m 和 SpeechKitWrapper.h,但是您在哪里定义 SpeechKitApplicationKey?在 SpeechKitWrapper.m 或单独的文件中?另外,statussetStatus 一样吗?谢谢....
  • 没关系 - 我把它放在 SpeechKitWrapper.m 中(在@implementation 上方)。我这样定义 SpeechKitWrapper.h... #import #import \@interface SpeechKitWrapper : NSObject // { NSString *status; SKRecognizer *语音搜索; NSObject *del; } \@property (nonatomic,retain) NSString *status; \@结束
  • 感谢 Omri,成功生成了 dll。我的(希望)最后一个问题是关于 touch 论点。我不断收到“本机链接失败。请查看提供给 gcc 的用户标志”。我的论点如下-gcc_flags "-F/Users/kos/Projects/MySolution/MyProject/Frameworks -framework SpeechKit -framework SystemConfiguration -framework Security -framework AVFoundation -framework AudioToolbox",在Frameworks文件夹中我复制了SpeechKit.frameworklibSpeechKitLibraryUniversal.a。我尝试了其他各种途径。我错过了什么吗?再次,非常感谢您的帮助...
  • 您不需要移动 libSpeechKitLibraryUniversal.a - assemblyinfo.cs 中的“linkwith”属性应该会导致 .a 嵌入到 dll 中。此外 -F 仅适用于框架,不适用于静态库(请参阅 ld(1))。退后一步,我在上面列出了很多步骤。相信我,如果您下载 BindingSample 并花时间了解 makefile 的作用,它们都会变得更有意义。首先让那个东西工作(包括在模拟器上部署它)。然后开始将您的代码替换为该示例。这会让事情变得更容易......祝你好运!
  • 再次感谢。我实际上下载并让 BindingSample 工作 - 你是对的,在尝试其余部分之前绝对值得这样做。但是,BindingSample 没有任何 mtouch 参数可以帮助我处理项目所需的参数。只是想知道-F&lt;insert_framework_path_here&gt; 参数中需要做什么 - 即它是原始 Xcode SpeechKit.framework,如果是,我是否需要将它复制到我的项目路径中并从那里链接它?
【解决方案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

【讨论】:

  • 我一直在这样做(按照您提到的链接中的描述编写绑定库 - 这与我在原始问题中引用的相同)。我仍然没有让它工作(仍然在努力链接它,因为它是一个框架而不是 libX.a)。是否有您知道的绑定示例绑定一个框架(显然 MonoTouch 绑定了每个 CocoaTouch 框架 - UIKit 等 - 所以它必须是可能的)。
【解决方案3】:

再次感谢 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 似乎没有必要,因为这是一个框架而不是库。

【讨论】:

  • 在给定的 *.framework 文件夹中通常有一个静态编译的库。也尝试新的 LinkWith 属性:-)
  • 更新:我终于得到了这个工作 - Anuj 的绑定样本绝对是要走的路。我永远无法让绑定库项目模板为我工作——相反,我做了大多数其他人似乎在做的事情——明确使用 btouch 并采用 Anuj 的方法来创建包含 arm6、arm7 和 i386 静态库的通用静态库。另一个非常重要的事情是不要忘记在 APPLICATION 项目中使用 -F -framework mtouch 参数。
  • 有机会通过 github 共享库吗?如果可能的话,我将非常感谢重用。
  • kos - 见上面 anuj 的评论 - 他是对的 - 细微差别不允许这样做。我花了几天的时间(似乎比应该做的更难),但这绝对是可行的。
  • Omri - 我正在努力让它发挥作用。有没有机会展示您如何定义 ApiDefinition.cs 包装器?我试图让它适用于 SpeechKit、SKRecognizer 和 SKRecognition 类。
猜你喜欢
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
相关资源
最近更新 更多