【C#】PCのマイクで拾った音をPepperに送って再生させる【qi Framework】

Pocket

リアルタイムなスピーカーとしてPepperを使おうという話の紹介です。

 

もくじ
1. はじめに
2. C#でマイク入力を拾うには
3. Pepperの音声出力APIの話
4. サンプルコード
5. まとめ

 
 

はじめに

本記事は前に公開した「C#プログラムでPepperが聞いてる音をストリーミング」の対極となる処理、つまり手元のマイクに向かって喋った音をPepperに投げつけて再生させる、言い換えるとPepperの口を乗っ取る方法の紹介になります。Pepperに音声バッファを投げる方法については直接的なAPIがあり、参考としてアルデバラン社の方が非公式で試された方法紹介もあります。この記事ではスタンダードにC++で試してますが、コアになる処理はそんなに複雑ではなくC#にも移植できそうなので、実際にやってみました。

 
 

C#でマイク入力を拾うには

C#で声の入力を拾う方法ですが、音声出力のプログラムでもお世話になったNAudioは当然と言わんばかりに音声入力にも対応しているため、再びNAudioを使います。入力を拾うにはWaveInEventクラスを利用すればよく、使い方もそんなに複雑ではありません。例えばPCにマイク入力を入れ、そのままエコーバック的に出力する場合は次のようなコードを書きます。

 

上の例は音声の入力コードと出力コードが入り混じっていますが、マイク入力に関係ある部分だけ抜粋するとこうなります。

 

かなり単純な作りであり、上記のイベントハンドラ部分に「Pepperに音を再生させる」という処理を記述すればよさそうな事が分かります。

 
 

Pepperの音声出力APIの話

Pepperに音声出力用のスピーカーがついているのは今更言うまでも無い事実ですが、このスピーカーはALAudioDeviceALTextToSpeechなど一部のAPIからのみ触れるようになっています。

今回に関しては冒頭でも紹介したこちらの記事を見ると“ALAudioDevice”サービスの“sendRemoteBufferToOutput”関数を使えば普通に再生できますよ、と書かれています。同記事で紹介されているGitHubのソースコードも参考になりますし、公式ドキュメンテーションではこのへんに色々書かれています。関数のシグネチャはこんな感じ。

bool ALAudioDeviceProxy::sendRemoteBufferToOutput(const int& nbOfFrames, const AL::ALValue& buffer)

この関数ですが“sendRemoteBufferToOutput”関数のドキュメンテーションのすぐ上にあるsendLocalBufferToOutput関数のサンプル等を見ると、次のような注意点があることが分かります。

  • フレーム数にあたる数値はバイト配列の長さの1/4相当を指定すればOK
  • バイト配列にはリトルエンディアンの値で16bit値を、左右のスピーカー用に交互に入れていく
  • 出力のサンプリングレートを変えたい場合は“setParameter”関数越しで変更するらしい

これらを踏まえて出力用のコードを書くと、およそ次のような感じになります。

 

上の例では出力サンプリングレートを最低値の16kHzに設定しています。当然ですが周波数は通信データ量にほぼ直結するので、必要に応じてほどほどの値に設定します。

 
 

サンプルコード

入力と出力をくっつけて動くようにしたのが下記のコードです。実行にあたってはNAudioが必要でありアンマネージドライブラリの配置も必要なので、実行できない場合はBaku.LibqiDotNetのGithubとか「C#プログラムでPepperが聞いてる音をストリーミング」に載っている内容を確認してください。

  

うまく行った場合、実行してヘッドセット等から喋ればPepperから音が出ます。マイクが正しく選ばれずに失敗する場合はコントロールパネルで”sound”などのキーワードから検索してサウンド設定を開き、録音デバイスとして使いたいマイクを既定のデバイスに設定してください。

 
 

まとめ

終わってしまえばC++コードの移植以上のものではありませんでしたが、まあ「やればできるね」という話でした。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です