AudioRecord读取返回奇怪的值

时间:2012-06-16 14:40:39

标签: android audio android-sensors android-audiorecord

我正在尝试为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)。

2 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分: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);
}