Windows Phone マイクからオーディオ入力を取得する

2011年10月3日(月)
PROJECT KySS

今回は、Silverlight アプリケーションでの Windows Phoneマイクからオーディオ入力を取得するサンプルを紹介します。

このプログラムで実装する機能の動作を、下記に解説しておきます。

実行すると、[記録]、[再生]、[中止]の3つのボタンが表示されます。最初に[記録]ボタンをクリックします。画面に「記録中・・・・」の文字が表示されます。この状態からマイクに向かって何か喋ると、音声が記録されます。筆者はPCにWebカメラを装着していますので、Webカメラに向かって喋りテストしました。

次に、[中止]をクリックします。「再生準備完了」の文字が表示されますので、この状態から[再生]ボタンをクリックします。「再生中・・・・」と表示され、いま記録した音声が再生されます。再生が終わると、「[再生]または[記録]ボタンをクリック」と表示されます(図1)。

図1: [記録]、[再生]、[中止]の3つのボタンで音声を記録再生する(クリックで拡大)

サンプルは以下よりダウンロードできます。
→ 「Windows Phone マイクからオーディオ入力を取得する」のサンプルファイル(298KB)
※サンプル実行でエラーが発生した場合は、「ソリューションのビルド」を実行後、再度、デバッグ開始を行ってください

プロジェクトの作成

VS 2010のメニューから[ファイル(F)/新規作成(N)/プロジェクト(P)]を選択します。次に、「Windows Phone アプリケーション」を選択して、「名前(N)」に任意のプロジェクト名を指定します。ここでは「WP7_Microphone」という名前を付けています。Windows Phoneのバージョンは、今回は7.0を選択します。

MainPage.xamlの編集とコントロールの追加

x:NameがPageTitleというTextBlockのTextプロパティに「Microphone」と指定します。

ツールボックスからButtonコントロールを3個、TextBlockコントロールを1個配置します。ButtonのContentとx:Nameには図2のように指定します。[再生]と[中止]ボタンのIsEnabledのチェックは外して、最初表示された時点ではクリック不可としておきます。またTexBlockコントロールの、プロパティウィンドウの[ブラシ]パネルにある、ForegroundにGoldを指定し文字色を黄色系統色にしています。[テキスト]パネル内の文字サイズには36と指定しておきます。

図2: Buttonコントロールを3個、TextBlockコントロールを1個配置する(クリックで拡大)

またVS2010のメニューから「プロジェクト(P)/参照の追加(R)」と選択して、Microsoft.Xna.Frameworkを追加しておきます(図3)。

図3: Microsoft.Xna.Framework を追加する(クリックで拡大)

日本語表示設定

Windows Phone 7.1 SDK RC 日本語版では、フォントの設定なしにアプリケーションを実行し、タイトルやテキストに日本語を使った場合、日本語フォントが使われないで変な表示になってしまうことがあります。これを解消するには、書き出されるXAMLコードのアプリケーションのトップである要素内に、 Language="ja-JP" と指定しておきます

書き出されるXAMLコードは省略します。

ソリューションエクスプローラー内のMainPage.xamlを展開して表示される、MainPage.xaml.vbをダブルクリックして、リスト1のコードを記述します。

ロジックコードを記述する

リスト1 (MainPage.xaml.vb)

Option Strict On

指定した時間の間隔で実行されるタイマーである、DispatcherTimerクラスの含まれる、System.Windows.Threading名前空間をインポートします。
Imports System.Windows.Threading

ゲームクラス (タイマー、ゲーム ループなど) を提供するクラスの含まれる、Microsoft.Xna.Framework名前空間をインポートします。フレームワークコンポーネント (メディアなど)の状態を更新する、FrameworkDispatcher.Update()メソッドを利用するために、この名前空間が必要です。
Imports Microsoft.Xna.Framework

オーディオ再生用のプログラミング・インターフェース (API) を提供するクラスの含まれる、Microsoft.Xna.Framework.Audio名前空間をインポートします。
Imports Microsoft.Xna.Framework.Audio
Imports System.IO

Partial Public Class MainPage
  Inherits PhoneApplicationPage
 
  Public Sub New()
    InitializeComponent()
  End Sub

マイクのオーディオ データのキャプチャに、プロパティ、メソッド、およびフィールドとイベントを提供するクラスであるMicrophoneのメンバ変数myMicrophoneを宣言し、Microphone.Defaultで、デフォルトで接続されているマイクを取得します。
  Dim myMicrophone As Microphone = Microphone.Default

マイクからオーディオ データを取得する動的バッファーを、Byte型のmyBuffer配列メンバ変数として宣言します。
  Dim myBuffer() As Byte

バッキング ストアとしてメモリを使用するストリームを作成するクラスである、MemoryStream型のメンバ変数myStreamを宣言します。
  Dim myStream As New MemoryStream

SoundEffectサウンドの単一再生、一時停止、または停止インスタンスを提供するクラスである、SoundEffectInstanceクラス型のメンバ変数mySoundを宣言します。
  Dim mySound As SoundEffectInstance

サウンド再生の状態を監視するフラグとして、Boolean型のメンバ変数myStateを宣言します。
  Dim myState As Boolean = False

ページが読み込まれた時の処理

タイマーを表す新しいDispatcherTimerクラスのインスタンスmyTimerオブジェクトを宣言します。
タイマーの実行される間隔を50ミリセコンドに指定します。
AddHandlerメソッドで、指定したタイマーの間隔が経過した時に発生するTickイベントに、イベントハンドラを追加します。イベントハンドラ内では以下の処理を実行します。
FrameworkDispatcher.Updateメソッドで、いろいろなフレームワークコンポーネント (メディアなど) の状態を更新します。XNA FrameworkDispatcherや、サウンドが再生されているかどうかをチェックして更新します。
サウンド再生の準備はできていて、SoundEffectのインスタンスが再生されていない場合は、サウンドの再生状態を監視するmyState変数にFalseを指定し、TextBlockにメッセージを表示します。[記録]ボタンの使用は可能、[中止]ボタンの使用は不可とします。Startメソッドでタイマーを実行します。
AddHandlerメソッドで、オーディオ キャプチャバッファーを処理する準備ができている時に発生するイベントである、BufferReadyイベントに、イベントハンドラを追加します。イベントハンドラ内では以下の処理を行います。GetDataメソッドでオーディオデータを取得します。MemoryStreamのWriteメソッドで、オーディオデータをストリームに格納します。Writeメソッドの書式は下記の通りです。

MemoryStream.Write(データの書き込み元となるBuffer,書き込むデータの開始位置,書き込む最大Byte数)

  Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    Dim myTimer As New DispatcherTimer()
    myTimer.Interval = TimeSpan.FromMilliseconds(50)
 
    AddHandler myTimer.Tick, Sub() 
                           FrameworkDispatcher.Update()
                           If myState = True AndAlso mySound.State <> SoundState.Playing Then
                                    myState = False
                                    TextBlock1.Text = "[再生]または[記録]ボタンをクリック"
                                    recordButton.IsEnabled = True
                                    stopButton.IsEnabled = False
                                End If
                           End Sub
    myTimer.Start()
 
    AddHandler myMicrophone.BufferReady, Sub()
                                            myMicrophone.GetData(myBuffer)
                                            myStream.Write(myBuffer, 0, myBuffer.Length)
                                       End Sub
  End Sub

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています