読者です 読者をやめる 読者になる 読者になる

Natural Software

KinectなどのDepthセンサーを中心に活動しています

Kinect for Windows SDK v2.0 で音データを取得する

Kinect for Windows v2

Kinect for Windows SDK v2.0入門 目次

音について紹介します。Kinect v2を使ってできる音に関する機能は次の3つです。

  • 音データを取得する
  • 音の方向を取得する
  • 音声認識エンジンを使って、音声をテキスト化する

音データについて、v1では16bitのデータだったものが、v2では32bit IEEEフォーマットになってようです。この辺り詳しくないのですが、ハイレゾと呼ばれるものが24bitだそうで、それよりも良い音になるのでしょうか。

実際に取れるデータはモノラルのようで、これはどうなのかな?ということはありますが。

音の方向について、v1ではKinectを中心に左右50度、10度単位での取得でしたが、v2では左右50度(変わらず)、1度単位で取得できるようになり、より細かくなりました。また、音方向とTrackingIdの関連付けも自動でやってくれるので、「誰がしゃべってるか」が簡単に取れるようになりました。BodyIndexも独立して、より分かりやすくなったのがいいですね。

音声認識エンジンとの連携については、音声認識エンジン(Microsoft.Speech)ライブラリが16bitデータのようで、変換が必要になります。C#(デスクトップ)のサンプルに変換コードが付いているので、これを利用すればよいでしょう。

アプリケーションに音を取り込む方法がさまざまあり、取り込み方も簡単になったので、使ってみてください。

ここでは音データの取り出し方について解説します。なお、手元の環境でC#(Windowsストアアプリ)でAudioStreamが動作しないので、C++およびC#(デスクトップ)のみコードを掲載します。

なお、C++の場合は、この実装のほかにもいくつか実装方法があるようです。

環境

筆者の環境は次の通りです。

実行結果

音を記録したwavファイルが生成されます。

解説

音の取得についての初期化手順ははほかのデータとほぼ同じ方法で取得します。AudioSource、AudioBeamFrameReaderを使用します。データ取得については、ビームフレームおよびビームサブフレームをリストとして持っており、これらを順に取得して、最終的にはビームサブフレームから音データを受け取ります。

音データはAudioSource.SubFrameLengthInBytesで取得できるサイズ(1024バイト)のデータとなります。実際には32bit IEEEフォーマットなので、floatとなるため1/4の256個のデータからなり、これで16msec分のようです。

なお、定かではありませんが、ビームフレームがリストになっていること、サンプルのコメントを見ると「現状ではビーム方向は1つだけ」と書かれていることから、ビーム方向を複数検出する機能も持っているのではないかと推測できます。

初期化

初期化の手順は次の通りです

  1. Kinectを開く
  2. ビームリーダーを開く

まずKinectを開きます。続いてAudioSourceを使って赤外線画像リーダーを作成し、データの読み込み準備を行います。データの読み込みは、C++ではポーリング、C#ではイベントハンドラの登録を行います。また音バッファのためにバッファサイズをSubFrameLengthInBytesで取得します。

C++

void initializeAudioSource()

{

// オーディオを開く

ComPtr<IAudioSource> audioSource;

ERROR_CHECK( kinect->get_AudioSource( &audioSource ) );

ERROR_CHECK( audioSource->OpenReader( &audioBeamFrameReader ) );

ERROR_CHECK( audioSource->get_SubFrameLengthInBytes( &subFrameLengthInBytes ) );

// バッファを作成する

audioBuffer.resize( subFrameLengthInBytes / sizeof( float ) );

audioFile.Open( "audio.wav" );

}

C#(デスクトップ)

private void Window_Loaded( object sender, RoutedEventArgs e )

{

try {

// Kinectを開く

kinect = KinectSensor.GetDefault();

kinect.Open();

// 音声バッファを作成する

audioBuffer = new byte[kinect.AudioSource.SubFrameLengthInBytes];

// 音声リーダーを開く

audioBeamFrameReader = kinect.AudioSource.OpenReader();

audioBeamFrameReader.FrameArrived += audioBeamFrameReader_FrameArrived;

audioBeamFrameReader.IsPaused = true;

}

catch ( Exception ex ) {

MessageBox.Show( ex.Message );

Close();

}

}

C#(Windows ストアアプリ)

なし

データの取得

続いてデータを取得し表示します。C++ではポーリング、C#ではイベントハンドラになります。

  1. AudioBeamFrameListを取得する
  2. AudioBeamFrameListから、最初(0番目)のAudioBeamFrameを取得する
  3. AudioBeamFrameから、最初(0番目)のAudioBeamSubFrameを取得する
  4. AudioBeamSubFrameから音データを取得する
  5. 取得した音データを処理する

ここでは、取得した音データをwavファイルに書き込んでいます。

wavファイルへの書き込み方は「AudioCaptureRaw-Console」を参考にしています。なお、「AudioCaptureRaw-Console」はWASAPIを使っているようで、またデータの取り方が違うようです(入力チャネルが4になっている。こちらは1)。これによって、再生する音データの速度が速くなっています。間違いがあると思うのですが、見つけたら教えてもらえると嬉しいです。

C++

void updateAudioFrame()

{

ComPtr<IAudioBeamFrameList> audioBeamFrameList;

auto ret = audioBeamFrameReader->AcquireLatestBeamFrames( &audioBeamFrameList );

if ( ret != S_OK ){

return;

}

ComPtr<IAudioBeamFrame> audioBeamFrame;

ERROR_CHECK( audioBeamFrameList->OpenAudioBeamFrame( 0, &audioBeamFrame ) );

ComPtr<IAudioBeamSubFrame> audioBeamSubFrame;

ERROR_CHECK( audioBeamFrame->GetSubFrame( 0, &audioBeamSubFrame ) );

audioBeamSubFrame->CopyFrameDataToArray( subFrameLengthInBytes, (BYTE*)&audioBuffer[0] );

audioFile.Write( &audioBuffer[0], subFrameLengthInBytes );

}

C#(デスクトップ)

void audioBeamFrameReader_FrameArrived( object sender, AudioBeamFrameArrivedEventArgs e )

{

using ( var audioFrame = e.FrameReference.AcquireBeamFrames() ) {

if ( audioFrame == null ) {

return;

}

var subFrame = audioFrame[0].SubFrames[0];

subFrame.CopyFrameDataToArray( audioBuffer );

waveFile.Write( audioBuffer );

// (例)実際のデータは32bit IEEE floatデータなので変換する

float audioData1 = BitConverter.ToSingle( audioBuffer, 0 );

float audioData2 = BitConverter.ToSingle( audioBuffer, 4 );

float audioData3 = BitConverter.ToSingle( audioBuffer, 8 );

}

}

C#(Windows ストアアプリ)

なし

まとめ

v1と比べて音データがよくなっているようです。次に紹介する音声方向の取得および、音声認識を組み合わせて、見た目だけではなく、音も活用するアプリケーションができるといいですね。

Kinect for Windows SDK v2.0入門 目次