PCM静默检测

静默检测首先要能计算某段音频数据的音量大小,那么首先有两个个公式明确:

dB = 20 * log(P1/P2)

其中P1/P2可以看作一个整体的阈值;
当声音采样深度为16bit时,P1/P2 = 65535,即dB ≈ 96;
当不确定P1/P2具体值时,那么就有

dB = 20 * log(音频数据)

另外,音频数据大小也有一个公式可表示:

数据量(字节/秒) = 采样率(Hz) * 采样大小(bit) * 声道数  / 8

这里有一个JAVA表示的计算分贝方法:

	/**
	 * 计算输入数据段的db值,按公式应该为20*Math.log10(当前振幅值/最大振幅值);
	 * 位深为16bit,则代表两个字节表示一个音量采集单位;
	 * 此处用平方和平均值进行计算;
	 *
	 * @param data 输入pcm音频数据
	 * @param bit  位深,8或16
	 * @return 当前分贝值
	 */
	private int calculateVolume(byte[] data, int bit) {
		int[] newBuffer = null;
		int len = data.length;
		int index;

		//排列
		if (bit == 8) {
			newBuffer = new int[len];
			for (index = 0; index < len; ++index) {
				newBuffer[index] = data[index];
			}
		} else if (bit == 16) {
			newBuffer = new int[len / 2];
			for (index = 0; index < len / 2; ++index) {
				byte byteH= data[index * 2];
				byte byteL = data[index * 2 + 1];
				newBuffer[index] = bytesToShort(byteH, byteL);
			}
		}
		//平方和求平均值
		if (newBuffer != null && newBuffer.length != 0) {
			float avg = 0.0F;
			for (int i = 0; i < newBuffer.length; ++i) {
				avg += (float) (newBuffer[i] * newBuffer[i]);
			}
			avg /= (float) newBuffer.length;
			int db = (int) (10.0D * Math.log10(avg + 1));
			return db;
		} else {
			return 0;
		}
	}

	private static short bytesToShort(byte byteH, byte byteL) {
		short temp = 0;
		temp += (byteL & 0xFF);
		temp += (byteH & 0xFF) << 8;
		return temp;
	}

上面这个方法有几点需要明确:

  1. 使用平方和求平均值来计算一段音频数据的分贝值,因为已经平方过,所以公式中的20可以写为20/2=10;如果直接用绝对值和求平均值,那么仍然用20
  2. 使用short值来表示16bit的数据,因为有符号位,那么最大分贝值应该为20*log(32767) ≈ 90
  3. 使用大端模式表示数据,即低地址存高位字节

检测静默的前提是设定一个阈值,如果小于这个阈值,则判定为静默。
具体代码见传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值