miércoles, 11 de abril de 2012

Ecualizador Gráfico y Timer


El siguiente paso que nos propusimos fue realizar el ecualizador gráfico. Estos fueron los objetivos de este paso:
-          - Aprender a dibujar en la pantalla de nuestro programa.
-          - Hacer que apareciese en la pantalla el ecualizador gráfico, que representa lo grabado en tiempo real.
-          - Construir un Timer para poder “refrescar” los valores  del ecualizador gráfico cada 50ms.

Para poder dibujar en la pantalla de nuestra aplicación necesitábamos aprender a usar la clase Canvas, en particular, el método onDraw() de Canvas. Para hacerlo creamos la clase VisualizerView (subclase de la clase View) y implementamos dentro de ésta el método onDraw(Canvas canvas). La implementación de éste método por ahora era muy sencilla, sólo intentamos pintar un cuadrado con el método drawRect(). El “último” paso para ver si habíamos aprendido a pintar un cuadrado en la pantalla, fue ejecutar el método onDraw()en el método onCreate()(el cual se ejecuta al arranque de la aplicación).

Una vez hecho todo esto, nos surgió un problema ya que intentábamos en una misma pantalla tanto poner los botones con la ayuda del eclipse (con el archivo main.xml) como pintar un cuadrado en ésta mediante la programación arriba descrita. Este problema lo que producía era un conflicto de “quien manda sobre la pantalla” y nos mandaba forzar cierre nada más intentar arrancar la aplicación.

Para solucionarlo lo que tuvimos que hacer fue crear toda la interfaz del programa sin usar la ayuda del eclipse, es decir, tuvimos que crear también los botones mediante programación sin ayuda del simulador, definiendo su tamaño, su situación en pantalla… Una vez hecho esto, el problema arriba mencionado fue resuelto.

Ya aparecido el cuadrado en pantalla, aprendimos a configurar diferentes parámetros de dibujo como: color (clase Paint), colocación en una situación específica de la pantalla, largo y ancho de un rectángulo para dibujar nuestras barras del ecualizador…
  
El siguiente paso era aprender a crear el Timer, para que poder refrescar el ecualizador gráfico cada 50ms. Para crear el Timer había que programar un método run() para que pasado el  periodo que hayamos configurado gracias al método Schedule() se ejecute el método run(). En ese método lo único que ejecutaremos fue  el  método updateVisualizer(), que lo único que hace es actualizar el dibujo. Este fue el código:
t = new Timer();
                           scanTask = new TimerTask() {
public void run() {
                                        mVisualizerView.updateVisualizer();
                                                   }
                           };
                           t.schedule(scanTask, 0, 50);

Al ejecutar el programa en este momento nos daba un error y nos obligaba a forzar cierre de nuevo. Buscando el error nos dimos cuenta de que el Timer se ejecutaba en un “hilo” paralelo al propio hilo donde se ejecutaba el resto del programa, y el error se debía a que el hilo propio no permitía que el hilo paralelo del Timer dibujase en “su” pantalla.

Para solucionar este problema vimos que era necesario crear un Handler, junto con un Runnable para que el Timer se ejecute en el hilo principal y así se pudiese actualizar la pantalla mediante éste, quedando el siguiente código:
t = new Timer();
scanTask = new TimerTask() {
public void run() {
             handler.post(new Runnable() {
                    public void run() {
                           mVisualizerView.updateVisualizer();                                     }
             });
      }};
t.schedule(scanTask, 0, 50);

Tras haber conseguido dibujar un cuadrado (y aprender a configurar más parámetros de dibujo) y que funcionase el Timer, probamos ambas funcionalidades dibujando un rectángulo que fuera aumentando cada segundo un pixel de largo, de esta manera comprobamos que funcionaban ambas a la perfección, y el programa estaba listo para “pintar” el ecualizador gráfico.

Empezamos a crear el ecualizador asociado al Timer, y el siguiente problema que nos encontramos fue que no sabíamos como dibujar de abajo hacia arriba ya que al crear un LinearLayout te obliga a empezar el siguiente objeto siempre debajo del anterior tomando como origen de coordenadas la esquina superior izquierda de la pantalla. La solución que propusimos de manera provisional fue crear el ecualizador al revés, para ello creamos ocho rectángulos (barras del ecualizador gráfico) que fueran variando con la energía media por rango de frecuencias.

Al intentar comprobar la funcionalidad de la fft (explicada en el blog anterior) mediante la visualización del ecualizador nos dimos cuenta que la fft no funcionaba bien, ya que después de dos o tres  segundos el valor de las muestras toman valores negativos y de gran valor, por lo tanto la energía daba valores muy grandes y llegaba un momento que las variables se desbordan y daban 0, e incluso los pixeles de la pantalla no soportaban esos valores, por lo que al pasar unos segundos ya no dibuja el ecualizador.

Después de todo esto, los objetivos que nos hemos marcado para la siguiente semana son:
- “Dar la vuelta” al ecualizador gráfico
- Solucionar el problema de la fft.
- Comprobar la funcionalidad de la fft por respuesta del ecualizador gráfico.

No hay comentarios:

Publicar un comentario