java - Android:检查麦克风是否收到声音

标签 java android audio android-studio-2.0

我是Android的新手,并且正在Android Studio上开发听力计。步骤之一是查看麦克风是否正在接收我从耳机发出的声音,以检查它们是否正常工作。

我在同一 Activity 中同时做这两种事情,发送声音,并检查是否有声音传入。

使用AudioTrack类,我能够发送1kHz频率的声音2秒钟,下一步是检查麦克风是否接收到接近该频率的声音。由于我什至无法使麦克风正常工作,因此我降低了目标,只是检查麦克风是否接收到任何东西。

我检查了几个链接,但没有一个对我有帮助,或者是因为我对android不熟悉,或者因为这不是我所需要的,其中包括:
Detect sound levelHow to detect when a user stops talking into the microphoneDetect 'Whistle' sound in android

我已经将权限放在 list 上:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我的CalibrationActivity.java是:

import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack; 
import android.media.MediaRecorder;    
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.io.IOException;

public class CalibrationActivity extends AppCompatActivity {

private MediaRecorder myRecorder;
private String outputFile = null;

private final int duration = 2; // seconds
private final int sampleRate = 4000;
private final int numSamples = duration * sampleRate;
private final double sample[] = new double[numSamples];
private final double freqOfTone = 1000; // hz

private final byte generatedSnd[] = new byte[2 * numSamples];

Handler handler = new Handler();

int getAmplitude = myRecorder.getMaxAmplitude();

public int result(){
    if (getAmplitude != 0) {
        return 1;
    }else {
        return 0;
    }
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_calibration);

    outputFile = Environment.getExternalStorageDirectory().
        getAbsolutePath() + "/teste.3gpp";

    myRecorder = new MediaRecorder();
    myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    myRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    myRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
    myRecorder.setOutputFile(outputFile);


    Intent intent;
    if(result()==1){
        intent = new Intent(this, FirstTestActivity.class);
    }else{
        intent = new Intent(this, End1Activity.class);
    }

}

void start_recording() {
    try {
        myRecorder.prepare();
        myRecorder.start();
    } catch (IllegalStateException e) {
        // start:it is called before prepare()
        // prepare: it is called after start() or before setOutputFormat()
        e.printStackTrace();
    } catch (IOException e) {
        // prepare() fails
        e.printStackTrace();
    }
}

void stop_recording(){

    try {
        myRecorder.stop();
        myRecorder.release();
        myRecorder  = null;
    } catch (IllegalStateException e) {
        //  it is called before start()
        e.printStackTrace();
    } catch (RuntimeException e) {
        // no valid audio/video data has been received
        e.printStackTrace();
    }
}

@Override
protected void onResume() {
    super.onResume();
    // Use a new tread as this can take a while
    final Thread thread = new Thread(new Runnable() {
        public void run() {
            genTone();
            handler.post(new Runnable() {

                public void run() {
                    playSound();

                }
            });
        }
    });
    thread.start();
            start_recording();
            SystemClock.sleep(3000);
            stop_recording();
}


void genTone() {
    // fill out the array
    for (int i = 0; i < numSamples; ++i) {
        sample[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));
    }

    // convert to 16 bit pcm sound array
    // assumes the sample buffer is normalised.
    int idx = 0;
    for (final double dVal : sample) {
        // scale to maximum amplitude
        final short val = (short) ((dVal * 32767));
        // in 16 bit wav PCM, first byte is the low order byte
        generatedSnd[idx++] = (byte) (val & 0x00ff);
        generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

    }
}

void playSound() {
    final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
            sampleRate, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,
            AudioTrack.MODE_STATIC);
    audioTrack.write(generatedSnd, 0, generatedSnd.length);
    audioTrack.play();
  }

  }

我是根据我在网上找到的示例(主要来自hereherehere)编写的,因此我有一些我不太了解的代码。

这里的想法是从耳机发送声音,并且将通知用户将耳机放在靠近麦克风的地方。然后,该代码应让麦克风录制3秒钟,然后检查声音的振幅是否不同于0,如果是,则应用程序转到FirstTestActivity,否则转到End1Activity。但是,一旦我尝试运行代码,应用程序就会突然崩溃,我也不知道为什么。我已经为此工作了几个星期,但我找不到一个可能非常简单的解决方案。提前谢谢。

最佳答案

由于您缺乏对该主题的知识,因此您可能会像使用一个here这样,仅使用一个库可能会很有用。

关于java - Android:检查麦克风是否收到声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37899441/

相关文章:

javascript - 在 onclick 事件中播放音频文件

audio - ffmpeg 音频复制因管道失败

java - Java2d 中的动画图像

java - SharedPreferences 占用过多堆内存

java - 如何设置类名?

android - 如何将 HttpEntity 转换为 JSON?

java - 并发修改异常 : adding to an ArrayList

android - MySQLNonTransientConnectionException : Could not create connection to database server

java - DrawerLayout 后退箭头功能

ios - Swift + AVAudioRecorder 录音很安静