最近项目中需要实时获取播放音频的频率,并绘制波形图,用到了Visualizer这个类,记录下其使用方法:
Visualizer.OnDataCaptureListener有两个回调方法,分别是onFftDataCapture和onWaveFormDataCapture,onFftDataCapture返回的是经过傅里叶变换处理后的音频数据,onWaveFormDataCapture返回的是声音的波形数据。
计算声音分贝部分代码:
val readyData = readyData(fft)
val interval = readyData.size / (lineCount * 2)
for (i in readyData.indices step interval) {
...
val magnitude = readyData[i] * readyData[i] + readyData[i + 1] * readyData[i + 1] * 1.0
val dbValue = (10 * log10(magnitude)).toLong().coerceAtLeast(0) // 声音大小
}
private fun readyData(fft: ByteArray): ByteArray {
val newData = ByteArray(256) // 取一半
for (i in 0 until fft.size.coerceAtMost(256)) {
newData[i] = abs(fft[i].toInt()).toByte()
}
return newData
}
Visualizer的使用:
class VisualizerHelper {
private var visualizer: Visualizer? = null
private var mediaPlayer: MediaPlayer? = null
/**
* 播放音乐
*/
fun playMusic(
path: String,
onCompletionListener: MediaPlayer.OnCompletionListener,
onDataCaptureListener: Visualizer.OnDataCaptureListener
) {
mediaPlayer = MediaPlayer().apply {
setDataSource(path)
setOnCompletionListener {
onCompletionListener.onCompletion(it)
release()
releaseVisualizer()
mediaPlayer = null
}
}
mediaPlayer?.prepare()
mediaPlayer?.start()
initVisualizer(onDataCaptureListener)
}
/**
* 停止播放
*/
fun stopMusic() {
mediaPlayer?.run {
stop()
release()
}
mediaPlayer = null
releaseVisualizer()
}
/**
* 获取当前播放进度
*/
fun getCurrentPosition(): Long {
return (mediaPlayer?.currentPosition ?: 0) / 1000L
}
private fun initVisualizer(
dataCaptureListener: Visualizer.OnDataCaptureListener
) {
if (visualizer != null) {
visualizer?.enabled = true
return
}
visualizer = Visualizer(mediaPlayer?.audioSessionId ?: 0)
visualizer?.run {
captureSize = Visualizer.getCaptureSizeRange()[1] // 设置可视化数据的数据大小
setDataCaptureListener(
dataCaptureListener,
Visualizer.getMaxCaptureRate() / 2, // 采集频率
false,
true
)
enabled = true
}
}
/**
* 释放
*/
private fun releaseVisualizer() {
visualizer?.run {
enabled = false
release()
}
visualizer = null
}
}