Java中的麦克风级别
我正试图通过Java访问麦克风的级别。 我不需要录制任何东西,我只想知道声级的相对比例。
这可能是实时的吗?
如果这是不可能的,也许这可行:当电平超过某个值时开始录制,当电平下降到一定水平一段时间后停止录制四分之一秒的位并读取它的音量,如果它低于阈值停止录音。
提前致谢
您可以通过Sound API访问麦克风,但它不会给您一个简单的响度级别。 您只需要捕获数据并自行决定它的大小。
http://download.oracle.com/javase/tutorial/sound/capturing.html
录制意味着保存数据,但是在这里您可以在完成确定其响度后丢弃数据。
均方根法是计算一部分波数据幅度的好方法。
在回答你的评论时,是的,你会捕获一小段数据(可能只有几毫秒),并计算出它的幅度。 根据您需要更新的频率,定期重复此操作。 如果你想跟踪以前的响度并进行比较,那取决于你 – 在这一点上它只是比较数字。 您可以使用最近响度的平均值来计算房间的环境响度,这样您就可以检测到噪声的突然增加。
我不知道打开和关闭音频捕获有多少开销,但你可能最好不要一直打开TargetDataLine
,只需在需要时计算响度。 虽然该行是打开的,但您确实需要继续调用read(),否则应用程序将等待您读取数据。
关于此的相当不错的文章。 帮了我很多忙。
据我所知,这使用@ Nick的回答中谈到的均方根
基本上:
public int calculateRMSLevel(byte[] audioData) { long lSum = 0; for(int i=0; i < audioData.length; i++) lSum = lSum + audioData[i]; double dAvg = lSum / audioData.length; double sumMeanSquare = 0d; for(int j=0; j < audioData.length; j++) sumMeanSquare += Math.pow(audioData[j] - dAvg, 2d); double averageMeanSquare = sumMeanSquare / audioData.length; return (int)(Math.pow(averageMeanSquare,0.5d) + 0.5); }
和用法:
int level = 0; byte tempBuffer[] = new byte[6000]; stopCapture = false; try { while (!stopCapture) { if (targetRecordLine.read(tempBuffer, 0, tempBuffer.length) > 0) { level = calculateRMSLevel(tempBuffer); } } targetRecordLine.close(); } catch (Exception e) { System.out.println(e); System.exit(0); }