android - 大声震动android应用程序

标签 android audio

我是android应用程序开发的新手,正在尝试在android studio上开发一个应用程序,它为聋人提供了识别高于指定阈值的声音的能力。如果声音高于指定的阈值,则应用程序应实时收听环境并振动。

我已使用AudioRecord类将周围的声音记录到16BIT PCM的缓冲区中,然后将数据读取到array(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)

最佳答案

因为某些对象为空,所以抛出该异常,使用调试器找出什么对象为空,然后尝试从那里开始解决问题。在您的情况下,我怀疑您将data数组设置为null是问题,您应该将其初始化为一个长度为buffersize的空数组,即

byte[] data = new byte[buffersize];

关于获取样本值的问题,形成样本值的方式是错误的,您必须做类似于HERE的操作才能从字节中获取样本值。或者,通过使用read(short[] audioData, int offsetInShorts, int sizeInShorts)而不是read(byte[] audioData, int offsetInBytes, int sizeInBytes)方法使您的生活变得更简单,并直接从AudioRecord对象接收16Bit采样样本未缩放的采样值,这意味着您需要做的就是将短值除以32768以得到实际采样值(是介于-1和1之间的数字)。

我还想知道您打算如何进行响度比较,您将获得的最大分贝值为0db,因此与65db进行比较会导致错误的结果。

关于android - 大声震动android应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27676418/

相关文章:

java - 如果当前浏览器 url 包含单词,则执行某些操作

android - 应用 RadioButton 样式不工作 Android

android - 哪个 Intent 应该打开数据使用屏幕(来自设置)

ios - AVAudioRecorder消除低声音

android - 带 Sqlite 的 Android 空间数据库

android - 当两个依赖项使用FFmpeg时如何解决不满意的链接错误

ios - 同时播放多个音频流

excel-2007 - 在工作簿之间切换时,ms excel 中出现烦人的哔哔声

jquery - 我应该为 HTML 嵌入选择哪种音频格式和哪种压缩?

java - TargetDataLine.getFramePosition()vs read()