我找到了一些计算麦克风声级(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);
}
如何扩展代码以便它可以使用不同的位数?如果我将位数更改为16,则在静音时返回大约50的值,其中8位返回1或2.我还想在图表上绘制声音级别,声级值如何与时间相关?
答案 0 :(得分:2)
采样率并不重要,但位深度,字节序以及不同方式的通道数量都很重要。
要了解原因,您必须注意到有问题的函数将字节数组作为参数,并分别处理该数组中的每个值。字节数据类型是8位值。如果你想要一些适用于16位值的东西,你需要使用不同的数据类型(短)或从字节转换为。
一旦你这样做,你仍然会得到16位与8位不同的值,因为范围不同:8位从-128到+127,16位从-32768到+32767,但它们都是测量相同的东西,意味着他们将相同的真实单词值缩放到不同的表示值。
关于声级和它们与时间的关系......这取决于你的采样率和进入这个函数的数组的大小。例如,如果您的采样率为8kHz,并且每个缓冲区有2048个样本,那么您的函数将被称为8000/2048或大约每秒3.9次,这意味着您的结果将以该速率(每256毫秒)进行。 / p>
答案 1 :(得分:0)
您始终可以将输入缩放到相同的最小 - 最大范围,以获得不同格式的类似结果。
关于声级w.r.t。时间,除了样本之外,没有任何关系以1 / SampleRate(以Hz为单位)秒间相互分开。