0

我正在尝试为 Android 平台构建某种声音计。(我正在使用 HTC 野火)我使用AudioRecord该类来实现该目标,但似乎从其“读取”返回的值是不合理的。

这就是我创建 AudioRecord 对象的方式:

int minBufferSize = 
         AudioRecord.getMinBufferSize(sampleRateInHz,
                                      android.media.AudioFormat.CHANNEL_IN_MONO,
                                      android.media.AudioFormat.ENCODING_PCM_16BIT);

audioRecored = new AudioRecord( MediaRecorder.AudioSource.MIC,          
                                44100, 
                                android.media.AudioFormat.CHANNEL_IN_MONO,
                                android.media.AudioFormat.ENCODING_PCM_16BIT,
                                minBufferSize );

这就是我尝试从中读取数据的方式:

    short[] audioData = new short[bufferSize];
    int offset =0;
    int shortRead = 0;
    int sampleToReadPerGet = 1000;//some value in order to avoid momentaraly nosies.

    //start tapping into the microphone
    audioRecored.startRecording();

   //start reading from the microphone to an internal buffer - chuck by chunk
   while (offset < sampleToReadPerGet)
   {
            shortRead = audioRecored.read(audioData, offset ,sampleToReadPerGet - offset);
            offset += shortRead;
   }

   //stop tapping into the microphone
   audioRecored.stop();

    //average the buffer
    int averageSoundLevel = 0;
    for (int i = 0 ; i < sampleToReadPerGet ; i++)
    {
        averageSoundLevel += audioData[i];          
    }
    averageSoundLevel /= sampleToReadPerGet;      

这些价值观是什么?它们是分贝吗?

编辑:值从 -200 到 3000。shortRead 的值是 sampleToReadPerGet (1000)。

4

2 回答 2

1

不确定您指的是什么“那些值”,原始输出或平均值,但原始输出是瞬时幅度水平。重要的是要意识到这些值并没有特别引用任何东西。也就是说,仅仅因为你正在阅读 20,并不能告诉你 20 是什么。

取这些值的平均值没有任何意义,因为这些值在零上下波动。做足够长的时间,你就会得到零。

取平方的平均值,然后找到平均值的平方根可能是有意义的。这称为 RMS。但是,如果没有固定的缓冲区大小来平均,这充其量是危险的。

要测量 dB,您必须使用公式 dB = 20 log_10 (|A|/A_r),其中 A 是幅度,A_r 是参考幅度——显然,您必须决定要参考什么(您可以校准 HTC ,或针对最高水平或类似的东西进行测量)。

于 2012-06-17T17:27:10.323 回答
0

你不应该得到负值。这些值跨越 16 位或 8 位,因此您的最大值约为 32000 或其他值。这些值没有单位。

此外,我建议使用均方根而不是平均值来确定交易量。它更稳定。

你应该尝试什么:

  • 将缓冲区大小增加 3:您的应用程序读取它的速度可能不够快,因此您需要一些空间。否则,您可能会遇到一些缓冲区溢出错误(您没有在代码中检查)

  • 试试gast-lib中的代码:它可以帮助您定期录制音频并为您提供 AsyncTask。

  • 均方根:

public static double rootMeanSquared(short[] nums)
{
    double ms = 0;
    for (int i = 0; i < nums.length; i++)
    {
        ms += nums[i] * nums[i];
    }
    ms /= nums.length;
    return Math.sqrt(ms);
}
于 2012-06-18T08:41:29.787 回答