web-dev-qa-db-ja.com

Androidでマイクをサンプリングして、ライブの振幅/レベルを取得するための録音を行わない方法は?

私は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を返すだけです。

これが機能するには、実際に録音を開始する必要があるようです。あれは正しいですか?

もしそうなら、500ms記録し、振幅を取得し、記録を停止して繰り返す必要がありますか?

最後に、ファイルに記録する必要がありますか?このオーディオファイルを保存する必要はありません。録音せずに現在のライブマイク入力を最後に呼び出してから現在の振幅または最高の振幅を取得できませんか?

助けてくれてありがとう、ありがとう。

19
Tom

うん、あなたは最初にrecorder.start()を呼び出さなければならない、そして最後にrecorder.stop()を呼び出すことも忘れてはならない!

アプリケーションの例については、 http://code.google.com/p/Android-labs/source/browse/trunk/NoiseAlert/src/com/google/Android/noisealert/ を参照してください。 SoundMeter.JavaとNoiseAlert.Javaを見てみましょう

6
Toumal

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;
    }

}
14
Benjamin Kaiser

MediaRecorderの代わりにAudioRecordクラスを使用します

このサイトをチェックしてください: http://www.doepiccoding.com/blog/?p=195 、それは素晴らしい説明と実用的なコードを提供します:)

2
H. Bharatvaj

MediaRecoderクラスを使用して、ハンドラーを使用する必要があるUIにリアルタイムデータを表示することもできます。

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");
0
Mohammad Moradi