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