はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】SharpOpenJTalk.Langを用いてテキストから音素ラベルを抽出してみる

はじめに

今回はSharpOpenJTalk.Langというライブラリを利用してテキストから音素ラベルを抽出してみる記事になります。
github.com


前回SharpOpenJTalkの紹介をしましたが、SharpOpenJTalk.Langは音素ラベルの抽出のみを備えたライブラリのようですね。
www.hanachiru-blog.com



具体的には音声データがなくても動作するといったメリットがあります。後は軽量(なはず)とかですかね。

NuGetからSharpOpenJTalkを取得

宗教上の理由よりNuGetForUnityを利用できないので、今回はブラウザのNuGetから取ってきます。

www.nuget.org

右にあるDownload packageを押すと、sharpopenjtalk.lang.〇〇.nupkgがダウンロードされるはずです。

nupkgをダウンロードする

.nupkg.zipに拡張子を変更して解凍できるので、それを行ってください。

Unityへインポート

Unityにインポートすべきなのは以下のファイルになります。

  • lib/netstandard1.3/SharpOpenJTalk.Lang.dll
  • runtimes
Unityにインポートすべきファイル

これをインポートするときPluginsフォルダの中に入れる必要があること、runtimes以下にあるライブラリのプラットフォーム設定を適切に行う必要があることに注意してください。

ライブラリをインポートした様子

コーディングを行う

OpenJTalkで利用する辞書をStreamingAssets内に配置したコードを以下に記述します。

using System.IO;
using SharpOpenJTalk.Lang;
using UnityEngine;
using UnityEngine.UI;

public class Sample : MonoBehaviour
{
    [SerializeField] private Text text;

    private void Start()
    {
        var instance = new OpenJTalkAPI();
        
        var dictPath = Path.Combine(Application.streamingAssetsPath, "dic");

        if (!instance.Initialize(dictPath))
        {
            text.text = "Initialize failed";
            return;
        }

        var labels = instance.GetLabels("これはテストです");

        text.text = string.Join(",", labels);
    }
}

ひとこと

SharpOpenJTalk.Langruntimesの中には以下のプラットフォームに対応したライブラリが入っています。

  • browser-wasm (.a)
  • linux (.so)
  • osx (.dylib)
  • win-x64 (.dll)
  • win-x86 (.dll)

ただ.a.soがあるなら、iOSAndriodで動くんじゃね?とか思いましたが、今のところ上手くいってはいません。

ちなみにiOSで動作させたい場合は[DllImport("__Internal")]にする必要があるのは注意点の一つですね。

// iOSで動作させたいならば、CoreDefinitions.csのコードを変更する必要があります

using System;
using System.Runtime.InteropServices;

namespace SharpOpenJTalk.Lang.Native
{
  internal class CoreDefinitions
  {
#if !UNITY_EDITOR && UNITY_IOS
    private const string DllName = "__Internal";
#else
    private const string DllName = "openjtalk-lang";
#endif
    
    [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr Open_JTalk_initialize();

    [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
    public static extern void Open_JTalk_clear(ref IntPtr openJTalkInstance);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    public static extern int Open_JTalk_load_u16(
      IntPtr openJTalkInstance,
      string dictPath,
      string userDictPath);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    public static extern int Open_JTalk_extract_label_u16(
      IntPtr openJTalkInstance,
      string text,
      out IntPtr unmanagedLabels,
      out int labelLength);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    public static extern int Open_JTalk_dict_gen_u16(
      string dictPath,
      string userCsvPath,
      string outputUserDictPath);
  }
}

まあ自身でOpenJTalkのC#ラッパーを作成できれば一番良いのですが、技量が足らずなかなか難航してます。

もし何か良い方法を知っている方がいましたら、コメント等で教えていただけますと嬉しいです。