VR Chatを始めて、ボイスチェンジャーというものに興味が湧いたので、始めたばかりのゲームをほっぽり出して、ボイチェンを自作しているような暇人の記録
今回自作したこのボイチェンの機能としては、処理した音声の出力先をSteamなどで遊んでいるゲームにするか、ZoomやTeamsなどのWeb Meetingアプリケーションにするか、WindowsOS上で切り替えるだけで、インプットするアプリケーションによらず使用できるものになります。
目的:
- ゲーム内ボイスチャットやWeb Meeting(ネタ枠)で使えるボイスチェンジャーを自作する
- C/C++の簡単な知識
https://github.com/sukima-log/RealTimeSoftVoiceChanger
ボイスチェンジャーの構成
ここでは機能の全体像について、紹介します。
全体構成図
手を動かしてコードを書いていくのは、下図のAudio I/O Liblaryを含めた内部になります。このアプリケーションに音声を入力し、音声を変換処理を経て、任意のアプリケーションに音声を出力します。
上記の構成で音声処理を行うのに必要なライブラリやソフトウェアについて、次で紹介します。
使用するソフトやライブラリ
ここでは、今回の実装でボイスチェンジャーとして機能させるためのソフトウェアやアプリケーションと、実装に用いるライブラリについて簡単にまとめます。
ボイチェン動作環境
今回の実装における動作環境は以下表の通り。
動作環境 | Windows |
---|---|
開発環境 | Linux |
対応アプリケーション | ZoomなどのWeb会議アプリ, Steamなどのボイスチャット機能 |
今回はMinGWを用いたWindows向けの実行ファイルを生成しているので、MacOSやChromeOSには対応していないのですが、CMakeというコンパイラに依存しないビルド自動化ツールを使っているので、少しの変更でクロスプラットフォーム開発にも適用しやすいと思われます。
開発環境としては、WSLやDocker、VirtualBoxなどの仮想環境を用いて、どなたでも統一の環境を簡単に用意することができるLinux(Ubuntu)を用いています。
仮想オーディオデバイス
実装したアプリケーションの出力を、任意のアプリケーションの入力へ接続するために、コンピュータに「仮想オーディオデバイス」をインストールしておきます。これは、実装中のC/C++コード内の処理に用いるものではなく、自作したボイチェンアプリの出力の交通整理をパソコン内で行うために用います。
▼以下よりインストール可能
インストールすると、WindowsやZoomなどのサウンド設定項目に「CABLE Input/Output(VB-Audio Virtual Cable)」のような項目が追加されます。
他にも「YAMAHA SYNCROOM driver」という仮想オーディオデバイスなどがあるようですが、少し調べたかぎりでは、多少手間が増えそうだったので今回は見送りました。
音声の入出力設定
コンピュータに入力した音声を実装するアプリケーションに誘導し入力して、ボイチェンから出力した音声を出力(ここではCABLE Output(VB-Audio Virtual Cable))に書き込む処理を行うために、音声のインプット、アウトプットを制御するためのライブラリとして、オープンソースライブラリの「PortAudio」を用いています。
Windows側で入力と出力先を指定してやることで、PortAudioのデバイス取得処理でこれらのデバイスを入出力として認識することができます。
▼アプリケーション毎の設定▼
ここで、出力を自身のヘッドホンやスピーカーにすると、変換された音声がそのまま聞こえるので、デバックも容易です。また、出力をVB-Audio Virtual Cableにして、アプリに接続してやると、アプリに音声を入力することができます。
音声の処理
ボイスチェンジャーにおける音声の変換処理においては、オープンソースの「SoundTouch」というライブラリを用いました。
タイムストレッチやピッチシフトを行うことができ、処理がほかの音声処理ライブラリと比べても比較的軽量であるため、リアルタイム音声処理向きだとされているようです。
以下、設定項目の例です。
設定項目例 | 説明 |
---|---|
setSampleRate(int sampleRate) | サンプリング周波数 |
setChannels(int numChannels) | チャネル数(ステレオ/モノラル) |
setTempo(float tempo) | 再生速度(テンポ) |
setPitch(float pitch) | 音の高さ(ピッチ) |
setRateChange(float rateChange) | 再生速度の変更率 |
setPitchOctaves(float pitchOctaves) | ピッチのオクターブ変更 |
setPitchSemiTones(float pitchSemiTones) | ピッチのセミトーン変更 |
setRate(float rate) | 再生速度 |
setRateChange(float rateChange) | 再生速度の変更率 |
setOverlapMs(int overlapMs) | オーバーラップ(重なり) |
setSetting(int settingId, int value) | 追加のパラメータ |
パラメータを細かく調整することで、欲しい音声を探ることができます。
実際の動作例
実際の動作例をここでは示します。
アプリ操作(UI)
グラフィカルなUIを作るのも面倒だったので、基本コマンドで操作するようになってます。以下は、Windowsのコマンドプロンプト上の操作です。
起動時:
* Setting Option Change or Application End
* Select Option And Input Option Name.
* Option List
> exit : End Application.
> * : Start Voice Conversion!
> default : Set default Voice! and Start Voice Conversion!
> default1 : Set default Voice! (No Library) and Start Voice Conversion
> custom : Custom Mode!
> lady_A : Set Lady_A Voice! and Start Voice Conversion!
> man_A : Set man_A Voice! and Start Voice Conversion!
>
6~12行目のように、それぞれの名前に割り当てたパラメータ設定のプリセットを作っておき、切り替えられるようにしています。また、「custom」モードでは、各種パラメータをアプリケーション実行中に変換して、音声を微調整できるモードを実装しています。
アプリを終了する場合は「exit」と入力します。
音声変換時:
now : default
Hit [e]+Enter to Stop Voice Change.
>
音声変換モードに切り替えると、現在のモードと終了方法の書かれた上のような表示になり、音声の変換が開始されます。音声の変換モードを終了する場合は、「e+Enter」で終了します。
customモード:
[ 1]. soundTouch.setChannels (2);
[ 2]. soundTouch.setSampleRate (44100);
[ 3]. soundTouch.setTempo (1.000000);
[ 4]. soundTouch.setTempoChange (1.000000);
[ 5]. soundTouch.setPitch (1.000000);
[ 6]. soundTouch.setPitchSemiTones (1.000000);
[ 7]. soundTouch.setRateChange (1.000000);
[ 8]. soundTouch.setRate (1.000000);
[ 9]. soundTouch.setSetting(SETTING_USE_AA_FILTER, 0);
[10]. soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0);
[11]. soundTouch.setSetting(SETTING_SEQUENCE_MS, 32);
[12]. soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 20);
[13]. soundTouch.setSetting(SETTING_OVERLAP_MS, 8);
set value [3~13] or [exit]
>
customモードに移行すると、各種パラメータの現在値と、どのパラメータの値を変換するかを選択する表示となります。パラメータに関連付けられている数字を入力することで、任意のパラメータ値を変更することができます。
以上が、簡単に作った操作の例です。
音声変換例
実際の音声変換の様子を示します。
コンピューター内の音声ファイルを変換して録音しようとしましたが、うまくいかなかったのでヘッドセットのマイクにスマホの音を直接拾わせています。音質はかなり悪いです、すいませんorz
パラメータ | 高音 | 低音 |
---|---|---|
setTempo | 1.5f | 1.2f |
setTempoChange | 1.0f | 0.0f |
setPitch | 1.0f | 1.2f |
setPitchSemiTones | 3.5f | -4.0f |
setRateChange | 1.0f | 1.0f |
setRate | 1.2f | 1.0f |
SETTING_USE_AA_FILTER | 0 | 0 |
SETTING_USE_QUICKSEEK | 0 | 0 |
SETTING_SEQUENCE_MS | 32 | 32 |
SETTING_SEEKWINDOW_MS | 20 | 20 |
SETTING_OVERLAP_MS | 8 | 8 |
はじまるよ!(元音声)
変換(高音)
変換(低音)
パラメータは自由に設定可能なので、音声のテンポや速度、高さを自由に変換可能です。上記は変換の一例になります。以下、女性の声バージョンの変換例です。
おはようございまーす!(元音声)
変換(高音)
変換(低音)
今回のようにピッチを上げすぎると、ケロケロボイス化するようなので、パラメータの調整が必要になります。その時、パラメータはそれぞれの要素に独立しているものと、他のパラメータに影響するものとがあるので注意が必要です。
詳しくは、実装を中心にまとめている別記事↓にもまとめています。
ボイチェン実装詳細
ここでは、実装手法の詳細についてまとめています。
開発環境構築
実装における環境は以下のようなものです。
OS | Ubuntu |
---|---|
言語 | C/C++ |
コンパイラ | MinGW |
ツール | CMake |
備考 |
|
環境構築についての詳細は以下をご覧ください。
もしくは、コード中の「environment/environment.sh」内を見ると、環境構築用のスクリプトになっているので、流れと必要なものが分かります。
実装コード
実装コードについても、別記事に詳細をまとめているので、こちらをご覧ください。
実際に書いたコード自体は、ファイルを分割するほどでもない、mian.cppファイル内にすべて納まる500行にも満たないソースコードです。散らかっているなりにコメントも入れているので、上記詳細を見るよりmian関数から順にコードをなめた方が早いかもしれません。
今後の課題
ひとまず、動作するものを実装したまではいいのですが、完成度的には満足できていません。というのも、SoundTouchでは、自然な声の変換が難しいなぁ~と完成したものを聞いて思っているからです。
特に、声の性別の変換は細かくパラメタをいじらないと自然な変換はかなり難しいです。より自然な音声の変化のためにF0変換やスペクトル包括変換機能などのある、音声処理ライブラリのWorldを使用するなど、工夫のやり方はまだまだあると思っています。
また、少し感じる音の途切れが気になるので、FPGAなどのハードウェア処理に置き換えて処理のパイプライン化を検討してもいいかもしれません。
ただ、FPGAなどの機材の購入には馬鹿にできない費用が発生するので、FPGAを購入してボイチェンの実装に凝るより、ゲームのスペックを挙げるためのGPUなどを買う方が満足度は高いかもしれません。( 一一)
とりあえず、興味がわいたものを作ってみたい衝動はこれで収まったので、また、ボイチェンへの興味が再熱したら他の実装も試したいと思います。
参考:
https://www.springin.org/sound-stock/category/voice/
https://amitaro.net/voice/voice_dl/
以上、ありがとうございました。