You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从AudioRecord读取的ShortArray数据中提取音频振幅

从AudioRecord读取的ShortArray中提取振幅的实现方法

你当前用ShortArray接收音频数据的写法,是适配安卓平台最通用的AudioFormat.ENCODING_PCM_16BIT(16位有符号PCM)音频格式的标准写法,比处理ByteArray少了手动拼接高低位字节的步骤,提取振幅的逻辑更简单。

16位PCM单个采样点的取值范围为-32768~32767,和Kotlin中Short类型的取值范围完全匹配,你可以根据业务场景直接计算两类常用振幅值:

  • 瞬时峰值振幅:响应速度快,适合做实时跳变的峰值电平条、突发爆音检测。计算逻辑为遍历当前帧所有采样点,取绝对值的最大值。
    注意必须先将Short值转为Int再取绝对值,否则Short.MIN_VALUE(-32768)取绝对值时会发生数值溢出,得到错误结果:
    var peakAmp = 0
    for (sample in data) {
        val absVal = sample.toInt().absoluteValue
        if (absVal > peakAmp) peakAmp = absVal
    }
    // 输出范围0~32767,数值越大振幅越高
    
  • RMS均方根振幅:反映音频帧的平均能量,更贴合人耳对响度的实际感知,不会被单个异常尖峰干扰,是普通音量检测、平均电平显示的首选方案。计算逻辑为对帧内所有采样点求平方和的均值,再开平方:
    import kotlin.math.sqrt
    
    var squareSum = 0.0
    for (sample in data) {
        val intVal = sample.toInt()
        squareSum += intVal * intVal
    }
    val rmsAmp = sqrt(squareSum / data.size).toInt()
    // 输出范围0~32767
    

如果需要将振幅映射到0~1的归一化区间(比如绑定UI进度条、设置音量触发阈值),直接将计算得到的振幅值除以32767.0即可:

val normalPeak = peakAmp / 32767.0f
val normalRms = rmsAmp / 32767.0f

网上流传的基于ByteArray的振幅提取方案,核心逻辑是先将每两个连续字节按小端序拼接为16位Short值,再执行和上述完全一致的振幅计算。你直接读取ShortArray的方式,相当于系统已经帮你完成了字节拼接、字节序处理的底层步骤,代码更简洁,运行效率更高,也能避免手动处理字节时容易出现的高低位错位、字节序错误等问题。

内容的提问来源于stack exchange,提问作者Pavel Poley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 18:33:31