2016-02-22 13 views
8

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

Я беру данные от MIC мобильного и используя класс MediaRecorder, используя этот класс, я могу записывать, сохранять и воспроизводить входные данные. Теперь мне нужно, чтобы мой мобильный телефон вибрировал всякий раз, когда раздавался звуковой сигнал или какой-либо звук.

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

У меня есть кнопка, на которой начинается запись. У меня есть разрешения на вибрацию и запись в моем файле манифеста.

record.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       try { 
        isRecording=true; 
        myAudioRecorder.prepare(); 
        myAudioRecorder.start(); 
... 
} 

Я также попытался найти в интернете и нашел вид на подобный вопрос here, но я не могу найти правильный ответ.

Однако, я могу сделать телефон вибрировал по нажатию другой кнопки и вот snipt коды,

Vibrator vibrate; 
    vibrate = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); 

     Btn1.setOnClickListener(new View.OnClickListener() 

           { 
            @Override 
            public void onClick(View v) { 
             vibrate.vibrate(800); 
            } 
           } 

Я попытался назвать вибратор внутри recorder.start(); но это заставляет телефон вибрировать, даже когда звук больше отсутствует. Я также пробовал получить помощь от this question, поэтому всякий раз, когда наступает тишина, телефон не должен вибрировать, но я сбиваюсь с толку, я как-то понимаю, что должно быть логическое значение, которое становится истинным, когда есть звук и заставляют телефон вибрировать, но я я не могу поместить эту логику в код. Пожалуйста, дайте мне знать, что я могу сделать в этом контексте и в каком направлении я должен искать?

UPDATE Я нашел this toturial для показа индикатора с амплитудой входного сигнала, он отлично работает, и я попытался сделать телефон вибрировал, когда существуют некоторое значение в буфере, сейчас она вибрирует даже тогда, когда амплитуда нуль, я думаю, это связано с тем, что каждая вибрация создает шум, который заставляет телефон вибрировать. Я не могу проверить функцию через TOAST из-за java.lang.RuntimeException: Невозможно создать обработчик внутри потока, который не вызвал Looper.prepare(). Есть ли какие-нибудь предложения?

ответ

0

Попробуйте это:

Btn1.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      v.post(new Runnable() { 

       @Override 
       public void run() { 

        vibrate.vibrate(800); 
       } 
      }); 

     } 
    }); 
+0

Благодарим вас за ответ, но мне нужно, чтобы телефон вибрировал, когда есть звук, а не по щелчку, я уже могу это сделать. Пожалуйста, прочитайте вопрос еще раз. –

0

Вы можете попробовать это:

Handler handler; 
    Runnable r; 

      handler = new Handler(); 
       r = new Runnable() { 
        public void run() { 

        Vibrator vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); 
        vib.vibrate(500); 
        handler.postDelayed(r, 1000); 

        } 
       }; 
      handler.post(r); 
+0

Не могли бы вы объяснить код, я новичок в андроиде и не знаком со всеми понятиями. –

6

Для вашей основной проблемой, может быть, вы можете проверить амплитуду звука, и только вибрировать, если минимальный порог имеет была достигнута.Что-то вроде этого:

private class DetectAmplitude extends AsyncTask<Void, Void, Void> { 

    private MediaRecorder mRecorder = null; 
    private final static int MAX_AMPLITUDE = 32768; 
    //TODO: Investigate what is the ideal value for this parameter 
    private final static int MINIMUM_REQUIRED_AVERAGE = 5000; 

    @Override 
    protected Void doInBackground(Void... params) { 
     Boolean soundStarted = true; 
     if (mRecorder == null) { 
      mRecorder = new MediaRecorder(); 
      mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
      mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
      mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
      mRecorder.setOutputFile("/dev/null"); 
      try { 
       mRecorder.prepare(); 
      } catch (IllegalStateException e) { 
       soundStarted = false; 
       Log.e(TAG, "Could not detect background noise. Error preparing recorder: " + e.getMessage()); 
      } catch (IOException e) { 
       soundStarted = false; 
       Log.e(TAG, "Could not detect background noise. Error preparing recorder: " + e.getMessage()); 
      } 
      try { 
       mRecorder.start(); 
      } catch (RuntimeException e) { 
       Log.e(TAG, "Could not detect background noise. Error starting recorder: " + e.getMessage()); 
       soundStarted = false; 
       mRecorder.release(); 
       mRecorder = null; 
      } 
     } 

     if (soundStarted) { 
      // Compute a simple average of the amplitude over one 
      // second 
      int nMeasures = 100; 
      int sumAmpli = 0; 
      mRecorder.getMaxAmplitude(); // First call returns 0 
      int n = 0; 
      for (int i = 0; i < nMeasures; i++) { 
       if (mRecorder != null) { 
        int maxAmpli = mRecorder.getMaxAmplitude(); 
        if (maxAmpli > 0) { 
         sumAmpli += maxAmpli; 
         n++; 
        } 
       } else { 
        return null; 
       } 
       try { 
        Thread.sleep(1000/nMeasures); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
      mRecorder.stop(); 
      mRecorder.release(); 
      mRecorder = null; 

      final float avgAmpli = (float) sumAmpli/n; 

      if (avgAmpli > MINIMUM_REQUIRED_AVERAGE) { 
       //TODO: Vibrate the device here 
      } 
     } 
     return null; 
    } 
} 

Для получения более подробной информации относительно обнаружения уровня звука, пожалуйста, обратитесь к следующему:

Что касается исключения java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(), что происходит потому, что Toast должен запускаться в основном потоке вашего приложения. Если ваш Thread код (как AsyncTask) находится внутри Activity, вы можете попробовать следующее:

runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      //Call your Toast here 
     } 
    }); 

В противном случае, вам нужно каким-то образом передать заключение вашего метода к Activity для того, чтобы запустить Toast.

EDIT:

Если вы хотите использовать это от Button, вы можете установить его OnClickListener на ваш Activity «s onCreate() вызов и выполнить AsyncTask там. Например:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.your_layout); 
    Button button = (Button)findViewById(R.id.your_button_id); 
    button.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      new DetectAmplitude().execute(new Void[]{}); 
     } 
    }); 
} 

Я предлагаю вам взглянуть на how AsyncTask works перед использованием этого в рабочем коде.

+0

Привет, Это звучит здорово, но я не могу найти способ начать запись при нажатии кнопки, предложите ли вы метод onclicklistener внутри AsyncTask, а затем защищенный Void doInBackground (Void ... params внутри? –

+0

Привет @MomoPomo Я отредактировал свой ответ с примером использования. Надеюсь, что это поможет. –

1

Вы хотите пробовать аудио и анализировать его немедленно.

Для этого MediaRecorder обладает высоким уровнем, он захватывает только файл. Вероятно, вы захотите использовать AudioRecorder, поскольку он дает прямой доступ к входным образцам.

Чтобы определить конкретный тон , вы можете использовать Goertzel algorithm на входных образцах. Вот C++ implementation, который я сделал несколько лет назад, что может служить примером.

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

+0

Вы можете использовать 'setOutputFile ("/dev/null ")' в 'MediaRecorder', чтобы избежать выхода файла. Кроме того, для простого определения наличия шума , медиа-рекордер прекрасно справится, проверив амплитуду звука за небольшой промежуток времени. –

+0

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