Android+BeagleBoardでAudioのダウンサンプリング


ITサービス様がBeagleBoard上のAndroidでAudioのダウンサンプリング動作を実装してくれましたので、その成果を公開させていただきたいと思います。

1.はじめに

 昨今話題となっているAndroid。既に多くの企業が参入しているなか、我々もキーワードとして注目していました。
そんな中、2009年度の組込み総合技術展に参加し、手作りAndroidケータイを拝見しながら、我々も何かをAndroidで作ってみようということで、Audioのダウンサンプリングを作成する運びになりました。


なぜAudioダウンサンプリングなのかというと・・・・
BeagleBoard Rev C3 での公開実績はまだ無い
Androidを作成の中で把握する
・Audio,Videoといったメディアに必要な部分の構造を理解し、カスタマイズできるようになる
といった所が挙げられます。


作成したAudioダウンサンプリング処理について、Android内のAudio入出力の流れを交えながら書いていきたいと思います。

1.1.ダウンサンプリングシステムについて

 BeagleBoardで起動するAndroidを使用し、Audioのサンプリング周波数を1/2にして再生するシステムを作成します。AudioのデバイスドライバにはAlsa Driverを用いることとします。

システム作成において、追加する内容は以下二点です。
・ ダウンサンプリング処理
・ ダウンサンプリング ON / OFFコマンド

1.2使用環境

 今回のダウンサンプリングシステムを導入した環境は以下の通りです。


表1.使用環境一覧

使用環境一覧
メインボード BeagleBoard Rev.C3
Android Ver Android 1.6(Donut)
Audio Driver ALSA
Android Kernel Ver 2.6.29(embinuxより取得)
PC環境 Ubuntu 8.10


□環境設定
 主にブリリアントサービス様 のRev.C2立ち上げの資料を参考にさせていただきました。ソースコードのVerに合わせ、Androidの初期化設定ファイルである、init.rcの内容を変更しました。

2.既存の音楽再生の流れ

Android内のAudio処理の流れ
 Android内のAudioの処理に新たな機能を追加する為に、Android上でのAudioの流れを簡略図で表した物が下図です。
 Javaアプリケーション内で、MediaPlayerクラスのメソッドを呼ぶことで、フレームワーク内でいくつかのコマンドが作成されます。
コマンドはOpencore内のキューを用いてスケジューリングされ、実行されます。
Opencore内にてコマンドが実行されることで、Audio データのデコードやAudio再生の処理が起動し、Driver、HardWareへと処理が渡り、音楽が再生されます。


図1.Android Audio処理の流れ図

3.システム作成での変更点

□ダウンサンプリングシステムの作成
 2節で取り上げたAndroid内のAudio処理の流れにおいて、Javaフレームワーク内に「ダウンサンプリング ON / OFF コマンド」を、Android ミドル部分Opencore内に「ダウンサンプリング処理」を追加します。
 2点を追加することで、Audioの1/2倍ダウンサンプリングに成功しています。以下項目にて詳細を説明します。

3.1.ダウンサンプリング ON / OFFコマンドの追加

 AndroidフレームワークのMediaPlayerクラスにダウンサンプリングコマンドを追加します。
 ダウンサンプリングコマンドは、JavaアプリケーションからダウンサンプリングのON/OFFを受け取り、Opencore内部に追加するダウンサンプリングの処理部分まで渡します。
以下に詳細実装方法を記します。

3.1.1.JAVAのソース変更箇所

 フレームワークに追加を行ったため、JAVAアプリケーションもダウンサンプリングコマンドを受け渡す処理を追加する必要があります。
処理を追加したアプリケーションのソースコードは下図のようになります。



図2.JAVAアプリケーションからの追加コマンドの使用方法


コマンドを追加することにより既存の再生関数(start())との変更点は下図のようになります。



図3.既存の再生関数との変更点

