如何使用Android Media Recorder获得最大振幅?

时间:2019-01-18 19:48:40

标签: android android-mediarecorder

我从getMaxAmplitude()看过各种各样的帖子,都用方法MediaRecorder解决了问题,但仍然无法解决我的问题。我想用分贝的声音幅度不断更新TextView。我试图通过使用调用此方法的函数每隔1秒钟运行一个处理程序来实现这一目标,但似乎MediaRecorder对象即使在初始化它之后也总是为null(我觉得很奇怪)。顺便说一句,我已经添加了在android中进行音频录制的所有必要权限。我需要在代码中进行哪些更改才能访问getMaxAmplitude()方法?

package com.inversepalindrome.sensorbox;

import com.cardiomood.android.controls.gauge.SpeedometerGauge;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Build;
import android.os.Handler;
import android.content.pm.PackageManager;
import android.widget.TextView;
import android.media.MediaRecorder;
import android.support.v4.app.ActivityCompat;
import android.widget.Toast;

import java.io.IOException;
import java.util.Locale;


public class SoundActivity extends AppCompatActivity {
    private MediaRecorder mediaRecorder;

    private SpeedometerGauge speedometer;

    private TextView soundAmplitudeText;

    private final int AUDIO_REQUEST_CODE = 200;
    private final int AUDIO_RECORDING_DELAY = 1000;
    private final double referenceAmplitude = 0.0001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppTheme);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sound);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.RECORD_AUDIO,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, AUDIO_REQUEST_CODE);
        }

        speedometer = findViewById(R.id.speedometer);

        speedometer.setLabelConverter(new SpeedometerGauge.LabelConverter() {
            @Override
            public String getLabelFor(double progress, double maxProgress) {
                return String.format(Locale.US, "%.1f", progress);
            }
        });
        speedometer.setMaxSpeed(120);
        speedometer.setMajorTickStep(20);
        speedometer.setMinorTicks(1);
        speedometer.setLabelTextSize(32);
        speedometer.addColoredRange(0, 40, Color.GREEN);
        speedometer.addColoredRange(40, 80, Color.YELLOW);
        speedometer.addColoredRange(80, 120, Color.RED);

        soundAmplitudeText = findViewById(R.id.soundAmplitudeValueText);
    }

    @Override
    public void onResume(){
        super.onResume();

        startRecording();
    }

    @Override
    public void onPause(){
        super.onPause();

        stopRecording();
    }

    @Override
    public void onRequestPermissionsResult(final int requestCode, String[] permissions, int[] grantResults) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (requestCode == AUDIO_REQUEST_CODE) {
                startRecording();

                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        final double amplitude = getAmplitude();

                        speedometer.setSpeed(amplitude);
                        soundAmplitudeText.setText(String.format(Locale.US, "%.1f", amplitude));

                        handler.postDelayed(this, AUDIO_RECORDING_DELAY);
                    }
                }, AUDIO_RECORDING_DELAY);
            } else {
                Toast.makeText(this, "No audio recording permissions given!", Toast.LENGTH_LONG).show();
            }
        }
    }

    private void startRecording(){
        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();
                mediaRecorder.start();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void stopRecording(){
        if(mediaRecorder != null) {
            mediaRecorder.stop();
            mediaRecorder.release();
            mediaRecorder = null;
        }
    }

    private double getAmplitude(){
        if(mediaRecorder != null){
            final double maxAmplitude = mediaRecorder.getMaxAmplitude();
            final double amplitude = 20 * Math.log10(maxAmplitude / referenceAmplitude);

            return amplitude;
        }
        else{
            return 0.0;
        }
    }
}

编辑:修复了一些指出的问题后,我的应用崩溃了 带有以下调试消息的getMaxAmplitudeCall:

1501-6480/? E/AudioFlinger: createRecordTrack_l() initCheck failed -12; no control block?
2019-01-18 15:23:54.983 2362-10949/com.google.android.googlequicksearchbox:search E/AudioRecord: AudioFlinger could not create record track, status: -12
2019-01-18 15:23:54.987 2362-10949/com.google.android.googlequicksearchbox:search E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -12.
2019-01-18 15:23:54.987 2362-10949/com.google.android.googlequicksearchbox:search E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.

2 个答案:

答案 0 :(得分:0)

    if(mediaRecorder != null)
    {
        mediaRecorder = new MediaRecorder();

您可以向后检查。所以它永远不会初始化

答案 1 :(得分:0)

答案在我的评论中,但您的问题是您正在呼叫onPause停止录制,停止和释放MediaRecorder。如果您没有录制权限,可能会发生这种情况。当出现询问权限的对话框时,stopRecording被调用,因此您的录音机为空并被释放。

如果您已经具有权限,则不会发生。试试看。

此外,在startRecording方法中,检查您的媒体记录器是否为null。您是否拥有null的其他区别。