2014-12-28 3 views
-1

Я новичок в разработке приложений для Android и пытаюсь разработать приложение на студии Android, которое позволяет глухим людям распознавать громкие звуки выше определенного порога. приложение должно прослушивать среду в режиме реального времени и вибрировать, если звук превышает заданный порог.Вибрация при громких звуках приложения для андроида

Я использовал класс 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

Это исключение, потому что какой-то объект имеет нулевое значение, выяснить с помощью отладчика, что объект является недействительным и попытаться начните решать проблему оттуда. В вашем случае я подозреваю, что вы задаете нулевой массив , это нужно инициализировать до пустого массива длиной buffersize, то есть

byte[] data = new byte[buffersize]; 

Что касается вопроса о получении значений выборки, то, как вы формируете значения выборки (просто добавив их), неправильно, вам нужно сделать что-то похожее на то, что было сделано HERE, чтобы получить значения выборки из байты. Или вы могли бы альтернативно сделать вашу жизнь намного проще, используя read(short[] audioData, int offsetInShorts, int sizeInShorts) вместо метода read(byte[] audioData, int offsetInBytes, int sizeInBytes) и получить образец 16-битных значений без масштабирования непосредственно из объекта AudioRecord, то есть все, что вам нужно будет сделать, это разделить короткие значения на 32768, чтобы получить фактическое значение выборки (которое будет иметь число от -1 до 1).

Я также задаюсь вопросом, как вы собираетесь выполнять сравнение громкости, максимальное значение децибела, которое вы когда-либо получите, равно 0 дБ, поэтому сравнение с 65 дБ приведет к неправильным результатам.

Смежные вопросы