Android Tips #48 BGM や効果音を再生する
Android アプリで音データを再生するには
Android アプリで BGM や効果音などのような音データを再生するにはいくつか方法(クラス)があります。ただ方法が分かれているわけではなく、それぞれのクラスには特徴があるので再生したいデータや場面に応じて適切なクラスを使う必要があります。
ということで、SoundPool、MediaPlayer、AudioTrack、JetPlayer のそれぞれのクラスの使いかたと特徴をまとめました。
SoundPool
SoundPool は短い音データの再生に適したクラスです。ファイルサイズによっては読み込みに少し時間が必要な場合はありますが、一度読み込んでしまえば遅延なく再生できます。
特徴
- データをあらかじめデコード、Nativeのヒープ領域に一時展開して再生する
- データの読み込みに時間がかかるが、一度読み込んでしまえば遅延は少ない
- 1つのインスタンスで複数のデータを再生できる
- 再生できるデータは10秒程度まで
- 効果音の再生に適している
サンプル
private SoundPool mSoundPool; private int mSoundId; @Override protected void onResume() { super.onResume(); // 予め音声データを読み込む mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0); mSoundId = mSoundPool.load(getApplicationContext(), R.raw.cat, 0); } @Override protected void onPause() { super.onPause(); // リリース mSoundPool.release(); } private void playFromSoundPool() { // 再生 mSoundPool.play(mSoundId, 1.0F, 1.0F, 0, 0, 1.0F); }
音声データの読み込みは onResume() のときなど実際に再生するときより前に処理しておいたほうが良いでしょう。
MediaPlayer
MediaPlayer は音楽ファイルなどの再生に適しているクラスです。ストリーミング再生ができるので、サーバーにある音データをストリーミング再生する、などという実装ができます。
特徴
- 音データをストリーミング再生する
- 尺が長い音データの再生ができる
- 同時に4つまでしか再生できない(らしい)
- BGM の再生に適している
サンプル
private void playFromMediaPlayer() { MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.strings); mediaPlayer.start(); }
AudioTrack
AudioTrack はバイトデータを再生するクラスです。プログラム上から動的作った音データを再生するときに適しています。
特徴
- 音データをバイト配列で渡して再生する
- MODE_STATIC と MODE_STREAM の2つのモードを選択できる
- 音データをプログラムから動的に作って再生したい場合に適している
サンプル
private void playFromAudioTrack() { try { // 音データを読み込む InputStream is = getResources().openRawResource(R.raw.bird); byte[] byteData = new byte[(int) is.available()]; is.read(byteData); is.close(); // バッファサイズを取得 int bufSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); // AudioTrackインスタンスを生成 AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufSize, AudioTrack.MODE_STREAM); // 再生 audioTrack.play(); audioTrack.write(byteData, 0, byteData.length); } catch (IOException e) { e.printStackTrace(); } }
データの読み込みが発生しているので、実際に使う場合は非同期で実装しましょう。また、サンプルソースでよく見かける AudioFormat.CHANNEL_CONFIGURATION_MONO は非推奨になっているので AudioFormat.CHANNEL_OUT_MONO を使いましょう。
以下の記事で音データをプログラムから作って再生する方法が載っていますので、ぜひ参考にしてください!
【クリスマスだし】Androidで8ビット音を生成してジングルベルを奏でてみる【25日目の1】
JetPlayer
JetPlayer は JET 形式のファイルを再生するためのクラスです。複数の音データを1ファイルにでき、そのデータを読み込んで管理できるところが特徴です。
特徴
- 主に MIDI 形式のファイルをベースにして作る JET 形式のファイルを再生する
- 複数の音データを一つのファイルとして扱い、管理することができる
- 鍵盤アプリなど、インタラクティブなアプリに適している
サンプル
private void playFromJetPlayer() { // JetPlayerインスタンスを取得 JetPlayer jetPlayer = JetPlayer.getJetPlayer(); // 既存のキューをクリア jetPlayer.clearQueue(); // JETファイルの読み込み jetPlayer.loadJetFile(getResources().openRawResourceFd(R.raw.level1)); // 指定したセグメントの音データを再生 byte segmentId = 0; jetPlayer.queueJetSegment(1, 0, 1, 0, 0, segmentId); jetPlayer.play(); }
サンプルの JET データは Android SDK のサンプルソースを使いました。samples/android-17/JetBoy がプロジェクトファイルなのでこれをインポートして試してみても良いと思います。
ソースコード
今回サンプルで作ったソースコードを GitHub に公開しました!それぞれのクラスでどんな感じで再生されるのか確かめたいときに使ってください。
なお、再生した音データは以下のサイト様よりいただきました!ありがとうございます。
まとめ
ということで、効果音には SoundPool を、BGM には MediaPlayer を使っていけば良さそうです。BGM や効果音を取り扱うアプリはゲームが主流ですが、タップしたときの効果音に使うなど、どんなアプリにおいても分かりやすいフィードバックになると思うので、ぜひ活用していきたいところです。まぁ、マナーモードにされると無意味なんですが…。
特徴を簡潔にまとめましたが、ご指摘大歓迎です!ここが違うよなどありましたらぜひぜひお気軽にコメントください。