Android:检测声音级别

36

使用 MediaRecorder 我从设备的麦克风捕获声音。我只需要分析声音的音量(声音响度),而不将声音保存到文件中。

两个问题:

  1. 如何在给定时刻获取声音的响度?
  2. 如何在不保存声音到文件的情况下进行分析?

谢谢。

3个回答

53
  1. 使用mRecorder.getMaxAmplitude();

  2. 如果只需要分析声音而不保存,你只需使用mRecorder.setOutputFile("/dev/null");

以下是一个例子,希望对您有所帮助。

public class SoundMeter {

    private MediaRecorder mRecorder = null;

    public void start() {
            if (mRecorder == null) {
                    mRecorder = new MediaRecorder();
                    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    mRecorder.setOutputFile("/dev/null"); 
                    mRecorder.prepare();
                    mRecorder.start();
            }
    }

    public void stop() {
            if (mRecorder != null) {
                    mRecorder.stop();       
                    mRecorder.release();
                    mRecorder = null;
            }
    }

    public double getAmplitude() {
            if (mRecorder != null)
                    return  mRecorder.getMaxAmplitude();
            else
                    return 0;

    }
}

1
我喜欢 /dev/null,但我不明白如何每秒获取几次 MaxAmplitude。 - Zelter Ady
1
我需要连续记录声音水平(每秒100次)。记录的声音水平(响度)应该是从我录制的那一刻开始。 - Zelter Ady
1
我解决了。在Android开发网站上,getMaxAmplitude()返回的最大绝对幅度被解释为:<b>自上次调用以来测量到的最大绝对幅度,或者在第一次调用时返回0</b>,为了获取任何秒钟的值,我使用了一个计时器。 - Zelter Ady
1
谢谢Anna。你知道有关使用AudioRecorder和声音分析的教程吗?我在这个领域找不到更多好的信息 - 或者我不擅长选择信息来源。 - Zelter Ady
1
Ana Llera,getAmplitude() 返回 int。MB 最好使用 int getAmplitude() 吗? - Fortran
显示剩余3条评论

9
如果您想直接从麦克风获取声音样本并在不保存数据到文件的情况下进行分析,则需要使用AudioRecord对象,操作如下:
int sampleRate = 8000;
try {
    bufferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO,
        AudioFormat.ENCODING_PCM_16BIT);
    audio = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT, bufferSize);
} catch (Exception e) {
    android.util.Log.e("TrackingFlow", "Exception", e);
}

接着,当您准备好时,您需要开始录制:

audio.startRecording();

现在是时候开始阅读以下示例了:
short[] buffer = new short[bufferSize];

    int bufferReadResult = 1;

    if (audio != null) {

        // Sense the voice...
        bufferReadResult = audio.read(buffer, 0, bufferSize);
        double sumLevel = 0;
        for (int i = 0; i < bufferReadResult; i++) {
            sumLevel += buffer[i];
        }
        lastLevel = Math.abs((sumLevel / bufferReadResult));

最后一段代码将所有不同样本的振幅组合起来,将平均值分配给lastLeveL变量。如需详细信息,请访问此文章
问候!

4
这个算法有问题 - 你不能像那样简单地加起来,因为这些是有符号的值。你必须取它们的大小并计算平均值。 - Chris Stratton
@Martin:“lastLevel”指的是最大振幅吗?实际上,我需要计算“dbValue”和“MeanLevelTotal”的值,并且我没有使用预录文件。我正在处理现场录音。 - Mitesh Shah

4
我尝试了几个声音录制源代码应用程序,但花了一些时间才搞定。
你可以复制Google的NoiseAlert源代码 - SoundMeter代码,这就是我使用的代码。
getMaxAmplitude范围从0到32768。 EMA的东西我没用过。
在你的主活动中,你必须声明一个MediaRecorder对象并调用它的start()函数,如Anna所引用的那样。
有关更多信息,您可以参考我的项目: http://kaitagsd.wordpress.com/2013/03/25/arduino-project-amplify-part-2-i-e-how-to-transmit-send-data-from-android-to-arduino-bluesmirf-silver-using-bluetooth/ 在那里我需要通过蓝牙发送声音幅度的值。

代码在这里:https://github.com/garytse89/Amplify/tree/master/Android%20Code/src/com/garytse89/allin

只需浏览与相关的MediaRecorder对象有关的部分即可。


据WordPress称,网页http://kaitagsd.wordpress.com/2013/03/25/arduino-project-amplify-part-2-i-e-how-to-transmit-send-data-from-android-to-arduino-bluesmirf-silver-using-bluetooth已经“不再可用”。 - CODE-REaD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接