簡體   English   中英

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

[英]How to use Android media recorder to get max amplitude?

我從MediaRecorder看到過各種帖子,都解決了方法getMaxAmplitude()的問題,但仍然無法解決我的問題。 我想用分貝的聲音幅度不斷更新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.
    if(mediaRecorder != null)
    {
        mediaRecorder = new MediaRecorder();

您有向后檢查。 所以它永遠不會初始化

答案在我的評論中,但您的問題是您正在呼叫onPause停止錄制,停止並釋放MediaRecorder。 如果您沒有錄制權限,可能會發生這種情況。 當出現詢問權限的對話框時,stopRecording被調用,因此您的錄音機為空並被釋放。

如果您已經具有權限,則不會發生。 試試看。

另外,在startRecording方法中,檢查您的媒體記錄器是否為null。 您是否擁有null的其他區別。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM