如何使用Android 媒体记录器获得最大振幅?
How to use Android media recorder to get max amplitude?
我已经看到各种帖子解决了方法 getMaxAmplitude() from 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.
if(mediaRecorder != null)
{
mediaRecorder = new MediaRecorder();
你的支票倒退了。所以它永远不会初始化
答案在我的评论中,但你的问题是你正在调用 onPause 停止录制,停止并释放你的 MediaRecorder。当您没有录制权限时,可能会发生这种情况。当出现请求权限的对话框时,正在调用 stopRecording,因此您的录音机为空并已释放。
如果您已经拥有权限,则不会发生这种情况。试试看。
此外,在 startRecording 方法中检查您的媒体记录器是否为空。你有 if is it different of null。
我已经看到各种帖子解决了方法 getMaxAmplitude() from 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.
if(mediaRecorder != null)
{
mediaRecorder = new MediaRecorder();
你的支票倒退了。所以它永远不会初始化
答案在我的评论中,但你的问题是你正在调用 onPause 停止录制,停止并释放你的 MediaRecorder。当您没有录制权限时,可能会发生这种情况。当出现请求权限的对话框时,正在调用 stopRecording,因此您的录音机为空并已释放。
如果您已经拥有权限,则不会发生这种情况。试试看。
此外,在 startRecording 方法中检查您的媒体记录器是否为空。你有 if is it different of null。