我找到了一些计算麦克风音量(RMS)的代码:
public int calculateRMSLevel(byte[] audioData) {
// audioData might be buffered data read from a data line
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 = sumMeanSquare + Math.pow(audioData[j] - dAvg, 2d);
}
double averageMeanSquare = sumMeanSquare / audioData.length;
return (int) (Math.pow(averageMeanSquare, 0.5d) + 0.5);
}但仅适用于以下音频格式:
private AudioFormat getAudioFormat() {
float sampleRate = 8000.0F;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,
bigEndian);
}如何扩展代码,使其可以与不同的位数一起工作?如果我将bitness更改为16,当静默时,它返回大约50的值,而对于8位,它返回1或2。另外,我想在图形上绘制声级值,声级值与时间有什么关系?
发布于 2012-07-19 04:08:00
采样率并不重要,但位深度、字节顺序以及以不同方式表示的通道数才是重要的。
要了解其中的原因,只需注意所讨论的函数将一个字节数组作为参数,并分别处理该数组中的每个值。byte数据类型是一个8位的值。如果您希望使用16位值,则需要使用不同的数据类型(short)或将其从字节转换为短数据类型。
一旦你这样做了,你仍然会得到16位和8位不同的值,因为范围是不同的:8位从-128到+127,16位从-32768到+32767,但它们都测量相同的东西,这意味着它们将相同的实字值缩放到不同的表示值。
至于声级及其与时间的关系……这取决于你的采样率和进入这个函数的数组的大小。例如,如果您的采样率是8 8kHz,并且每个缓冲区有2048个采样,那么您的函数将被调用8000/2048,或者说大约每秒3.9次,这意味着您的结果将以该速率(每256毫秒)传入。
发布于 2012-07-18 19:47:27
您始终可以将输入缩放到相同的最小-最大范围,以从不同的格式获得相似的结果。
至于音量w.r.t.时间,除了样本之间相差1/SampleRate(以Hz为单位)秒之外,没有任何关系。
https://stackoverflow.com/questions/11540094
复制相似问题