LoginSignup
2
4

More than 1 year has passed since last update.

Windows環境で音声合成(音声読み上げ)

Posted at

はじめに

WindowsAPIを使って、音声合成(音声読み上げ)処理を実装しました。

環境

ソースコード

音声合成には、SpeechSynthesizer クラスを使用しています。
.NET APIを利用するためにC++/CLIを経由しています。
英語はMicrosoft Zira Desktop、日本語はMicrosoft Haruka Desktopとそれぞれに適した音声で再生します。
ソースコードではコメントアウトしていますが、waveファイルへの出力も可能です。

speak.d
import std.stdio;
import std.utf;

extern (C++) {
    void speak(const(wchar)* phrase, const(wchar)* speaker, const(wchar)* filename = cast(wchar*)0);
}

void main()
{
    wstring phrase = "D is a general-purpose programming language with static typing, systems-level access, and C-like syntax.";
    writefln("input : %s", phrase);
    phrase.toUTF16z.speak("Microsoft Zira Desktop");
    phrase = "D言語は、静的かたづけ、システムレベルのアクセス、およびCのような構文を備えた汎用プログラミング言語です。";
    writefln("input : %s", phrase);
    phrase.toUTF16z.speak("Microsoft Haruka Desktop");
//  waveファイルに出力することも可能
//  phrase.toUTF16z.speak("Microsoft Haruka Desktop", "output.wav");
}
speechsynthesizer.cpp
#using <C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Speech\v4.0_4.0.0.0__31bf3856ad364e35\System.Speech.dll>

using namespace System;
using namespace System::Speech::Synthesis;

void outputToWaveFile(char16_t const *phrase, char16_t const *speaker, char16_t const *filename)
{
    SpeechSynthesizer^ synth = gcnew SpeechSynthesizer();
    if ( filename != 0 ){
        synth->SetOutputToWaveFile(gcnew String(reinterpret_cast<wchar_t const*>(filename)));
    }
    synth->SelectVoice(gcnew String(reinterpret_cast<wchar_t const*>(speaker)));
    String^ p = gcnew String(reinterpret_cast<wchar_t const*>(phrase));
    synth->Speak(p);
}

void speak(char16_t const *phrase, char16_t const *speaker, char16_t const *filename = 0)
{
    outputToWaveFile(phrase, speaker, filename);
}

コンパイル、実行

x64 Native Tools Command Prompt for VS 2019を起動して、以下の順に実行します。
音声合成の技術は、思っていたより向上していて、いい感じに読み上げてくれました。
こんなに簡単に実装できたのにも驚きです。

コマンドプロンプト
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.4.2
** Copyright (c) 2019 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

d:\Dev> cl /clr /c speechsynthesizer.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.24.28314
Microsoft (R) .NET Framework の場合 バージョン 4.08.4300.0
Copyright (C) Microsoft Corporation.  All rights reserved.

speechsynthesizer.cpp

d:\Dev> dmd -m64 -release -L=/NODEFAULTLIB:libcmt.lib speak.d speechsynthesizer.obj "C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Lib\um\x64\mscoree.lib"

d:\Dev> chcp 65001
Active code page: 65001

d:\Dev> speak
input : D is a general-purpose programming language with static typing, systems-level access, and C-like syntax.
input : D言語は、静的かたづけ、システムレベルのアクセス、およびCのような構文を備えた汎用プログラミング言語です。

実験:隠れキャラ(?)の呼び出し

この実験ではレジストリの書き換えを行っています。推奨しているわけではありません。

.NET Framework 4.8環境のSpeechSynthesizer クラスで日本語読み上げに適した音声はMicrosoft Haruka Desktopしか用意されていません。
しかし、音声認識の音声選択ではMicrosoft AyumiMicrosoft Ichiroなる音声が存在します。

voice.png

レジストリを探したところ、HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices\Tokens以下に何か定義があります。さらに、そこにはMicrosoft Sayakaという隠れキャラ(?)まで存在しました。
これらの定義をHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens以下でも追加すれば、音声合成に使えるのではないかと思い、試しました。
結論として、これでうまく音声合成ができました。

以下、追加したレジストリ定義です。

ayumi.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_JA-JP_AYUMI_11.0]
@="Microsoft Ayumi - Japanese (Japan)"
"411"="Microsoft Ayumi - Japanese (Japan)"
"CLSID"="{179F3D56-1B0B-42B2-A962-59B7EF59FE1B}"
"LangDataPath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,\
  00,70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,\
  65,00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,\
  00,5c,00,6a,00,61,00,2d,00,4a,00,50,00,5c,00,4d,00,53,00,54,00,54,00,53,00,\
  4c,00,6f,00,63,00,6a,00,61,00,4a,00,50,00,2e,00,64,00,61,00,74,00,00,00
"VoicePath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,00,\
  70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,65,\
  00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,00,\
  5c,00,6a,00,61,00,2d,00,4a,00,50,00,5c,00,4d,00,31,00,30,00,34,00,31,00,41,\
  00,79,00,75,00,6d,00,69,00,00,00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_JA-JP_AYUMI_11.0\Attributes]
"Age"="Adult"
"Gender"="Female"
"Language"="411"
"Name"="Microsoft Ayumi"
"SharedPronunciation"=""
"Vendor"="Microsoft"
"Version"="11.0"
ichiro.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_JA-JP_ICHIRO_11.0]
@="Microsoft Ichiro - Japanese (Japan)"
"411"="Microsoft Ichiro - Japanese (Japan)"
"CLSID"="{179F3D56-1B0B-42B2-A962-59B7EF59FE1B}"
"LangDataPath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,\
  00,70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,\
  65,00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,\
  00,5c,00,6a,00,61,00,2d,00,4a,00,50,00,5c,00,4d,00,53,00,54,00,54,00,53,00,\
  4c,00,6f,00,63,00,6a,00,61,00,4a,00,50,00,2e,00,64,00,61,00,74,00,00,00
"VoicePath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,00,\
  70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,65,\
  00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,00,\
  5c,00,6a,00,61,00,2d,00,4a,00,50,00,5c,00,4d,00,31,00,30,00,34,00,31,00,49,\
  00,63,00,68,00,69,00,72,00,6f,00,00,00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_JA-JP_ICHIRO_11.0\Attributes]
"Age"="Adult"
"Gender"="Male"
"Language"="411"
"Name"="Microsoft Ichiro"
"SharedPronunciation"=""
"Vendor"="Microsoft"
"Version"="11.0"
sayaka.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_JA-JP_SAYAKA_11.0]
@="Microsoft Sayaka - Japanese (Japan)"
"411"="Microsoft Sayaka - Japanese (Japan)"
"CLSID"="{179F3D56-1B0B-42B2-A962-59B7EF59FE1B}"
"LangDataPath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,\
  00,70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,\
  65,00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,\
  00,5c,00,6a,00,61,00,2d,00,4a,00,50,00,5c,00,4d,00,53,00,54,00,54,00,53,00,\
  4c,00,6f,00,63,00,6a,00,61,00,4a,00,50,00,2e,00,64,00,61,00,74,00,00,00
"VoicePath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,00,\
  70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,65,\
  00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,00,\
  5c,00,6a,00,61,00,2d,00,4a,00,50,00,5c,00,4d,00,31,00,30,00,34,00,31,00,53,\
  00,61,00,79,00,61,00,6b,00,61,00,00,00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_JA-JP_SAYAKA_11.0\Attributes]
"Age"="Adult"
"Gender"="Female"
"Language"="411"
"Name"="Microsoft Sayaka"
"SharedPronunciation"=""
"Vendor"="Microsoft"
"Version"="11.0"

レジストリ追加後の実装例

speak1.d
import std.stdio;
import std.utf;

extern (C++) {
    void speak(const(wchar)* phrase, const(wchar)* speaker, const(wchar)* filename = cast(wchar*)0);
}

void main()
{
    wstring phrase = "D言語は、静的かたづけ、システムレベルのアクセス、およびCのような構文を備えた汎用プログラミング言語です。";
    writefln("input : %s", phrase);
    phrase.toUTF16z.speak("Microsoft Haruka Desktop");
    phrase.toUTF16z.speak("Microsoft Ichiro");
    phrase.toUTF16z.speak("Microsoft Ayumi");
    phrase.toUTF16z.speak("Microsoft Sayaka");
}

参考情報

インストールされている .NET Framework バージョンを確認する
SpeechSynthesizer クラス

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4