我是Android应用程序开发的新手,我正在尝试在android studio上开发一个应用程序,它为聋人提供识别超过指定阈值的大声音的能力。如果声音高于指定的阈值,应用程序应实时监听环境并振动。
我已经使用AudioRecord类将周围的声音录制到16BIT PCM的缓冲区中,然后将数据读入数组(Byte [])。我不确定如何将16BIT,2字节,样本转换为十进制值,以便我可以将其与阈值进行比较。我也遇到了运行时错误,并在互联网上搜索了答案,但找不到任何答案。
这是我的MainActivity:
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Vibrator;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button vib = (Button) findViewById(R.id.button);
LoudSoundDetector action = new LoudSoundDetector();
vib.setOnClickListener(action);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class MyVibrator {
public Vibrator vibrator;
public void vibrate1() {
Toast.makeText(getBaseContext(), "Vibration test", Toast.LENGTH_LONG).show();
long pattern[] = {0,100,200,300,400};
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(pattern,0);
}
}
public class LoudSoundDetector implements View.OnClickListener{
private int amplitudeThreshold = 65;
int checkThreshold(){
return amplitudeThreshold;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Listener lsn = new Listener();
try {
lsn.listen();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Listener{
int audioSource = MediaRecorder.AudioSource.MIC;
int samplingRate = 44100; /* in Hz*/
@SuppressWarnings("deprecation")
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channelConfig, audioFormat);
boolean isRecording = false;
public void listen() throws IOException{
AudioRecord recorder = new AudioRecord(audioSource, samplingRate, channelConfig, audioFormat, bufferSize);
recorder.startRecording();
isRecording = true;
//capture data and compare threshold
int readBytes=0;
do{
byte[] data = null;
readBytes = recorder.read(data, 0, bufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != readBytes){
int sampleVal = 0;
for(int i=0;i<data.length; i+=2)
sampleVal = data[i] + data[i+1];
float db = (float) (20 * Math.log10(Math.abs(sampleVal)/32768));
LoudSoundDetector lsd = new LoudSoundDetector();
if(db>=lsd.checkThreshold()){
MyVibrator mVib = new MyVibrator();
mVib.vibrate1();
}
}
}while(isRecording);
}
}
}
和日志猫:
12-28 14:23:51.192 12962-12962/com.rayan.graduationtest E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.rayan.graduationtest.MainActivity$Listener.listen(MainActivity.java:122)
at com.rayan.graduationtest.MainActivity$LoudSoundDetector.onClick(MainActivity.java:80)
at android.view.View.performClick(View.java:4432)
at android.view.View$PerformClick.run(View.java:18339)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5283)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:0)
抛出异常是因为某个对象为null,找出使用调试器的对象是null并尝试从那里开始解决问题。在你的情况下我怀疑你设置data
数组null是问题,你应该把它初始化为一个长度为buffersize
的空数组,即
byte[] data = new byte[buffersize];
关于获取样本值的问题,您构建样本值的方式(仅通过添加它们)是错误的,您必须执行与已完成的HERE类似的操作来获取样本来自bytes.Or你可以使用read(short[] audioData, int offsetInShorts, int sizeInShorts)
而不是read(byte[] audioData, int offsetInBytes, int sizeInBytes)
方法让你的生活更简单,并直接从AudioRecord对象接收样本16Bit未缩放的样本值,这意味着你需要做的就是将短值除以32768以得到实际样本值(这将是介于-1和1之间的数字)。
我也想知道你打算如何进行响度比较,你得到的最大分贝值是0db,所以与65db相比会导致错误的结果。