我试图像这样在Android上获取麦克风的振幅水平:
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new RecorderTask(recorder), 0, 1000);
private class RecorderTask extends TimerTask {
private MediaRecorder recorder;
public RecorderTask(MediaRecorder recorder) {
this.recorder = recorder;
}
public void run() {
Log.v("MicInfoService", "amplitude: " + recorder.getMaxAmplitude());
}
}
不幸的是,这总是一直返回0。
看来,要执行此操作,我实际上必须开始记录。正确吗?
如果是这样,我是否需要记录500毫秒,获取振幅,停止记录并重复?
最后,我必须记录到文件吗?我不需要保存此音频文件,自上次调用当前的现场麦克风输入以来,我是否只能获取当前幅度或最高幅度而不进行记录?
感谢您的任何帮助,谢谢。
是的,您必须首先调用recorder.start(),并且一定不要忘记最后也要调用recorder.stop()!
请参见http://code.google.com/p/android-labs/source/browse/trunk/NoiseAlert/src/com/google/android/noisealert/以获取示例应用程序,您可能想看看SoundMeter.java和NoiseAlert.java
Toumal的解决方案有效,但是我无法获得足够高的刷新率来满足我的需求。因此,我最终使用了Toumal链接的SoundMeter.java类,但对其进行了修改,以使用此answer
中的代码这是我使用的代码,它提供了更好的刷新率:
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
public class SoundMeter {
private AudioRecord ar = null;
private int minSize;
public void start() {
minSize= AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
ar = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,minSize);
ar.startRecording();
}
public void stop() {
if (ar != null) {
ar.stop();
}
}
public double getAmplitude() {
short[] buffer = new short[minSize];
ar.read(buffer, 0, minSize);
int max = 0;
for (short s : buffer)
{
if (Math.abs(s) > max)
{
max = Math.abs(s);
}
}
return max;
}
}
使用AudioRecord类代替MediaRecorder
查看此站点:http://www.doepiccoding.com/blog/?p=195,它给出了很好的解释和有效的代码:)
您还可以使用mediaRecoder类,以在UI上显示实时数据,您需要使用Handler:
public class SoundMeter {
private MediaRecorder mediaRecorder;
public void start(){
if(started){
return;
}
if (mediaRecorder == null){
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(
MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(
MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(
MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setOutputFile("/dev/null");
try{
mediaRecorder.prepare();
}catch (IllegalStateException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
mediaRecorder.start();
started = true;
}
}
}
public double getAmplitude(){
return mediaRecorder.getMaxAmplitude();
}
}
此部分显示UI上的数据:
private Runnable pollTask = new Runnable() {
@Override
public void run() {
double amplitude = soundMeter.getAmplitude();
amplitudeTextView.setText("Amplitude: " + amplitude);
handler.postDelayed(pollTask, 500);
}
};
不要忘记在onCreate方法中调用处理程序:
handler.postDelayed(pollTask, 500);
500是将更新UI的延迟(以毫秒为单位)
如您在这里看到的,如果您将输出目标设置为以下内容,则无需将输出保存到文件中:它不会保存在任何地方:
mediaRecorder.setOutputFile("/dev/null");