我是Android的新手,并且正在Android Studio上开发听力计。步骤之一是查看麦克风是否正在接收我从耳机发出的声音,以检查它们是否正常工作。
我在同一 Activity 中同时做这两种事情,发送声音,并检查是否有声音传入。
使用AudioTrack类,我能够发送1kHz频率的声音2秒钟,下一步是检查麦克风是否接收到接近该频率的声音。由于我什至无法使麦克风正常工作,因此我降低了目标,只是检查麦克风是否接收到任何东西。
我检查了几个链接,但没有一个对我有帮助,或者是因为我对android不熟悉,或者因为这不是我所需要的,其中包括:
Detect sound level,How to detect when a user stops talking into the microphone和Detect '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();
}
}
我是根据我在网上找到的示例(主要来自here,here和here)编写的,因此我有一些我不太了解的代码。
这里的想法是从耳机发送声音,并且将通知用户将耳机放在靠近麦克风的地方。然后,该代码应让麦克风录制3秒钟,然后检查声音的振幅是否不同于0,如果是,则应用程序转到FirstTestActivity,否则转到End1Activity。但是,一旦我尝试运行代码,应用程序就会突然崩溃,我也不知道为什么。我已经为此工作了几个星期,但我找不到一个可能非常简单的解决方案。提前谢谢。
最佳答案
由于您缺乏对该主题的知识,因此您可能会像使用一个here这样,仅使用一个库可能会很有用。