int audioFormat,
int bufferSizeInBytes,
int mode,
int sessionId)
* streamType,Android手机上提供音频管理策略,按下音量键我们会发现由媒体声音管理,闹铃声音管理,通话声音管理等等,当系统有多个进程需要播放音频的时候,管理策略会决定最终的呈现效果,该参数的可选值将以常量的形式定义在类AudioManager中,主要包括以下内容:
· STREAM\_VOCIE\_CALL:电话声音
· STREAM\_SYSTEM:系统声音
· STREAM\_RING:铃声
· STREAM\_MUSCI:音乐声
· STREAM\_ALARM:警告声
· STREAM\_NOTIFICATION:通知声
因为这里是播放音频,所以我们选择`STREAM_MUSCI`。
* sampleRateInHz,采样率,即播放的音频每秒钟会有多少次采样,可选用的采样频率列表为:8000、16000、22050、24000、32000、44100、48000等,一般采用人能听到最大音频的2倍,也就是44100Hz。
* channelConfig,声道数的配置,可选值以常量的形式配置在类AudioFormat中,常用的是CHANNEL\_IN\_MONO(单声道)、CHANNEL\_IN\_STEREO(立体双声道)
* audioFormat,采样格式,可选值以常量的形式定义在类AudioFormat中,分别为ENCODING\_PCM\_16BIT(16bit)、ENCODING\_PCM\_8BIT(8bit),一般采用16bit。
* bufferSizeInBytes,其配置的是AudioTrack内部的音频缓冲区的大小,可能会因为生产厂家的不同而有所不同,为了方便AudioTrack提供了一个获取该值最小缓冲区大小的方法`getMinBufferSize`。
* mode,播放模式,AudioTrack提供了两种播放模式,可选的值以常量的形式定义在类AudioTrack中,一个是MODE\_STATIC,需要一次性将所有的数据都写入播放缓冲区中,简单高效,通常用于播放铃声、系统提醒的音频片段;另一个是MODE\_STREAM,需要按照一定的时间间隔不间断地写入音频数据,理论上它可以应用于任何音频播放的场景。
* sessionId,AudioTrack都需要关联一个会话Id,在创建AudioTrack时可直接使用`AudioManager.AUDIO_SESSION_ID_GENERATE`,或者在构造之前通过`AudioManager.generateAudioSessionId`获取。
上面这种构造方法已经被弃用了,现在基本使用如下构造(最小skd 版本需要>=21),参数内容与上基本一致:
public AudioTrack (AudioAttributes attributes,
AudioFormat format,
int bufferSizeInBytes,
int mode,
int sessionId)
通过`AudioAttributes.Builder`设置参数streamType
var audioAttributes = AudioAttributes.Builder()
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
.build()
通过`AudioFormat.Builder`设置channelConfig,sampleRateInHz,audioFormat参数
var mAudioFormat = AudioFormat.Builder()
.setChannelMask(channel)
.setEncoding(audioFormat)
.setSampleRate(sampleRate)
.build()
### [](https://blog.csdn.net/u012165769/article/details/109730722)切换播放状态
首先通过调用`getState`判断AudioRecord是否初始化成功,然后通过`play`切换成录播放状态
if (null!=audioTrack && audioTrack?.state != AudioTrack.STATE_UNINITIALIZED){
audioTrack?.play()
}
### [](https://blog.csdn.net/u012165769/article/details/109730722)开启播放线程
开启播放线程
thread= Thread(Runnable {
readDataFromFile()
})
thread?.start()
将数据不断的送入缓存区并通过AudioTrack播放
private fun readDataFromFile() {
val byteArray = ByteArray(bufferSizeInBytes)
val file = File(externalCacheDir?.absolutePath + File.separator + filename)
if (!file.exists()) {
Toast.makeText(this, "请先进行录制PCM音频", Toast.LENGTH_SHORT).show()
return
}
val fis = FileInputStream(file)
var read: Int
status = Status.STARTING
while ({ read = fis.read(byteArray);read }() > 0) {
var ret = audioTrack?.write(byteArray, 0, bufferSizeInBytes)!!
if (ret == AudioTrack.ERROR_BAD_VALUE || ret == AudioTrack.ERROR_INVALID_OPERATION || ret == AudioManager.ERROR_DEAD_OBJECT) {
break
}
}
fis.close()
}
###