3.1.2.ソース変更後の処理シーケンス

 コマンドを追加した後の再生関数の処理シーケンスは下図のようになります。



図4.ソース変更後の処理シーケンス

3.1.3.実装箇所

 ダウンサンプリングコマンドで修正を加えたソースは以下の通りです。


表2. ダウンサンプリング ON / OFFコマンド ソース変更点一覧

3.2.ダウンサンプリング処理の変更点
3.2.1.Opencore内の処理の流れ

 Androidにデフォルトで備わっているMediaPlayerであるOpencoreの処理の流れの概略を下図に記述しました。



図5.Android Audio処理の流れ


今回のダウンサンプリングの処理では、Audioのデコード後データが表面化している、以下関数内で行うことにします。

○FilePath
android_root/external/opencore/android/android_audio_output.cpp
○関数名
AndroidAudioOutput::writeAudioBuffer()
3.2.2.ダウンサンプリング処理と追加内容

 ダウンサンプリングの処理の概念に関しては以下リンクを参考してください。


サンプリング周波数変換


 本システムでは、下記内容で実装します。

○ローパスフィルタ
取得したデコード後のAudioデータについて、4点移動平均を取ることで実装する。ただし、1サンプル量は量子化ビット16bitより、2byteとして扱う。
○間引き
ローパスフィルタを通した後のデータを、1サンプルデータ置きに間引く。ただし本システムでは、Audioデータをステレオ2chデータと考え、1サンプルを L+R の 4byte として扱う。
3.2.3.実装箇所

 追加するダウンサンプリングの処理のフローチャートは下図の通りです。



図6.Android Audio処理の流れ


 これに従い、下記の内容でソースコードの追加変更を行います。
 まず、3.1節にて作成した「 ON / OFF コマンド 」によって作成されるフラグを受け取る部分(getDownSamplFlag関数)を作成します。



 次に、作成したgetSamplFlag関数を使用し、フラグがONであれば現在のサンプリング周波数を1/2倍にします。



 次に、デコード後のAudioデータが表面化した部分にローパスフィルタと間引き処理を挿入します。
ソースコード内「 AudioDownSamplingExec関数 」はダウンサンプリングを行う自作関数です。




 最後に、ダウンサンプリングを行うAudioDownSamplingExec関数を(android_audio_output.cpp)内に記述します。



AudioDownSamplingExec関数内のwhileループ内がローパスフィルタの処理、forループ内が間引き処理に当たります。

4.まとめ

4.1.動作確認済み環境

 作成したシステムの動作確認のために下図のようなテストアプリを作成し、以下表の環境において、動作を確認しました。



図7.アプリケーション実行画面

 元データとダウンサンプリングされたデータを耳で比較した場合にも、出力された音の質が下がっていることが確認できました。
(特に、元データのサンプリング周波数が48Khz以下の場合に顕著に差を感じました。)

4.2.あとがき

 ダウンサンプリングの処理を行う関数の作成には、まず間引き処理の実装から入りました。
間引き処理のみの実装段階で音楽データが正常に再生されていましたので、後はローパスフィルタを入れるだけ!と作成したフィルタを間引き処理の前に挿入すると・・・


「ザーー・・・」


ほんの一時前まで鳴っていた音楽データが再生されなくなってしまいました。
原因は、移動平均を取る際にunsignedデータのまま計算していたことでした。
単純な話でしたが、気づくまではあれやこれやと修正をかけ、再生してみるの繰り返しでした。。。
signed / unsigned には気をつけようと学んだ入社一年目の新人のあとがきでした。


本システムの説明は以上で終了です。
長々と失礼致しました。
また、内容に間違い等がありましたらご指摘いただけると幸いです。




開発メンバ
 小林 弘典
 藤田 武大
 山形 泰之
 小林 慎治
 鈴木 匠
 嶋田 大輔


窓口担当
 今井利久


株式会社 アイティサービス
 URL http://www.upload-gp.co.jp/
 TEL 06-6910-8780