更新:この回答は、調査後に編集されました。当初、SupportedAudioFormats は (おそらく誤って構成された) レジストリ データからのものである可能性が高いことを記憶から示唆していました。調査によると、私にとって、Windows 7 ではこれは間違いなく当てはまり、Windows 8 では偶然にもバックアップされています。
サポートされているオーディオ形式に関する問題
System.Speech
由緒ある COM 音声 API (SAPI) をラップし、一部の音声は 32 ビット対 64 ビットであるか、誤って構成されている可能性があります (64 ビット マシンのレジストリでは、HKLM/Software/Microsoft/Speech/Voices
対HKLM/Software/Wow6432Node/Microsoft/Speech/Voices
.
私は ILSpySystem.Speech
とそのVoiceInfo
クラスを指摘しましたが、SupportedAudioFormats はレジストリ データのみに由来するものであると確信しているためSupportedAudioFormats
、TTS エンジンがアプリケーションのプラットフォーム ターゲットに適切に登録されていない場合、列挙時にゼロの結果が返される可能性があります ( x86、Any、または 64 ビット)、または単にベンダーがレジストリでこの情報を提供しない場合。
音声は、レジストリ (データ) ではなく、音声エンジン (コード) 次第であるため、異なる形式、追加の形式、または少ない形式をサポートする可能性があります。そのため、暗闇でのショットになる可能性があります。この点に関して、標準の Windows の音声は、多くの場合、サード パーティの音声よりも一貫性がありますが、必ずしも有用な機能を提供するとは限りませんSupportedAudioFormats
。
この情報を見つけるのは難しい方法です
現在の音声の現在の形式を取得することはまだ可能であることがわかりましたが、これはリフレクションに依存して System.Speech SAPI ラッパーの内部にアクセスします。
したがって、これは非常に脆弱なコードです。また、本番環境での使用はお勧めしません。
注: 以下のコードでは、セットアップのために Speak() を 1 回呼び出す必要があります。Speak() なしでセットアップを強制するには、さらに多くの呼び出しが必要になります。しかし、私はSpeak("")
何も言わずに電話をかけることができ、それはうまく機能します.
実装:
[StructLayout(LayoutKind.Sequential)]
struct WAVEFORMATEX
{
public ushort wFormatTag;
public ushort nChannels;
public uint nSamplesPerSec;
public uint nAvgBytesPerSec;
public ushort nBlockAlign;
public ushort wBitsPerSample;
public ushort cbSize;
}
WAVEFORMATEX GetCurrentWaveFormat(SpeechSynthesizer synthesizer)
{
var voiceSynthesis = synthesizer.GetType()
.GetProperty("VoiceSynthesizer", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(synthesizer, null);
var ttsVoice = voiceSynthesis.GetType()
.GetMethod("CurrentVoice", BindingFlags.Instance | BindingFlags.NonPublic)
.Invoke(voiceSynthesis, new object[] { false });
var waveFormat = (byte[])ttsVoice.GetType()
.GetField("_waveFormat", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(ttsVoice);
var pin = GCHandle.Alloc(waveFormat, GCHandleType.Pinned);
var format = (WAVEFORMATEX)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(WAVEFORMATEX));
pin.Free();
return format;
}
使用法:
SpeechSynthesizer s = new SpeechSynthesizer();
s.Speak("Hello");
var format = GetCurrentWaveFormat(s);
Debug.WriteLine($"{s.Voice.SupportedAudioFormats.Count} formats are claimed as supported.");
Debug.WriteLine($"Actual format: {format.nChannels} channel {format.nSamplesPerSec} Hz {format.wBitsPerSample} audio");
テストするために、Microsoft Anna のAudioFormats
レジストリ キーの名前を に変更しました。これHKLM/Software/Wow6432Node/Microsoft/Speech/Voices/Tokens/MS-Anna-1033-20-Dsk/Attributes
によりSpeechSynthesizer.Voice.SupportedAudioFormats
、クエリを実行しても要素がなくなりました。以下は、この状況での出力です。
0 formats are claimed as supported.
Actual format: 1 channel 16000 Hz 16 audio