Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[SOLVED] SpeechLib.SpVoiceClass:GetVoices does crash my Unity executable

Discussion in 'Scripting' started by DaG_II, Sep 12, 2014.

  1. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
    I created a project with Unity (version 4.5.3f3).
    I only wrote a simple script.
    The script code is as follow:

    Code (CSharp):
    1.     using UnityEngine;
    2.     using System.Collections;
    3.     using SpeechLib;
    4.  
    5.     public class SpeechTest : MonoBehaviour
    6.     {
    7.         private SpVoice voice;
    8.  
    9.         void Start()
    10.         {
    11.             voice = new SpVoice();
    12.             ISpeechObjectTokens voices = voice.GetVoices();
    13.         }
    14.  
    15.         // Update is called once per frame
    16.         void Update()
    17.         {
    18.             if (Input.anyKeyDown)
    19.             {
    20.                 voice.Speak("Hello, world!", SpeechVoiceSpeakFlags.SVSFlagsAsync);
    21.             }
    22.         }
    23.     }
    When I try to play (in Unity editor), the game runs without problems.
    Instead, when I build and run the game, I receive a message error:
    The zipped folder "2014-09-12_013622" is attached to this post.

    When i comment this line:

    Code (CSharp):
    1.     SpeechObjectTokens voices = voice.GetVoices();
    I need to call GetVoices method, because I want to set a new voice in the "SpVoice voice" object.
    How to solve this problem?

    Thanks in advance to everybody!
     

    Attached Files:

  2. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I've never heard of SpeechLib before. From a bit of googling, it's a Microsoft library; it wouldn't surprise me if it's not available on Mono (and it would greatly surprise me if it's available on Mono for any platform but Windows).

    Do you have reason to believe you can use it from Unity?
     
  4. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
    I believe I can use it from Unity because other people have used it: http://forum.unity3d.com/threads/speech-using-c.61309/
    Furthermore it seems work from Unity, because in "play mode" I have not issues. Then the game works if I build it and I don't use GetVoices() method.
    Have you any idea why the game crashes?
     
  5. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
  6. jnoffke

    jnoffke

    Joined:
    Nov 26, 2013
    Posts:
    31
    In that link you posted to the forum the guy solved the problem by writing a standalone C# application and then communicating using sockets with unity.

    If you want to use any speech libraries in unity you'll need to write an unmanaged plugin so you can use the windows SAPI engine.
     
  7. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
    What do you mean?
    Maybe should I build my .dll library that relies on SpeechLib?
     
  8. jnoffke

    jnoffke

    Joined:
    Nov 26, 2013
    Posts:
    31
    You'll need to write a c++ plugin dll if you want to use speech stuff in unity has been my experience. This will require Unity pro however and using SAPI will only work on windows platforms.

    If you want to use the c# libraries you'll need to write an entirely separate program outside of unity. Then unity and this external application can communicate over the network. Should be noted this will also only work on windows I believe as speechlib is a windows specific .net library.
     
  9. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
    Ok, I think I understood what you mean.
    Just for my own curiosity: why in Unity "play mode" the game doesn't crash?
     
  10. jnoffke

    jnoffke

    Joined:
    Nov 26, 2013
    Posts:
    31
    Ok, so you can actually get it to play in the standalone I found. I was also curious as to why this wasn't working. I looked at what modules were actually being loaded in the editor vs. the standalone build. So it turns out in the editor when GetVoices is called, the CustomMarshalers.dll is loaded. So I found this file in Unity install directory at : UnityInstallDir\Editor\Data\Mono\lib\mono\2.0 Once I actually built the player, I had to copy this file over into the builtPlayer_data\Managed\ folder. Which is what you'll have to do any time you build as it's not included in the build by default. This should actually let you call GetVoices function without crashing. I guess it's handling some Marshalling of COM objects that Unity may need in the editor and as a by product it was working in the editor. This could cause some other side effects though that I'm not aware of though.
     
  11. jnoffke

    jnoffke

    Joined:
    Nov 26, 2013
    Posts:
    31
    Or actually just drop the CustomMarshalers.dll into your project. That way it will always be included with the build.
     
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    That's a clever hack. Good job figuring it out!
     
  13. DaG_II

    DaG_II

    Joined:
    Apr 28, 2014
    Posts:
    9
    This is a great news! I was already thinking to create a separate program using unnamed pipe to communicate to/from Unity.

    I tried the solution suggested by jnoffke and the standalone executable works fine!

    I thank JoeStrout to have replied in this thread, but obviously the biggest thanks is for jnoffke for having found the solution to the problem. :)


    Thank you again guys!
     
  14. jnoffke

    jnoffke

    Joined:
    Nov 26, 2013
    Posts:
    31
    Ok, so it bothered me that this just "worked". So I did a little more digging this morning and will post what I found in case anyone else ever comes across this thread and wonders why just adding the CustomMarshalers.dll works.

    The "magic", so to say of what is happening is taking place in EnumeratorToEnumVariantMarshaler.cs. This is a "custom marshaler that marshals IEnumVARIANT interface to the .NET IEnumerator interface and vice versa." It is supposed to be used automatically by the CLR to bridge COM enumerators and .NET enumerators. According to the little documentation on it, you're not supposed to explicitly Marshal this, CLR is just supposed to know to do this somehow? So essentially, when GetVoices is called it returns an ISpeechObjectTokens, which within it implements GetEnumerator function that returns an IEnumerator. So, when built, this is where the crash was coming from. It was trying to marshal the IEnumVARIANT to IEnumerator and looking for the EnumeratorToEnumVariantMarshaler, but wasn't finding it. So it crashed.

    At least, that's my understanding of what was causing the crash.
     
  15. Shovancj

    Shovancj

    Joined:
    Dec 21, 2011
    Posts:
    16
    Thanks @jnoffke that worked great in a test project.

    But now I go to integrate it into my solution and I'm getting a build message and crash on run of the build.

    SpritePacker failed to get types from Interop.SpeechLib, Version=5.4.0.0, Culture=neurtral, PublicKeyToken=null.
    Error: The classes in the module cannot be loaded.
    UnityEngine.GUIUtility: ProcessEvent(Int32, IntPtr)

    my build settings are the same in both projects.
    stable (.Net 3.5 Equivalent)
    Mono backend
    .net 2.0

    Definitely and interesting one im running into and any help would be greatly appreciated. If I find anything out I'll be sure to update here.
     
  16. Shovancj

    Shovancj

    Joined:
    Dec 21, 2011
    Posts:
    16
    Ok so for what its worth the SpritePacker wasnt causing the crash.. had a null ref while using SpVoice causeing the crash on start..

    I disabled the SpritePacker and the messge went away, building with the packer didnt seem to hurt things tho.