lunes, 2 de septiembre de 2013

Tutorial Mostrar las ondas de audio des de el micrófono en RAW FFT en streaming en Android

Buenos días!
Hoy os traigo un tutorial que me a costado bastante que funcionase ya que es algo complejo pero el resultado es fantástico! Se trata de dibujar en un canvas las ondas de sonido que recibe el micrófono de nuestro terminal Android.
Los usos que se le pueden dar son muchos. Aquí solo mostraremos como hacerlo funcionar, la forma de utilizarlo dependerá de cada uno de vosotros. Para empezar necesitaremos descargar unas classes de Java (que no recuerdo de donde las descargué así que las subo a Mega) para descargar las clases hacer click en el link:




Al descargaros el .zip tendréis que meter la carpeta dentro de vuestro proyecto en eclipse, os debería quedar así:

Una vez tengamos esto abrá que añadir los permisos necessarios al Manifest en este caso solo se necesitará el de grabar por micrófono:
<uses-permission android:name="android.permission.RECORD_AUDIO">
Perfecto, primero mostraremos el Layout que será simplemente de un ImageView que ocupará toda la pantalla:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/ic_launcher" />

</RelativeLayout>
Perfecto a continuación os muestro el código Java totalmente comentado:
protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
      //Creamos espacio en memoria para la clase FFT
     transformer = new RealDoubleFFT(blockSize);
     //Creamos el Bitmap para dibujar
     //Recordar que los dos primero int són el tamaño
     bitmap = Bitmap.createBitmap(256, 450, Bitmap.Config.ARGB_8888); 
     //Lo añadimos al canvas
     canvas = new Canvas(bitmap);
     //Nuestro image view
     imageView = (ImageView) findViewById(R.id.imageView1); 
     //Pintaremos de verde
     paint = new Paint();
     paint.setColor(Color.GREEN);
     imageView.setImageBitmap(bitmap); 
     //Ejecutamos microfono en segundo plano
     new  RecordAudio().execute();
}
   
    private class RecordAudio extends AsyncTask<Void, double[], Void> {
        @Override
        protected void onPreExecute() { }
 @Override
        protected Void doInBackground(Void... params) {
  //Creamos el buffer
                int bufferSize = AudioRecord.getMinBufferSize(frequency,
                        channelConfiguration, audioEncoding);
                //Configurarmos el microfono
                AudioRecord audioRecord = new AudioRecord(
                        MediaRecorder.AudioSource.MIC, frequency,
                        channelConfiguration, audioEncoding, bufferSize);
                //Array de buffer
                short[] buffer = new short[blockSize];
                double[] toTransform = new double[blockSize];
                //Encendemos el microfono
                audioRecord.startRecording();
                //Bucle infinito (para este tutorial)
                while (true) {
                     //vamos recogiendo los resultados
                     int bufferResult = audioRecord.read(buffer, 0, blockSize);
                     for (int i = 0; i < bufferResult; i++) {
                          //Adaptamos los resultados a nuestro array
                          toTransform[i] = (double) buffer[i] / Short.MAX_VALUE;
                     }
                     //Le pasamos los resultados a la clase
                     transformer.ft(toTransform);
                     //Actualizaoms la gráfica
                     publishProgress(toTransform);
                 }
        }
    
        @Override
        protected void onProgressUpdate(double[]... values) {
              super.onProgressUpdate(values);
              //Pintamos el fondo de negro
              canvas.drawColor(Color.BLACK);
              //Recogemos cada valor del array 
              for (int i = 0; i < values[0].length; i++) {
                   int x=i; 
                   int downy=(int)(100-(values[0][i])*10);
                   int upy=100; 
                   //Pintamos todos los valores recogidos en nuestrocanvas
                   canvas.drawLine(x, downy, x, upy, paint);
               } 
                   //Imprimimos
                   imageView.invalidate(); 
                }
        } 
Para descargar el proyecto completo en eclipse hacer click al siguiente enlace:


Espero que os haya gustado este tutorial ya que es difícil de encontrar.

Espero vuestro comentarios!! +1

3 comentarios:

  1. Muy buena entrada!!! lo necesitaba para proyecto de reconocimiento de voz con pocketsphinx !!!

    ResponderEliminar