音を扱うクラスとしてSoundPoolがあり、比較的短いものを遅延が少なく再生できるのでゲームの効果音の再生などに向いています。
下はAnimationとsound再生を同時に行った例です。
2021.1.1
SoundPool
Audioの再生にはこのSoundPool以外にもMediaPlayerやAudioTrackがあります。
- SoundPool
- 再生可能なフォーマット:mp3, ogg, wav(非圧縮), etc.
- Audio Mixerのように複数の音源を重ねて再生できる
- 事前にデコードしてメモリに展開するので低レイテンシー
- 再生できるのは5秒程度
- 繰り返し再生
- 再生スピードを可変できる
- それぞれの音源に優先度をつけられる
- ゲームの効果音再生に適している
- MediaPlayer
- Supported media formatsおそらくこれらをサポート
- BGMとしてあるいは楽曲の再生用途で使う
- AudioTrack
- メモリに直接展開して再生するので低レイテンシー
- 細かい操作ができる(してあげないといけない)
SoundPool
SoundPoolはLollipop以降使い方が変わりました。
- val audioAttributes = AudioAttributes.Builder()…
- val soundPool = SoundPool.Builder()…
- soundPool.load(…)
- soundPool.play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
- soundID: load()で決めたID
- leftVolume, rightVolume: 左音量, 右音量(range = 0.0 to 1.0)
- priority: (0 = lowest priority) default 0
- loop: (0 = no loop, -1 = loop forever)
- rate: (1.0 = normal playback, range 0.5 to 2.0)
SoundPoolは、事前に音源をロードしておく必要があります。いきなりロード再生ではうまくいきません。そのためアプリとして音源を抱えたままになりかねないため、release, unload等を使って
Out Of memory
に陥らない対策が必要です。
SoundPool、AudioAttributes
wavファイルを res/raw/ 以下に置きます。
「res」から「New」「Directory」
res以下にできたディレクトリーにwavファイルを入れます。参考までに以下wavファイルを名前をつけて保存できます。
one two
多くの音声ファイルをフォルダ階層で管理したい場合はassetsに置きます。ただし、assetsからのデータ取得はAssetManagerを使う作業が必要です。
サンプルコード
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
//package your.package.name import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.media.AudioAttributes import android.media.SoundPool import android.util.Log import android.view.animation.RotateAnimation //Kotlin Android Extensions import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private lateinit var soundPool: SoundPool private var soundOne = 0 private var soundTwo = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val audioAttributes = AudioAttributes.Builder() // USAGE_MEDIA // USAGE_GAME .setUsage(AudioAttributes.USAGE_GAME) // CONTENT_TYPE_MUSIC // CONTENT_TYPE_SPEECH, etc. .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build() soundPool = SoundPool.Builder() .setAudioAttributes(audioAttributes) // ストリーム数に応じて .setMaxStreams(2) .build() // one.wav をロードしておく soundOne = soundPool.load(this, R.raw.one, 1) // two.wav をロードしておく soundTwo = soundPool.load(this, R.raw.two, 1) // load が終わったか確認する場合 soundPool.setOnLoadCompleteListener{ soundPool, sampleId, status -> Log.d("debug", "sampleId=$sampleId") Log.d("debug", "status=$status") } button1.setOnClickListener{ // one.wav の再生 // play(ロードしたID, 左音量, 右音量, 優先度, ループ, 再生速度) soundPool.play(soundOne, 1.0f, 1.0f, 0, 0, 1.0f) // ボタンの回転アニメーション val buttonRotation = RotateAnimation( 0f, 360f, (button1.width/2).toFloat(), (button1.height/2).toFloat() ) buttonRotation.duration = 2000 button1.startAnimation(buttonRotation) } button2.setOnClickListener { // two.wav の再生 soundPool.play(soundTwo, 1.0f, 1.0f, 1, 0, 1.0f) // ボタンの回転アニメーション val buttonRotation = RotateAnimation( 0f, 360f, (button1.width/2).toFloat(), (button1.height/2).toFloat() ) buttonRotation.duration = 2000 button2.startAnimation(buttonRotation) } } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" android:background="#dfe" tools:context=".MainActivity"> <Button android:id="@+id/button1" android:text="@string/one" android:textSize="20sp" android:layout_margin="40dp" android:layout_width="200dp" android:layout_height="wrap_content" /> <Button android:id="@+id/button2" android:text="@string/two" android:textSize="20sp" android:layout_margin="40dp" android:layout_width="200dp" android:layout_height="wrap_content" /> </LinearLayout> |
strings.xml
1 2 3 4 5 |
<resources> <string name="app_name">YourAppName</string> <string name="one">One</string> <string name="two">Two</string> </resources> |
build.gradle
1 2 3 4 5 6 7 |
android{ ... buildFeatures { viewBinding true } } |
ついでに、ボタンを押してSoundPoolで音を再生し、ボタンを回転させてみました。
References:
SoundPool
AudioAttributes