Android 使用Visualizer获取播放音频的频率

公羊俊
2023-12-01

最近项目中需要实时获取播放音频的频率,并绘制波形图,用到了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
    }

}
 类似资料: