あけましておめでとうございます!
2011年もTechBoosterを宜しくお願い致します。
さて、2011年最初のHow To AndroidはAudioTrackを使ってWAVEデータを再生する方法についてご紹介します。
詳細はつづきからどうぞ。
AudioTrackクラスではバイトデータをオーディオハードウェアに直接書き込むことができるので、
MediaPlayerクラスと比べて高速に音を鳴らすことができます。
ゲームやGUIの効果音のような、リアルタイムに音を出したいというような用途に向いています。
コンストラクタ
AudioTrackクラスのコンストラクタは以下のようになっています。
AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode, int sessionId)
streamType | ストリームタイプを指定します。 |
sampleRateInHz | サンプルレートを指定します。 |
channelConfig | オーディオチャネルを指定します。 |
audioFormat | オーディオフォーマットを指定します。ENCODING_PCM_16BITとENCODING_PCM_8BITの2つがあります。 |
bufferSizeInBytes | オーディオデータのバッファサイズを指定します。 |
mode | STREAMモードかSTATICモードかいずれかを選択します。詳細は後述します。 |
sessionId | オーディオセッションIDを指定します。 |
STREAMモードとSTATICモード
AudioTrackクラスは以下の2つのモードで動作します。
- STREAMモード:
メモリに収まらない大きな音声データを再生したい場合、音声データを一定量ずつ、逐一ハードウェアに出力します。 - STATICモード:
メモリに収まる程度の小さな音声データは予めメモり領域上に置いておいて、それを必要なときにハードウェアに出力します。
サンプルコード
以下はAudioTrackクラスを使ってSDカードに保存してあるWAVEファイルを鳴らすサンプルです。
WAVEファイルはサンプリングレート44100Hz、オーディオチャネル2ch、16bitのものを使っています。
大きなバイトデータになりますので、STREAMモードを使います。
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // ボタンのインスタンスを作成 play_button = (Button) findViewById(R.id.Button01); stop_button = (Button) findViewById(R.id.Button02); // WAVEファイルのFileインスタンスを作成 file = new File("/sdcard/strings.wav"); // WAVEファイルのサイズを取得 byteData = new byte[(int) file.length()]; // WAVEファイルをロード FileInputStream in = null; try { in = new FileInputStream(file); in.read(byteData); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 再生用初期化処理 initialize(); // プレイボタン play_button.setOnClickListener(new OnClickListener() { public void onClick(View v) { // 再生用スレッドを起こす play_thread.start(); } }); // ストップボタン stop_button.setOnClickListener(new OnClickListener() { public void onClick(View v) { // 再生中なら停止させる if (myAT.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { myAT.stop(); play_thread = null; initialize(); } } }); } // 再生用初期化処理 void initialize() { // 必要となるバッファサイズを計算 bufSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); // AudioTrackインスタンス作成 myAT = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufSize, AudioTrack.MODE_STREAM); // スレッドインスタンス作成 play_thread = new Thread(this); } // 再生用スレッド処理 public void run() { if (myAT != null) { // 再生開始 myAT.play(); myAT.write(byteData, 0, byteData.length); } }
処理としては、SDカードに保存しているWAVEファイル用のFileインスタンスを作成し、WAVEファイルのバイトデータをFileInputStreamにロードします(10-26行目)
バイトデータをロードしたらAudioTrackインスタンスの初期化処理を行います(29行目, 52-67行目)。
ここで、WAVEファイルのサンプリングレートなどの情報をもとに必要なバッファサイズを計算し、AudioTrackインスタンスを作成します。
あとはボタンが押されたら再生を開始させます(35行目, 69-76行目)。
writeメソッドはバイトデータの書き込みが終わるまでブロックしてしまうのでスレッドで実行するようにしています。