¿Cómo activar la vibración en la entrada de sonido?

Estoy tratando de crear una aplicación de Android en la que filtrar una frecuencia específica de un pitido y hacer que el teléfono vibre.

Estoy tomando la entrada de la MIC del móvil y usando la clase MediaRecorder, utilizando esta clase, puedo grabar, guardar y reproducir la entrada. Ahora necesito mi móvil para vibrar siempre que haya un pitido / o cualquier sonido.

La entrada es dada por un cable a la toma de auriculares del móvil, así que sé que sólo hay una frecuencia de entrada.

Tengo un botón, haciendo clic en que comienza a grabar. Tengo Permisos para vibrar y grabar en mi archivo de manifiesto ya.

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

También traté de buscar en Internet y encontró una especie de pregunta similar aquí, pero no puedo encontrar ninguna respuesta correcta.

Sin embargo, puedo hacer que el teléfono vibre al hacer clic en otro botón y aquí está el snipt de código,

  Vibrator vibrate; vibrate = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); Btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { vibrate.vibrate(800); } } 

Intenté llamar a un vibrador dentro de graber.start (); Pero esto hace que el teléfono vibre incluso cuando ya no hay sonido. También traté de obtener ayuda de esta pregunta, así que cada vez que hay silencio, el teléfono no debe vibrar, pero me estoy confundiendo, de alguna manera entiendo que debe haber un booleano que se hace realidad cuando hay sonido y hacer que el teléfono vibre, pero yo Soy incapaz de poner esta lógica en código. Por favor, hágamelo saber qué puedo hacer en este contexto y en qué dirección debo buscar?

UPDATE Encontré este toturial para mostrar la barra de progreso con amplitud de sonido de entrada, funciona bien y he intentado hacer que el teléfono vibre cuando hay algún valor en el búfer, Ahora vibra incluso cuando la amplitud es cero, supongo que es debido a El hecho de que cada vibración hace ruido que lleva al teléfono a vibrar. No puedo comprobar la función a través de TOAST debido a java.lang.RuntimeException: No se puede crear el controlador dentro de subproceso que no ha llamado Looper.prepare () . ¿Hay alguna sugerencia?

Para su problema principal, tal vez pueda comprobar la amplitud del sonido, y sólo vibrar si se ha alcanzado un umbral mínimo. Algo como esto:

 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; } } 

Para obtener más información sobre la detección del nivel de sonido, consulte lo siguiente:

  • Android: detectar el nivel de sonido
  • ¿Qué me da la función getMaxAmplitude () de Android para el MediaRecorder?

Respecto a la excepción java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() , eso está sucediendo porque el Toast necesita ejecutarse en el subproceso principal de la aplicación. Si su código de Thread (como un AsyncTask ) está dentro de una Activity , puede intentar lo siguiente:

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

De lo contrario, necesita pasar de alguna manera la conclusión de su método a la Activity para que ejecute el Toast .

EDITAR:

Si desea usar esto desde un Button , puede configurar su OnClickListener en la llamada onCreate() su Activity y ejecutar allí el AsyncTask . Por ejemplo:

 @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[]{}); } }); } 

Le sugiero que eche un vistazo a cómo AsyncTask funciona antes de usar esto en el código de producción.

Desea probar el audio y analizarlo inmediatamente.

MediaRecorder parece de alto nivel para esto, sólo captura a archivo. Es probable que desee utilizar AudioRecorder en su lugar, ya que da acceso directo a las muestras de entrada.

Para detectar un tono específico , puede utilizar el algoritmo Goertzel en las muestras de entrada. Aquí está una implementación de C ++ que hice hace años que podría servir como un ejemplo.

Con el fin de detectar cualquier sonido sobre un determinado umbral , puede utilizar Root Mean Square análisis en las muestras de entrada y hacer que se dispare una vez que la sonoridad llega a su umbral. Aquí hay un ejemplo de Python que reacciona a los ruidos fuertes de un micrófono.

Prueba esto:

 Btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.post(new Runnable() { @Override public void run() { vibrate.vibrate(800); } }); } }); 

Puede probar esto:

  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); 
  • Patrón de vibración para entradas incorrectas (Android)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.