ブログ@kaorun55

HoloLensやKinectなどのDepthセンサーを中心に書いています。

KINECT SDK Beta2 で音源方向を取得する(C#) #kinectsdk_ac

このエントリはKINECT SDK Advent Calendar 2011 : ATNDの12月23日分です
Advent Calendarでの、僕の全プロジェクトはこちらです


今回は、Kinectの特徴的な機能の一つである、音源方向の取得をやってみます。
音声の取得はマイクなどでできますが、その音源の方向となるとなかなか取得できる機材はないのではないでしょうか。この値段であればなおさらだと思います。
基本的なコードは以前の音声と同じで、差分を解説します。

全体のコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Research.Kinect.Audio;
using System.IO;

namespace AudioDiretion
{
    class Program
    {
        static void Main( string[] args )
        {
            // 音源を取得するインスタンスを生成する
            using ( KinectAudioSource source = new KinectAudioSource() ) {
                // SingleChannelAec:シングルチャネルのマイクで、エコーキャンセルを使用する
                // OptibeamArrayOnly:マルチチャネルのマイクのみを使用する(エコーキャンセルを使用しない)
                // OptibeamArrayAndAec:マルチチャネルのマイクと、エコーキャンセルを使用する)
                // SingleChannelNsAgc:シングルチャネルのマイクのみを使用する(エコーキャンセルを使用しない)
                source.SystemMode = SystemMode.OptibeamArrayOnly;
                source.BeamChanged += new EventHandler<BeamChangedEventArgs>( source_BeamChanged );

                using ( Stream audioStream = source.Start() ) {
                    Console.WriteLine( "Start... Press any key" );

                    byte[] buffer = new byte[4096];
                    Win32.StreamingWavePlayer player = new Win32.StreamingWavePlayer( 16000, 16, 1, 100 );
                    while ( !Console.KeyAvailable ) {
                        int count = audioStream.Read( buffer, 0, buffer.Length );
                        player.Output( buffer );

                        // 詳細な音源方向の信頼性がある場合、音源方向を更新する
                        if ( source.SoundSourcePositionConfidence > 0.9 ) {
                            Console.Write( "詳細な音源方向(推定) : {0}\t\tビーム方向 : {1}\r",
                                source.SoundSourcePosition, source.MicArrayBeamAngle );
                        }
                    }
                }
            }
        }

        static void source_BeamChanged( object sender, BeamChangedEventArgs e )
        {
            Console.WriteLine( "ビーム方向が変わった:{0}", e.Angle );
        }
    }
}

解説

音源方向には、「ビーム方向」と「音源方向」という2つのパラメータがあります。両方とも、Kinectの中心を0度として、Kinectから見て右がマイナス、左がプラスになっています。また、単位は「ラジアン」です。
「ビーム方向」はKinectが音源方向の推定に使用するためのもので、Kinectの中心から10度ずつ、左右5本の、計11本のビームが出ています。このビーム方向のどこからでているか。というのが「ビーム方向」で、こちらは変更されるとイベントが発生します。
「音源方向」はさらに詳細にどの方向から出ているか。というパラメータです。こちらの変更はイベントでは通知されず、KinectAudioSource.SoundSourcePositionConfidenceという信頼性のパラメータで更新を取得します。
それぞれの具体的なイメージは下記の図のようになっています。これはCodePlexにあるサンプルです。

  • 「緑」の線が、それぞれのビームの方向を表しています。
  • 「青」の線が、現在の音源方向になっている「ビーム方向」を表します。
  • 「オレンジ」の線が、現在の音源方向の詳細な推定位置を表しています。


Kinectの音源方向はマイクアレイを使って実現していますので、もちろんKinectAudioSource.SystemModeにはマイクアレイを使う設定をする必要があります。シングルモードにした場合でも例外などは発生しないようです。

ビーム方向の変更イベント

ビーム方向の変更を受け取るイベントを登録します。

source.BeamChanged += new EventHandler<BeamChangedEventArgs>( source_BeamChanged );
ビーム方向の変更イベント

ビーム方向が変わると発生するイベントです。BeamChangedEventArgs.Angleに変更後の位置(ラジアン)が入っています。

static void source_BeamChanged( object sender, BeamChangedEventArgs e )
{
    Console.WriteLine( "ビーム方向が変わった:{0}", e.Angle );
}
音源方向の更新

音源の方向を取得します。音源はKinectAudioSource.SoundSourcePositionで取得できますが、この値には信頼性パラメータ(KinectAudioSource.SoundSourcePositionConfidence)が付加されており、このパラメータが一定以上になった場合のみ使用するようにします。 音源の方向と同時に、ビームの方向もKinectAudioSource.MicArrayBeamAngleで取得しています。

// 詳細な音源方向の信頼性がある場合、音源方向を更新する
if ( source.SoundSourcePositionConfidence > 0.9 ) {
    Console.Write( "詳細な音源方向(推定) : {0}\t\tビーム方向 : {1}\r",
        source.SoundSourcePosition, source.MicArrayBeamAngle );
}

まとめ

いままでKinectの音声は難しいと思ってたのですが、サンプルをばらして最小限にすると、ぜんぜん難しくないですね。
音声をつかったアプリケーションはなかなか面白いので、これを機に色々やってみようと思います。