1

我找到了一些代码来计算麦克风声级(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。我还想在图表上绘制声级,声级值与时间有何关系?

4

2 回答 2

2

采样率无关紧要,但位深、字节序以及通道数很重要。

要了解原因,您必须简单地注意到所讨论的函数将字节数组作为参数并单独处理该数组中的每个值。字节数据类型是一个 8 位值。如果您想要使用 16 位值的东西,您需要使用不同的数据类型(短)或从字节转换为。

一旦你这样做了,你仍然会得到 16 位和 8 位的不同值,因为范围不同:8 位从 -128 到 +127,16 位从 -32768 到 +32767,但它们的测量值相同事物,这意味着它们将相同的实际值缩放为不同的表示值。

至于声级及其与时间的关系......这取决于你的采样率和进入这个函数的数组的大小。例如,如果您的采样率为 8kHz,并且每个缓冲区有 2048 个样本,那么您的函数将被称为 8000/2048 或大约每秒 3.9 次,这意味着您的结果将以该速率(每 256 毫秒)出现。

于 2012-07-18T20:08:00.423 回答
0

您始终可以将输入缩放到相同的最小-最大范围,以从不同格式获得相似的结果。

至于声级 wrt 时间,除了样本彼此分开 1/SampleRate(in Hz) 秒之外没有任何关系。

于 2012-07-18T11:47:27.077 回答