動機
先日書いた記事ではGemini Live APIを取り扱った。
また、以前、OpenAI APIのText-to-Speechを試したこともある。その結果をYouTubeへも投稿:
Gemini APIの Text-to-Speechも試したくなってきた。こういうとき、私は、WebアプリかUnityやGodotでアプリつくって試す。今回はUnityで試すことにした。
まずはGemini APIのC#コードを作成
ベースは、以前、Godot向けに書いたGemini APIのGDScriptコード。Gemini CLIで、これをC#のコードへ変換した。
更に、このコードをVS Codeで開き、Gemini Code Assistによるアシストで細かな部分の修正を行った後、以下のサイトの情報をGemini Code Assistへテキストで与え、Text-to-Speechにも対応させた:
いや、すごい時代が来たものだ。。。最近、コードを書くときは、何をつくるにしても、Geminiが2~5割、私が5~8割という作業分担。今後、生成AIが書く割合は増えていく。。。
作成したC#コードは以下:
https://github.com/araobp/unity-robotics/blob/main/robotics/Assets/Scripts/Gemini.cs
これを動かしてみる
Gemini APIからどんな形式の音声データが返されるのか?試しに、このコードのText-to-Speechの部分を動かしてみた。WAVかMP3形式で返されたデータだろうと勝手に想像し、とりあえずWAVの拡張子でファイルへ保存し、Audacityという音声データ解析ツールでこれを開いてみたところ、これはRAWデータだと文句を言われた。
Gemini APIのドキュメントを見ると24000という数値が。これはPCMオーディオのサンプリングレートに違いないと思い、以下のようにサンプリングレート指定し、再度読み込ませた。
そうすると音声データの波形が表示され、これを再生出来た。
さて、ここからはお遊びだが、Gemini APIが生成した音声データのスペクトログラムを表示してみる。人の声の場合、これは声紋に相当する。これを見ると、Geminiが人間の真似をしている様子を実感出来る。Gemini API "Leda"さんの声。
余談になるが、今年、私はG検定を受験し、G検定の教科書にも、PCM、サンプリング定理、ナイキスト周波数、スペクトログラム、更にはメルケプストラムまで解説されていた。。。そんなマニアックなところまで出題するのか???私のように、電話の開発や音のAI開発をやったことあれば、こういうのは楽勝かもしれないが、そうでないと、結構ハードル高いのでは。。。いや、これからフィジカルAIの時代に入るし、音のAIも重要になってきたのかもしれない。
試験用アプリの制作:まずは枠から
UIの制作から始める。声を選択するためのDropDownメニュー、テキストを入力するためのInputFieldとText-to-Speechを実行するボタンをUIへ配備した。
更に、GameControllerという空のオブジェクトを追加し、これに、メインのスクリプトとAudioSourceコンポーネントをアタッチ。
残りは、Gemini APIが生成したPCMデータをAudioSourceコンポーネントへ渡す処理を書くだけ。
PCMデータをUnityのAudioSourceコンポーネントへ入力
このコードもVS Code上のGemini Code Assistantへ書かせた。以下のようなコードが生成された。私は組み込みシステム開発をやったことあるので、これを見て、懐かしくなった。符号付き16bit整数を浮動小数点の配列データへ変換し、この、サンプリングレート24000Hzのモノラル音声データをAudioSourceコンポーネントへ入力。
void PlayAudio(byte[] pcmData)
{
// The synthesized audio is 16-bit PCM, so 2 bytes per sample.
int samplesCount = pcmData.Length / 2;
float[] floatData = new float[samplesCount];
for (int i = 0; i < samplesCount; i++)
{
// Convert two bytes to a 16-bit signed integer (short)
short sample = (short)((pcmData[i * 2 + 1] << 8) | pcmData[i * 2]);
// Convert to float in the range -1.0 to 1.0
floatData[i] = sample / 32768.0f;
}
const int sampleRate = 24000;
const int channels = 1; // Mono
AudioClip audioClip = AudioClip.Create("SynthesizedSpeech", samplesCount, channels, sampleRate, false);
audioClip.SetData(floatData, 0);
audioSource.clip = audioClip;
audioSource.Play();
Debug.Log("Playing synthesized speech.");
}
このコードを通し、見事、音声を再生出来ることが出来た。



