java数字音频最强教程之如何检测一段音频中是否有声音

7 篇文章 7 订阅
7 篇文章 0 订阅

声音检测

随着人工智能的发展,机器视觉,机器可视化也变的越来越完善,但是声音这块分析资料却比较少,有时候需要去检测一段视频或者音频中是否有声音。在某些场景中需要判断有声音则抓拍录制,当然这里只是先初步检测声音响度,如果还需要更高深的检测比如有人说话,也有其他嘈杂声音,我们如何去区分是人在说话,还是车开过,还是噪音,这个以后再讲。

可用于流媒体视频中实时检测,也可以用于离线文件检测,根据自己的需求,调节soundThreshold阈值,一般情况-65 db 为安静状态。

演示:
在这里插入图片描述

话不多说,直接上代码:

package com.zj.example;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import com.zj.filter.DetectSoundFilter;

/**
 * 识别音频中是否有声音
 * @author ZJ
 *
 */
public class TestDetectQuiet {

	public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
		
		loadFile("./data/安静.wav");
//		loadFile("./data/有声.wav");
		
	}
	
	/**
	 * 读取文件
	 */
	public static void loadFile(String path) throws UnsupportedAudioFileException, IOException {
		File f = new File(path);
		AudioInputStream audioStream = AudioSystem.getAudioInputStream(f);
		
		readData(audioStream);
	}
	
	/**
	 * 读取数据
	 * @throws IOException 
	 */
	public static void readData(AudioInputStream audioStream) throws IOException {
		byte[] frame = new byte[2048];
		
		DetectSoundFilter soundFilter = new DetectSoundFilter();
		
		while (true) {
			int read = audioStream.read(frame);
			if (read < 0) {
				break;
			}
			
			double[] byteToDouble = byteToDouble(frame);
			boolean silence = soundFilter.isSilence(byteToDouble);
			if(silence) {
				System.out.println("这是安静的");
			} else {
				System.out.println("这是有声音的");
			}
		}
	}
	
	/**
	 * pcm转成浮点
	 * @param data
	 * @return
	 */
	public static double[] byteToDouble(byte[] data) {
		ByteBuffer buf = ByteBuffer.wrap(data);

		buf.order(ByteOrder.BIG_ENDIAN);
		int i = 0;
		double[] dData = new double[data.length / 2];

		while (buf.remaining() > 1) {
			short s = buf.getShort();

			dData[i] = (double) s / 32767.0; // real
			++i;
		}
		return dData;
	}
	
}

检测声音核心部分:

package com.zj.filter;

/**
 * 识别声音过滤器
 * 用于判断有没有声音,甚至可以判断声音的响度
 * 
 * @author ZJ
 *
 */
public class DetectSoundFilter {
	
	/**
	 * 声音响度阈值
	 */
	public double soundThreshold = -60; // db
	
	/**
	 * 是否安静
	 * @param buffer
	 * @param soundThreshold
	 * @return
	 */
	public boolean isSilence(final double[] buffer) {
		double currentSPL = soundPressureLevel(buffer);
		System.out.println(currentSPL);
		return currentSPL < soundThreshold;
	}

	/**
	 * 声压计算
	 * @param buffer
	 * @return
	 */
	private double soundPressureLevel(final double[] buffer) {
		double value = Math.pow(localEnergy(buffer), 0.5);
		value = value / buffer.length;
		return linearToDecibel(value);
	}

	/**
	 * 线性转换为dB值
	 * @param value
	 * @return
	 */
	private double linearToDecibel(final double value) {
		return 20.0 * Math.log10(value);
	}

	/**
	 * 音频帧去负数
	 * @param buffer
	 * @return
	 */
	private double localEnergy(final double[] buffer) {
		double power = 0.0D;
		for (double element : buffer) {
			power += element * element;
		}
		return power;
	}
}

demo里只是来检测某一帧,实际应用中可能需求不一样,可以自行修改,比如一段时间内都是安静的话,否则不认为是安静。

gitee地址

至此简单的声音响度识别功能实现了。

java数字音频最强教程

如果觉得可以,请随手点赞,Thanks♪(・ω・)ノ

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值