前面のいくつかの記事では、MediaCodec
、MediaMuxer
、AudioRecord
などの音声およびビデオに関連する知識について説明しました。これらはすべて Android の音声およびビデオ開発で必要なものであり、以下の関連記事へのリンクを含みます:
- Camera2、MediaCodec での mp4 の録画
- Android のネイティブなエンコードおよびデコードインターフェースである MediaCodec の詳細
- AudioRecord を使用した音声データのキャプチャと合成 - jzman
Android で一般的に使用されるオーディオ再生インターフェースには、MediaPlayer
、AudioTrack
、SoundPool
があります。オーディオのレンダリングには、AudioTrack
とOpenSL ES
が最も一般的に使用されます。以下では、AudioTrack
に関連する情報を紹介します。主な内容は次のとおりです:
- AudioTrack の紹介
- AudioTrack の作成
- AudioTrack へのオーディオデータの書き込み
- AudioTrack のライフサイクル
- AudioTrack の使用方法
AudioTrack の紹介#
AudioTrack
は、元のpcm
形式のオーディオデータを再生するために使用されます。AudioTrack
には 2 つの再生モードがあります:
MODE_STATIC
:このモードでは、オーディオデータは一度にオーディオバッファに書き込まれます。メモリが少なく、できるだけ遅延の少ない短い音声シーン(ゲームの効果音、着信音、システムの通知音など)の処理に適しています。このモードでは、最小のオーバーヘッドが発生します。MODE_STREAM
:このモードでは、オーディオデータが継続的に書き込まれます。オーディオデータを継続的に受け取る必要がある場合に使用されます。このモードは、一部のオーディオデータが長時間続くか、またはオーディオの特性(高いサンプリングレート、より高いビット深度など)により、メモリに一度に書き込むことができない場合に使用されます。PCM
形式のオリジナルオーディオデータを正常に再生するには、このモードを選択します。
MediaPlayer
と比較すると、MediaPlayer
は異なるタイプや形式の音声ファイルを再生できますが、内部で対応するオーディオデコーダが作成されます。一方、AudioTrack
はPCM
形式のオリジナルオーディオデータのみを受け取ります。MediaPlayer
は内部でAudioTrack
を作成し、デコードされたPCM
ストリームをAudioTrack
に渡し、AudioTrack
はAudioFlinger
にミキシングされ、最終的にハードウェアで再生されます。
AudioTrack の作成#
AudioTrack
は、次の方法で作成されます:
// Android 5.0以降
AudioTrack(
attributes: AudioAttributes!,
format: AudioFormat!,
bufferSizeInBytes: Int,
mode: Int,
sessionId: Int)
上記のコンストラクタのパラメータは次のような意味を持ちます:
- attributes:オーディオストリームの情報を表す属性のセットです。Android 5.0 以降では、
AudioAttributes
を使用してストリームタイプの設定を置き換えるようになりました。より多くの情報を伝えることができるため、オーディオの目的や内容などを設定するために使用されます。 - format:
AudioTrack
が受け入れるオーディオフォーマットを表します。リニア PCM の場合、サンプルごとのサイズ(8、16、32 ビット)と表現形式(整数型、浮動小数点型)を反映します。オーディオフォーマットはAudioFormat
で定義されており、一般的なオーディオデータフォーマットでは、AudioFormat.ENCODING_PCM_16BIT
のみがすべてのデバイスで正常に使用できることが保証されています。AudioFormat.ENCODING_PCM_8BIT
のようなフォーマットは、すべてのデバイスで正常に使用できることが保証されていません。 - bufferSizeInBytes:オーディオデータバッファのサイズをバイト単位で表します。一般的に、バッファサイズはオーディオフレームサイズの非ゼロの倍数である必要があります。再生モードが
MODE_STATIC
の場合、バッファサイズは再生するオーディオのサイズになります。再生モードがMODE_STREAM
の場合、バッファサイズは最小バッファサイズより小さくすることはできず、getMinBufferSize
が返すサイズより小さくすることはできません。 - mode:再生モードを表します。
AudioTrack
はMODE_STATIC
とMODE_STREAM
の 2 つのモードを提供しています。MODE_STATIC
はオーディオリソースを一度にオーディオバッファに書き込みます。遅延が小さく、オーディオリソースのメモリ使用量が少ないシーン(着信音、システムの通知音など)に適しています。MODE_STREAM
は、データを継続的に書き込む必要があるシーンに適しています。MODE_STATIC
に比べて遅延があるかもしれませんが、継続的にオーディオデータを受け取ることができます。 - sessionId:オーディオセッション ID です。ここでは
AudioManager.AUDIO_SESSION_ID_GENERATE
を使用して、下層のオーディオフレームワークが自動的にsessionId
を生成するようにします。
AudioTrack へのオーディオデータの書き込み#
ストリームモード(STREAM_MODE
)または静的バッファモード(STATIC_MODE
)のいずれかで、再生するためにはwrite
メソッドを使用してオーディオデータを書き込む必要があります。主なwrite
メソッドは次のとおりです:
// AudioTrackのコンストラクタで指定されたフォーマットはAudioFormat#ENCODING_PCM_8BITである必要があります
open fun write(audioData: ByteArray, offsetInBytes: Int, sizeInBytes: Int): Int
// AudioTrackのコンストラクタで指定されたフォーマットはAudioFormat#ENCODING_PCM_16BITである必要があります
open fun write(audioData: ShortArray, offsetInShorts: Int, sizeInShorts: Int): Int
// AudioTrackのコンストラクタで指定されたフォーマットはAudioFormat#ENCODING_PCM_FLOATである必要があります
open fun write(audioData: FloatArray, offsetInFloats: Int, sizeInFloats: Int, writeMode: Int): Int
オーディオデータの書き込みは、0 以上の値を返します。一般的なオーディオデータの読み取り例外は次のとおりです:
- ERROR_INVALID_OPERATION:
AudioTrack
が初期化されていません。 - ERROR_BAD_VALUE:パラメータが無効です。
- ERROR_DEAD_OBJECT:オーディオデータが一部転送された場合にエラーコードが返されない場合、次の
write
呼び出しでエラーコードが返されます。
これは、AudioRecord
のread
メソッドといくつかの類似点があります。詳細については、公式ドキュメントを参照してください。
AudioTrack のライフサイクル#
AudioTrack
のライフサイクルは、主にSTATE_UNINITIALIZED
、STATE_INITIALIZED
、STATE_NO_STATIC_DATA
の 3 つの状態で構成されます。STATE_INITIALIZED
はSTREAM_MODE
に対応し、STATE_NO_STATIC_DATA
はSTATIC_MODE
に対応します。再生状態はあまり重要ではありません。以下の図に示すようになります:
AudioTrack の使用方法#
AudioTrack
の使用方法は、PCM
ファイルからデータを読み取り、読み取ったオーディオをAudioTrack
に書き込んで再生することです。主なコードは次のとおりです:
// AudioTrackの初期化
private fun initAudioTrack() {
bufferSize = AudioTrack
.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT)
attributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA) // オーディオの用途を設定
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) // オーディオのコンテンツタイプを設定
.build()
audioFormat = AudioFormat.Builder()
.setSampleRate(SAMPLE_RATE)
.setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.build()
audioTrack = AudioTrack(
attributes, audioFormat, bufferSize,
AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE
)
}
// AudioTrackへのオーディオデータの書き込み
private fun writeAudioData(){
scope.launch(Dispatchers.IO){
val pcmFile = File(pcmFilePath)
val ins = FileInputStream(pcmFile)
val bytes = ByteArray(bufferSize)
var len: Int
while (ins.read(bytes).also { len = it } > 0){
audioTrack.write(bytes, 0, len)
}
audioTrack.stop()
}
}
// 再生を開始
private fun start(){
audioTrack.play()
writeAudioData()
}
AudioTrack
の使用方法は基本的に上記のとおりです。AudioTrack
でオーディオを再生する関連するコードに興味がある場合は、コメントを残してください。