plataforma de efectos de guitarra controlada mediante dispositivo
TRANSCRIPT
PLATAFORMA DE EFECTOS DE GUITARRA CONTROLADA MEDIANTE DISPOSITIVO ANDROID
Proyecto Final de Grado
Daniel Muñoz Puerta y Carlos Romero Fernández Junio 2015
RESUMEN
El proyecto que se describe en esta memoria tiene como objetivo la creación de una
plataforma de efectos de guitarra para ordenador que puede ser controlada mediante un dispositivo Android.
Para la manipulación del programa de ordenador mediante un terminal Android se usará la red Wifi para enviar la información al programa de ordenador. Ambos dispositivos deberán estar
conectados en la misma red Wifi para comunicarse.
La programación de ambas aplicaciones se ha basado en lenguaje Java, en el caso de Android se han usado las librerías que nos ofrece el propio sistema operativo. Para el procesado de audio se realizará mediante una librería open-‐source llamada The Beads Project que nos
permitirá realizar los efectos de audio requeridos.
Desarrollador plataforma PC: Daniel Muñoz Puerta Desarrollador plataforma Android: Carlos Romero Fernández
Director: Ignasi Esquerra
Índice 1 Introducción ........................................................................................................................... 4
1.1 Motivación ................................................................................................................... 4
1.2 Objetivos ...................................................................................................................... 4
1.3 Agradecimientos .......................................................................................................... 5
2 Estado del arte ....................................................................................................................... 6
2.1 Estado del arte: Conjunto móvil – ordenador ................................................................. 6
2.2 Estado del arte: Dispositivo móvil ................................................................................. 10
2.3 Estado del arte: Programa PC ........................................................................................ 16
3 Tecnologías utilizadas ........................................................................................................... 20
3.1 Tecnologías utilizadas: Conjunto móvil – ordenador .................................................... 20
3.2 Tecnologías utilizadas: Dispositivo móvil ...................................................................... 21
3.3 Tecnologías utilizadas: Programa PC ............................................................................. 24
4 Implementación del proyecto .............................................................................................. 28
4.1 Planificación del proyecto ............................................................................................. 28
4.2 Implementación de la aplicación móvil ......................................................................... 29
4.3 Implementación de la aplicación de PC ......................................................................... 62
4.4 Comunicación entre dispositivos .................................................................................. 89
5 Conclusiones ........................................................................................................................ 91
5.1 Mejoras ......................................................................................................................... 91
6 Bibliografía y referencias ...................................................................................................... 92
7 Anexos .................................................................................................................................. 95
4
1 Introducción Hoy en día gracias a la introducción del mundo digital, hemos visto una evolución en los campos de procesado audiovisual, cada vez es más frecuente el uso de dispositivos, plataformas o aplicaciones que realizan este tipo de procesado.
Para el ámbito musical este cambio no ha sido una excepción, con el paso de los años se han ido introduciendo nuevas técnicas y mejoras que han permitido a usuarios cotidianos tener acceso a herramientas anteriormente inalcanzables para ellos.
El presente proyecto pretende aprovechar esta continua evolución para crear un sistema de procesado de audio orientado especialmente a guitarra eléctrica. Se persigue dar un paso más allá integrando dos dispositivos de uso cotidiano, como son los dispositivos móviles y los ordenadores, para implementar una aplicación que cumpla los requisitos.
1.1 Motivación La principal motivación de este proyecto es la de añadir una funcionalidad o mejora a un tipo de aplicaciones ya existentes, cubriendo así lo que consideramos un punto débil común en este tipo de sistemas.
Existen diversos sistemas o aplicaciones comerciales que realizan procesado de efectos de audio. Si nos centramos los procesadores de efectos de tipo software orientados a ordenador, nos encontramos con una de las primeras limitaciones que pretende solventar este proyecto, la comodidad. Es frecuente ver a los guitarristas cambiar repetidas veces los parámetros de su cadena de efectos, alterando el sonido que produce su instrumento.
En el caso estar utilizando una plataforma de efectos para ordenador, el hecho de cambiar o manipular algún valor de la cadena de efectos puede llegar a ser molesto (acercarse al ordenador, manipular el ratón…).
La propuesta de los fabricantes para solucionar este problema consiste en unos dispositivos en formato de pedal que nos permitirán modificar la cadena de efectos, y a su vez, el sonido producido. El problema de esta solución es que se trata de unos aparatos muy limitados y con un precio de venta elevado.
Este proyecto pretende ofrecer otra solución al mismo problema aprovechando un recurso tan accesible actualmente, como puede ser el teléfono móvil.
1.2 Objetivos El presente proyecto tiene como propósito principal implementar una solución para solventar el problema planteado anteriormente. Por un lado se pretende desarrollar una aplicación de tipo software que nos permita aplicar efectos a una señal, en este caso la de una guitarra eléctrica. Además, con la intención de facilitar el control de dicha aplicación se desarrollará una aplicación para dispositivos móviles con sistema operativo Android.
Ambas aplicaciones deberán conectarse entre sí utilizando para ello un protocolo de comunicación wireless.
5
La aplicación de PC debe ser capaz de procesar los efectos en tiempo real, y a la vez, poder recibir las ordenes enviadas por el dispositivo móvil. Además, debe de funcionar de forma independientemente, en el caso que no se requiera del uso del dispositivo móvil.
Ambas aplicaciones deben disponer de una interfaz gráfica user-‐friendly, es decir, con controles o vistas intuitivas y que no requieran de conocimientos previos para hacer uso de ellas.
Finalmente, se desea desarrollar un sistema de importación y exportación de presets en ambas aplicaciones con la finalidad de que los usuarios puedan compartir sus configuraciones con otros usuarios de la aplicación.
1.3 Agradecimientos Agradecer a todas las personas que nos han ayudado a realizar este proyecto tanto directamente como indirectamente.
A nuestro director, Ignasi Esquerra, por dejarnos libertad a la hora de realizar nuestro proyecto y apoyándonos a su vez.
6
2 Estado del arte En este apartado analizaremos y razonaremos las diferentes características (tecnologías, técnicas…) escogidas y que se utilizan en el proyecto implementado. Además mostraremos alternativas a las opciones elegidas y las compararemos entre ellas para mostrar sus ventajas e inconvenientes frente a los objetivos presentados al inicio de este proyecto.
Al ser un proyecto formado por dos partes (móvil y ordenador) se separarán en apartados para profundizar más para cada dispositivo, aun así hay aspectos del proyecto que aparecen en ambos lados y se razonarán desde el punto de vista conjunto.
2.1 Estado del arte: Conjunto móvil – ordenador En los apartados posteriores se razonarán las distintas características que se engloban y utilizan en el conjunto de los dos dispositivos (móvil y ordenador).
2.1.1 Entorno de desarrollo / Software de desarrollo Se buscaron diferentes opciones de software tanto para la creación y desarrollo de la aplicación en Android como la aplicación para PC, basadas en distintos lenguajes de programación (Java, C++/C#, Javascript). Las opciones se muestran y explican a continuación.
Eclipse Entorno de desarrollo basado en lenguaje Java y el más utilizado a la hora de programar en multitud de plataformas. Se compone de un conjunto de herramientas de programación de código abierto (open source), usada típicamente para desarrollar entornos de desarrollo integrados (IDE), por ejemplo el de Java, llamado Java Development Toolkit (JDT).
Eclipse se basa en plugins (módulos) que proporcionan funcionalidad a la plataforma. En el caso específico de Android tenemos el plugin ADT (Android Development Tools) que nos proporciona un entorno para crear aplicaciones Android (creación de proyectos Android, crear interfaz de usuario, hacer debug con el Android SDK).
Android Studio Recientemente declarado como IDE oficial [1.1] para Android, tiene muchas similitudes con el entorno de desarrollo Eclipse aunque mejora algunos aspectos, por ejemplo, para la creación de interfaz de usuario tanto en Eclipse como en Android Studio se basa en código XML, la diferencia radica que en Android Studio puedes ver las modificaciones hagas en el código XML al mismo tiempo que lo modificas tiempo real, mientras que en Eclipse se debe de actualizar el visor de la interfaz gráfica.
Pueden importarse y exportar proyectos de Eclipse, facilitando así la migración al entorno oficial de Android. Es un entorno muy potente y optimizado para Android, presente y futuro del desarrollo de aplicaciones Android.
Appcelerator Titanium Plataforma open-‐source que permite crear aplicaciones en diferentes plataformas móviles como iOS, Android, Windows Phone y BlackBerry OS. Se basa en la programación mediante lenguaje JavaScript. Dispone de una librería o API que nos permite acceder a funcionalidades
7
de Android (sistema, mapas, acelerómetro, relocalización...) así también la creación de vistas o interfaces de usuario.
Una diferencia notable entre Titanium y Eclipse/Android Studio se debe a que en el primero podemos integrar el diseño de la interfaz dentro de la lógica programable de la aplicación (funciones, acciones, métodos...) mientras que en los segundos programas debe separarse la implementación de la interfaz del código principal de la aplicación.
Xamarin Anteriormente conocido como MonoDroid, es una plataforma de desarrollo basada en lenguaje C# (C-‐Sharp) y que permite crear aplicaciones de cualquier sistema operativo (Android, iOs y WindowsPhone) programando en lenguaje C#. Dispone de una interfaz de desarrollo propia, pero a la vez se puede integrar en Visual Studio como un plugin, aunque ésta última opción es de pago.
La API nativa de Xamarin tiene mucha semejanza con la nativa de Android (utilizada en AndroidStudio y Eclipse). Al ser multiplataforma (como pasa en Titanium/PhoneGap) el tiempo de compilado y carga es elevado, además las aplicaciones pesan bastante más de lo común, aunque la ventaja de programar para multiplataforma es aprovechar bastante código.
Visual Studio Entorno de desarrollo para sistemas operativos Windows desarrollado por Microsoft. Permite la creación de programas para ordenador y servicios web, para ello Visual Studio posibilita la programación en distintos lenguajes (C++/C#, Java, VB.NET).
Aunque el entorno de desarrollo sea de pago, para estudiantes como nosotros Microsoft nos da la oportunidad de obtenerlo sin ningún coste.
2.1.2 Protocolo de comunicación wireless Para la transmisión de datos y la correcta comunicación entre dispositivos se usará un protocolo de transmisión sin cables (wireless). En la actualidad existen diferentes métodos de comunicación entre dispositivos mediante tecnología wireless, pero para dispositivos móviles, los dos protocolos por excelencia y más usados son el Bluetooth y el WiFi [1.2]. Describiremos las características de cada uno ellos y la razón de haber escogido WiFi frente a Bluetooth.
Bluetooth Bluetooth es un estándar de telecomunicaciones wireless para distancias relativamente cortas, diseñado para ser un protocolo de bajo consumo y basado en transceptores de bajo coste. Como la mayoría de conexiones entre dispositivos, se utiliza el modelo de maestro-‐esclavo. En una conexión Bluetooth, un dispositivo maestro puede estar conectado con hasta 7 dispositivos en una piconet (red informática conectada mediante Bluetooth), donde los dispositivos pueden alterar roles entre maestro y esclavo aunque solo puede haber un maestro (los demás serán esclavos).
8
Se clasifican diferentes clases o tipos de Bluetooth, cada uno con una potencia y rango, se describen a continuación [1.3]:
Clase Máxima potencia (dBm) Rango
1 20 100 m
2 4 10 m
3 0 1 m
La clase 1 es mayoritariamente para uso industrial mientras que la clase 2 es la que nos interesa en nuestro caso, ya que es la utilizada por los dispositivos móviles. El rango efectivo de las diferentes clases varía dependiendo de las condiciones de propagación, en nuestro caso, la comunicación se realizaría en interior, por lo que tendríamos que tener en cuenta los distintos obstáculos que se podría encontrar la señal (paredes, objetos…), por lo tanto, el rango efectivo estaría entre 5 y 10 metros.
Los dispositivos con Bluetooth, al intentar conectarse a otro deben estar “visibles” para que puedan aparecer en la lista. Al conectarse con un dispositivo se envía la siguiente información:
Nombre del dispositivo Clase del dispositivo Lista de servicios Información técnica
La conexión se puede realizar directamente si el dispositivo conoce la dirección de los otros dispositivos a conectar, aunque algunos servicios pueden requerir el permiso del usuario para poder empezar a comunicarse. Cada dispositivo cuenta con una dirección de 48 bits, normalmente esta dirección no se muestra y en su lugar aparece un nombre del dispositivo que puede ser configurado por el usuario.
El hardware de un dispositivo Bluetooth está compuesto principalmente de dos partes. La primera se encarga de modular y transmitir la señal mientras que la segunda compuesta por un controlador digital se encarga de la transferencia (síncrona y asíncrona) y la codificación y cifrado de datos.
El problema principal de este protocolo, aparte del rango para dispositivos móviles (muy limitado), es el requisito de tener un transceptor o receptor de Bluetooth en el ordenador para poder realizar la comunicación entre dispositivos, supondría un gasto adicional a la hora de utilizar nuestra aplicación.
9
WiFi Wifi es una tecnología que permite la conexión entre distintos dispositivos sin la necesidad de utilizar cables, es decir, sin estar físicamente conectados, usando para ello, la banda de 2.4 y 5 GHz y siguiendo los estándares 802.11. Los distintos dispositivos conectados a una misma red Wifi pueden tener acceso a Internet mediante un punto de acceso inalámbrico. Estas son las dos principales funciones del Wifi (comunicación entre dispositivos y acceso a Internet).
Una estructura [1.4] de una red Wifi se compone de diversas partes:
Punto de acceso Tarjeta de red (wireless) Router (opcional)
El punto de acceso es el soporte físico para crear y mantener redes inalámbricas, permite la comunicación entre los dispositivos de la red y controla la conexión y desconexión de los dispositivos.
La tarjeta permite conectarse a un punto de acceso dentro del rango, esta tarjeta puede ser externa mediante USB o interna mediante conector PCI, es decir, conectada directamente a la placa base del ordenador.
Por último el router, el cual nos permite tener acceso a Internet desde el punto de acceso.
En las comunicaciones en área local wireless existe un conjunto de especificaciones llamadas IEEE 802.11. Cada cierto tiempo estas especificaciones se actualizan y se crean nuevas versiones, las cuales mejoran técnicas y tecnologías.
En la actualidad se usan dos tipos [1.4]:
Versión Frecuencia Ancho de banda Velocidad Rango (interior)
802.11b 2.4 GHz 20 MHz 11 MB/s 35
802.11g 2.4 GHz 20 MHz 54 MB/s 38
El rango depende de la banda de frecuencia, la ganancia y tipo de antena y la técnica de modulación utilizada.
Una de las desventajas de la conexión mediante Wifi es la seguridad de la red. Al no estar conectados físicamente los dispositivos entre sí, es más sencillo tener acceso al flujo de información y a los mismos dispositivos. Para evitar esto, se utilizan unos protocolos de cifrado que aumentan la seguridad de la conexión, que aplican la codificación a la información transmitida.
10
Existen diversos estándares o protocolos de seguridad, los siguientes son los más destacados:
WEP Cifra los datos de la red usando para ello 64 o 128 bits. Actualmente muy poco usado por la facilidad de descifrar las claves.
WPA La clave de acceso se genera dinámicamente. IPSEC Permite la autenticación de usuarios para acceder a la red.
Una variante de conexión Wifi se llama WifiDirect. Se trata de una norma que permite la conexión entre diferentes dispositivos entre ellos, sin necesidad de un punto de acceso. Cuando se establece la primera conexión, los dispositivos deciden y determinan cuál de ellos va a ser el punto de acceso. Esta tecnología es usada sobre todo por impresoras y cámaras pero también se encuentra presente en smartphones y es utilizada principalmente para compartir archivos.
2.2 Estado del arte: Dispositivo móvil En los últimos años, el crecimiento de uso y de usuarios de teléfonos móviles inteligentes (smartphones) ha crecido espectacularmente. Este crecimiento es cada vez más grande gracias a las nuevas funcionalidades o utilidades que se añaden a los smartphones, pero también se debe a la necesidad de la sociedad urbana a estar conectados con otras personas continuamente (necesidad producida o agravada a partir de la creación de redes sociales).
2.2.1 Aplicaciones A causa de este gran uso de smartphones, se ha abierto un mercado de aplicaciones con un surtido de opciones bastante amplio, esto significa, además, un nuevo mercado de trabajo, creando profesiones y empleos. Si nos dirigimos a los puntos de descarga oficiales de cada plataforma, ya sea la Apple Store para iPhone o PlayStore para Android o Windows PhoneStore para Windows Phone, podremos ver la gran variedad de aplicaciones que puede haber (entretenimiento, educación, multimedia, comunicación, salud…).
Las aplicaciones nos ayudan a agilizar y controlar nuestro día a día más fácilmente. Seguidamente veremos algunas aplicaciones relacionadas con la temática del proyecto y que están actualmente en las tiendas de aplicaciones oficiales de los distintos sistemas operativos.
Aplicaciones de Audio Aunque nuestra aplicación para Android no capta ningún audio ni aplica ningún procesado, entraría en la categoría de aplicaciones relacionadas con el audio ya que al final es el objetivo del proyecto conjunto.
Si entramos en la sección Música y audio de la tienda de aplicaciones podemos ver que la mayoría de aplicaciones son de reproducción de audio, ya sea en local (archivos de sonido que se encuentran en la memoria interna o tarjeta SD del terminal Android) o streaming. Pero nos vamos a centrar en las aplicaciones de procesado de audio, ya que en este proyecto se utiliza el procesado de audio para poder hacer efectos de guitarra.
11
ClearTune Se trata de una aplicación para afinar instrumentos, orientado principalmente a guitarra. Utiliza el sonido captado por el micrófono y lo procesa para recoger la frecuencia del tono y así indicar al usuario si debe o no afinar. Esta aplicación está centrada para Android, pero en los otros mercados de aplicaciones de los distintos sistemas operativos podemos encontrarnos con aplicaciones muy similares a ésta.
Shazam Es una de las aplicaciones más famosas en la categoría de audio, disponible en cualquiera de las tres grandes plataformas móviles (Android, iOS, WindowsPhone). Captura el sonido proveniente del micrófono del dispositivo para procesar la señal, seguidamente coteja con una base de datos y finalmente muestra el nombre de la canción capturada.
Estas aplicaciones son dos ejemplos de procesado en una dirección, es decir, procesa el audio de entrada pero no hay audio de salida, sino que muestra información del audio capturado. A continuación veremos aplicaciones con entrada y salida de audio (procesado).
Amplitube Amplitube nos proporciona un estudio virtual para ordenador con amplificadores, pedales y distintas configuraciones para nuestro terminal. Esta aplicación está disponible para dispositivos con iOS y Android, este último caso con excepción, ya que solo lo pueden utilizar terminales con una tecnología llamada Samsung Professional Audio, que como su propio nombre indica es propiedad de Samsung por lo que solo sus terminales podrán utilizar esta aplicación. Además, para poder utilizarlo se deberá conectar utilizar una interfaz la cual tendrá una entrada de instrumento y una salida de auriculares.
Aplicaciones Comunicación vía Wifi Una vez visto algunas aplicaciones relacionadas con el procesado de Audio, ahora veremos algunas aplicaciones para poder compartir archivos mediante una red Wifi.
AirDroid La aplicación por excelencia en Android para compartir archivos entre dispositivos. Permite manejar tu terminal Android desde tu ordenador, teniendo acceso a una extensa serie de funcionalidades, como por ejemplo, la edición de contactos, importación de .apks (aplicaciones), uso de la cámara…
Wifi File Transfer Esta aplicación permite la subida y descargas de archivos desde tu dispositivo Android mediante una conexión inalámbrica Wifi. Existe una aplicación muy parecida a ésta pero basada en el sistema operativo iOS llamada AirTransfer.
Como se verá más adelante, nuestra aplicación no comparte ni sube ningún archivo, lo que realmente realiza es el envío de mensajes. Aun así esta última aplicación es una de las más parecidas ya que estos mensajes se pueden considerar como archivos de texto que subimos al ordenador.
12
2.2.2 Sistemas operativos para móviles En esta parte analizaremos las ventajas y desventajas de los distintos sistemas operativos que se usan actualmente en todo el mundo.
Sistema operativo Porcentaje Android 84.7 % iOS 11.7 % Windows Phone 2.5 % Otros 1.1 %
En la tabla anterior [1.5] se muestra, en tanto por ciento, los sistemas operativos usados en los smartphones de todo el mundo. Como vemos, Android es el sistema operativo más usado y por una amplia ventaja. Hay que decir que solo los smartphones de propiedad de Apple usan el iOS, mientras que para el caso de Android hay multitud de empresas, casi todas del mercado, que lo usan (Samsung, Motorola, Sony), y es por esto último que tiene un gran porcentaje de uso.
Finalmente vemos como Windows Phone tiene un número de usuarios bajo, esto ocurre por dos razones: la primera, Windows Phone es un sistema operativo relativamente nuevo, tiene la mitad de vida que los dos sistemas operativos por excelencia. Esta primera causa nos conduce a la segunda, Android ya está demasiado extendido (la competencia directa de Windows Phone es Android, ya que el iOS, Apple en concreto, tienen consumidores fieles con otros perfiles). Las compañías fabricantes de smartphones se han adaptado a Android y éste a ellos, trabajan conjuntamente para mejorar. Aun así Windows Phone está disponible en terminales de gran calidad, como por ejemplo la renacida empresa finlandesa Nokia, la cual apostó por el sistema operativo de Microsoft recién nacido, creando así terminales de muy buena calidad.
En la última fila, podemos ver Otros, se refiere a un conjunto de sistemas operativos los cuales, o están desapareciendo (Symbian, BlackBerry OS) o están empezando a usarse (Firefox OS, Tizen). En cualquier caso no los tendremos en cuenta ya que su expansión en el mercado es muy baja.
Seguidamente, explicaremos y analizaremos los sistemas operativos más importantes (Android, iOS y WindowsPhone) por separado.
iOS [1.7] Originalmente creado para iPhone (iPhone OS) más adelante se extendió a dispositivos como iPod Touch, iPad y Apple TV. iOS deriva de OS X (sistema operativo de ordenadores Mac), por lo tanto es un sistema basado en Unix. La simplificación y optimización del sistema es la razón por la cual los usuarios elijan iOS respecto a otros sistemas operativos.
Es un sistema orientado a su uso mediante dispositivos con pantalla táctil, incluyendo la tecnología multi-‐touch, que permite reconocer múltiples gestos y toques en la pantalla.
A partir de la cuarta versión de este sistema operativo se introdujo la funcionalidad multi-‐tarea, la cual permite trabajar con diferentes programas al mismo tiempo, en versiones
13
anteriores esta funcionalidad solo estaba disponible para aplicaciones por defecto del dispositivo.
Una desventaja de este sistema, es que solo se puede obtener y tener acceso a él mediante dispositivos de Apple, mientras que en el caso de Android (competidor principal de iOS) hay una gran variedad de dispositivos.
Pero esto a su vez es una ventaja, si lo vemos a la hora de desarrollar una aplicación. Al tener unos dispositivos fijos es mucho más sencillo crear aplicaciones, sobre todo para el caso del diseño visual de ésta.
En el caso de desarrollar una aplicación necesitaremos un equipo con MacOS X, para así poder utilizar el kit de desarrollo oficial, XCode, y a su vez el emulador (si hace falta) del dispositivo iPhone. Además para poder publicar nuestra aplicación en la Apple Store (servicio para poder descargar aplicaciones) deberemos pagar una cuota anual.
La administración de contenidos se realiza a través de iTunes, el cual es una plataforma para gestionar y sincronizar dispositivos Apple, una diferencia respecto Android el cual se puede usar como un disco duro o pendrive.
La razón por la cual este sistema operativo ha sido descartado es por el precio que supone desarrollar una aplicación en iOS, entre la compra de dispositivos Apple y la cuota anual, el precio total alcanza un valor muy alto.
iOS Compañía Apple,Inc
Versión actual 8.3 Familia SO Darwin (Unix) Lenguaje C, C++, Swift, Objective-‐C
Tienda de aplicaciones Apple Store Coste publicación aplicación 99$ anuales
Multitarea Versión 4-‐7: Si, limitada. Versión: 7+: Si.
Tabla resumen sistema operativo iOS[1.6]
Windows Phone [1.8] Windows Phone es el sistema más joven de los tres principales sistemas operativos para móvil, como apuntamos en la introducción tiene la mitad de vida con respecto a Android y iOS.
14
La compañía propietaria de Windows Phone, Microsoft, ya tenía un sistema operativo para móviles anterior a este, Windows Mobile, ahora ya en desuso.
Pero Microsoft quiere seguir unificando más sus dispositivos entre sí, para ello está desarrollando un nuevo sistema operativo revolucionario, Windows 10 que estará disponible en todas las plataformas (smartphones, tablets y ordenadores) y así dejar de lado Windows Phone.
Una de las características principales de Windows Phone es el diseño de su pantalla principal, llamada Modern UI. Se forma a partir de mosaicos dinámicos que son enlaces a las distintas aplicaciones del dispositivo. Estos marcos, llamados HUBS y que forman el mosaico, van actualizándose continuamente, manteniendo informado al usuario.
La desventaja principal de este sistema es la falta de diversidad en la tienda de aplicaciones, al ser un sistema operativo poco extendido los desarrolladores prefieren otros sistemas más populares, donde su aplicación pueda tener más éxito.
La poca extensión del sistema operativo dentro del mercado de los smartphones y por la inminente aparición del nuevo sistema operativo de Microsoft son las causas por las que se ha descartado este sistema operativo.
Windows Phone Compañía Microsoft
Versión actual Windows Phone 8.1 Familia SO Windows NT 8+ Lenguaje .NET C#, VB.NET, C/C++
Tienda de aplicaciones Windows PhoneStore Coste publicación aplicación 19$/99$ (individual/compañía) anuales
Multitarea Versión7.5: Si, limitada. Versión: 8+: Si.
Tabla resumen sistema operativo WindowsPhone [1.6]
Android [1.9] Diseñado para ser un sistema operativo para móviles basado en Linux, Android apareció por primera vez en un terminal en el año 2008, en un HTC Dream.
La creación del sistema operativo empezó con la compra por parte de Google de Android Inc., algunos de sus trabajadores se fueron a trabajar a Google para desarrollar el sistema operativo basado en Linux. A finales de 2007 un conjunto de compañías del mercado de la telefonía bajo el nombre de OHA (Open Handset Alliance) presentaron Android.
15
Android incluye una serie de aplicaciones básicas o base que forman parte del sistema operativo, como por ejemplo, un gestor de correo, calendario, mapas, contactos…
Además Android ofrece una serie de bibliotecas o librerías que se usan por varios componentes del sistema, estas ayudan a los desarrolladores a poder escribir código con más facilidad y comodidad.
Android usa una máquina virtual llamada Dalvik que es la responsable de ejecutar las aplicaciones programadas en Java. Dalvik está optimizada para requerir poca memoria y permite ejecutar varias instancias de aplicaciones al mismo tiempo, permitiendo así la funcionalidad de multitarea.
Para la gestión de los servicios base del sistema (seguridad, gestión de procesos y memoria…) Android hace uso del núcleo Linux para esta funciones.
Android ha significado un ejemplo de un modelo exitoso. A diferencia de iOS o Windows Phone, Android permite acceder al código fuente y ver su lista de incidencias (problemas resueltos o por resolver), eso sí, sólo cuando la versión ha sido desarrollada y está lista para ser publicada.
Como cualquier sistema operativo que tenga relativamente éxito, Android se actualiza cada cierto tiempo añadiendo nuevas funcionalidades y opciones tanto para los usuarios como para los desarrolladores.
Versión Nombre Fecha lanzamiento API Cuota 5.1 Lollipop 6 Abril de 2015 22 0.4 % 5.0 Lollipop 3 Noviembre de 2014 21 5.0 % 4.4 Kit Kat 31 Octubre de 2013 19 41.4 % 4.3 JellyBean 24 Julio de 2013 18 5.6 % 4.2 JellyBean 13 Noviembre de 2013 17 18.6 % 4.1 JellyBean 9 Julio de 2012 16 16.5 % 4.0 Ice Cream Sandwich 16 Diciembre de 2011 14 5.7 % 3.0 Honeycomb 22 Febrero de 2011 11 -‐ 2.3 Gingerbread 9 Febrero de 2011 10 6.4 % 2.2 Froyo 20 Mayo de 2010 8 0.4 %
En la tabla anterior [1.9] podemos ver las diferentes versiones de Android publicadas, y su respectiva cuota de uso mundial en el todos los dispositivos Android, donde podemos ver que la gran mayoría usa la versión 4.4 KitKat.
Para los desarrolladores Android supone una plataforma perfecta, ya sea para desarrolladores noveles, introduciéndose en el mundo de la programación para móviles, como es en nuestro caso, pero también significa una oportunidad de mercado para las compañías.
16
Para poder desarrollar en la plataforma Android se necesita básicamente un ordenador, con unos requerimientos mínimos muy básicos que hoy en día se cumplen a la perfección con cualquier ordenador. Hay muchos entornos de desarrollo para Android (como se explicara en apartados posteriores) que usan distintos lenguajes de programación (C/C++, Java, JavaScript…), es decir, Android ofrece multitud de opciones y así facilita a los desarrolladores para crear sus aplicaciones.
Android Compañía Google
Versión actual Android 5.1.1 Lollipop Familia SO Linux Lenguaje C/C++, Java
Tienda de aplicaciones Play Store Coste publicación aplicación Pago único: 25$
Multitarea Si Tabla resumen sistema operativo Android [1.6]
2.3 Estado del arte: Programa PC Durante la última década el uso de ordenadores se ha convertido en algo habitual, podríamos decir que prácticamente imprescindible. Encontramos ordenadores en oficinas, colegios, viviendas privadas… donde son utilizados cada día por millones de personas para una gran variedad de funciones diferentes.
Dentro del ámbito musical, de la misma manera, hemos podido ver una clara evolución en la forma de crear, editar y grabar composiciones musicales, donde el mundo digital predomina cada vez más sobre el analógico. La rapidez con la que evoluciona la tecnología actualmente, ha permitido que podamos disponer de un estudio de grabación con calidad “profesional” en nuestra habitación y a un coste relativamente reducido.
2.3.1 Tendencias Centrándonos en el instrumento al que va enfocado este proyecto, la guitarra eléctrica, podemos decir que es uno de los instrumentos que más ha ganado con este cambio. Cada vez más, guitarristas de todo el mundo sustituyen sus amplificadores por procesadores digitales, tanto en casa como en espectáculos en directo. De entre los motivos que pueden impulsar este cambio, encontramos:
-‐ Comodidad: Este, quizá, es el motivo más importante por el que un gran número de músicos sustituyen sus amplificadores y efectos analógicos por procesadores digitales. Los amplificadores analógicos son voluminosos, pesados, y en la gran mayoría de casos, no disponen de efectos. Esto nos lleva a la necesidad de pedales de efectos y en consecuencia, más espacio, tiempo para realizar las conexiones y dinero invertido.
17
-‐ Versatilidad: Los procesadores de efectos digitales, nos permiten realizar infinitas combinaciones entre los efectos de forma rápida y sencilla, obteniendo así un gran abanico de posibilidades sonoras en un espacio reducido.
-‐ Volumen: Si nos centramos en el caso de guitarristas que toquen en su casa, muchas veces tenemos el problema del volumen. Los amplificadores analógicos (sobretodo en el caso de amplificadores de válvulas), necesitan trabajar a un volumen relativamente elevado para ofrecer un buen sonido, llegando a poder molestar a los que estén a nuestro alrededor. En el caso de los procesadores digitales no tenemos este problema, con lo que podemos tocar a un volumen bajo, o incluso con auriculares, sin necesidad de subir el volumen.
Por estos motivos, entre otros, son cada vez más, los músicos que deciden utilizar los procesadores digitales tanto en formato software como hardware.
2.3.2 Procesadores digitales de efectos Dentro del procesado digital de señales de audio, nos encontramos procesadores tanto a nivel de hardware como de software. Nosotros nos centraremos en los procesadores de tipo software, donde podemos encontrar una gran variedad de productos comerciales de gran calidad. Los procesadores digitales a nivel de software se pueden separar en dos tipos:
-‐ Procesadores del tipo “Standalone”: Se tratan de procesadores capaces de funcionar de forma autónoma, sin necesidad de ningún programa adicional. Esto nos permite conectar nuestro instrumento y ponernos a tocar directamente, sin tener que realizar prácticamente ninguna configuración.
-‐ Procesadores del tipo “Plugin”: Por otro lado, los procesadores en formato “plugin” necesitan de un programa tipo DAW (Cubase, Logic, Pro Tools…), para hacerlos funcionar. La ventaja de este sistema, es que al estar integrados en un DAW, podemos realizar grabaciones de nuestras composiciones rápidamente y modificar el sonido posteriormente.
A continuación, veremos varios ejemplos comerciales de procesadores digitales tipo software, orientados al mundo de la guitarra eléctrica.
Guitar Rig (Standalone / Plugin)
18
Guitar Rig es un producto comercial de la compañía alemana Native Instruments, lanzado a la venta en el año 2004 y es posiblemente, el procesador digital de efectos para guitara eléctrica en formato software, más utilizado por los usuarios de todo el mundo.
Guitar Rig, puede funcionar tanto en formato “standalone” como en formato “plugin”. Nos ofrece infinidad de efectos tales como, simulación de amplificadores, simulación de altavoces y micros, overdrive, reverb, delay, entre muchos otros. Además, nos permite escoger el orden de nuestra cadena de efectos, haciendo así, que las combinaciones posibles sean prácticamente infinitas.
Line6 POD Farm™ (Standalone/Plugin)
POD Farm™, es un producto comercial de la marca Californiana Line6 y de la misma manera que Guitar RIg, lo encontramos tanto en formato “standalone” como en formato “plugin”, adaptándose de esta forma a las necesidades de todos los usuarios.
Dentro de POD Farm, encontramos efectos orientados a guitarra eléctrica, bajo eléctrico e incluso, efectos para voz. Estos efectos van desde la reverb más simple hasta la simulación de un amplificador famoso, pasando por todos los efectos que nos podamos imaginar.
Con el paso de los años, POD Farm ha ido evolucionando de tal manera que hoy en día, es utilizado por productores musicales de prestigio internacional tales como Andy Sneap o Joey Sturgis, obteniendo una calidad de grabación igual o incluso superior, sobre el material tradicional.
2.3.3 Librerías orientadas al procesado de audio
JSyn JSyn se trata de una librería open-‐source orientada al procesado de audio y escrita en lenguaje Java. Implementada por el desarrollador de software Phil Burk, JSyn nos permite generar sonidos encadenando diversos módulos denominados como Unit Generators. De entre los módulos que podemos utilizar encontramos osciladores, filtros, samplers, delays, etc.
Además de conectar módulos entre sí, JSyn nos permite grabar una señal de entrada en una pista de audio para posteriormente aplicarle los efectos.
19
Una de las principales ventajas de JSyn es que al tratarse de una librería escrita en lenguaje Java, nos permite crear aplicaciones tanto de tipo “Standalone” como las llamadas Applets ejecutadas utilizando un navegador web.
TheSynthesisToolkit TheSynthesisToolkit se trata de una librería open-‐source escrita en lenguaje C++. De la misma manera que JSyn, está orientada al procesado de audio y se trata de una librería multiplataforma. Empezó a desarrollarse por Perry Cook en el año 1990 y a partir de aquí ha sufrido numerosos cambios entre los que se incluyen el procesado de audio en tiempo real y la integración del protocolo MIDI.
TheSynthesisToolkit nos ofrece un gran número de clases permitiéndonos realizar un infinidad de funciones diferentes, creando así una herramienta con un gran potencial en lo que al procesado de audio se refiere.
De entre las principales características, los creadores destacan la facilidad de uso de la librería, ya que no precisa el uso de librerías o drivers externos.
The Beads Project The Beads Project es una librería escrita en Java y orientada al procesado de audio en tiempo real. Se trata de una librería de código abierto desarrollada principalmente por Ollie Brown y Ben Porter, con el soporte de la universidad de Monash, situada en Melbourne. La librería ha sufrido multitud de cambios desde su publicación en el año 2008, llegando a convertirse en una herramienta muy potente en el campo de la informática musical.
De la misma manera que la librería JSyn, Beads utiliza módulos de procesado de audio llamados Unit Generators. Cada uno de estos módulos genera un efecto distinto, pudiéndose combinar entre sí para generar una cadena de audio más compleja.
Una de las principales ventajas de la librería, es que nos permite aplicar efectos en tiempo real, manteniendo una latencia suficientemente baja como para poder tocar nuestro instrumento sin dificultades.
20
3 Tecnologías utilizadas Una vez tenemos información sobre las diferentes características de cada parte del proyecto hemos de decidir cuáles son las más adecuadas para nuestro caso.
3.1 Tecnologías utilizadas: Conjunto móvil – ordenador Como pasaba en el caso anterior hay algunos aspectos que se utilizan en ambos lados del proyecto, tanto en móvil como en ordenador, por lo que se ha añadido este apartado.
3.1.1 Entorno de desarrollo: Eclipse Probamos cada uno de los diferentes entornos de desarrollo para ver su potencial y características propias. Encontramos algunos inconvenientes en los entornos orientados a la programación a través de lenguaje JavaScript, uno de estos era el tiempo de compilación. Mientras que el tiempo de compilado y cargado de la aplicación en los entornos de Eclipse y Android Studio era de alrededor de 10-‐15 segundos en los entornos de JavaScript el tiempo superaba el minuto y medio, esto se debe a que en estos programas de desarrollo tienen que interpretar el código JavaScript y transformarlo (indexarlo) para cada plataforma (el lenguaje de Android es Java).
Otra gran ventaja de los programas basados en Java es la ayuda, sobretodo la ayuda de la comunidad de desarrolladores [1.10], es mucho más extensa y más detallada que no en los entornos basados en JavaScript.
Por lo que respecta a los lenguajes basados en C# o VB.NET tienen buenas críticas pero en el caso de programar para dispositivos Android tienen el mismo problema de tiempo de compilado e indexado del código que los software basados en JavaScript. Por lo que respecta VB.NET es un lenguaje que se diferencia bastante, la sintaxis del código, de nuestros conocimientos previos en programación (conocimiento de programación en C++).
Por último la programación en JavaScript cuando el código es muy extenso puede ser caótico, sobretodo revisar los errores de compilación puede ser muy tedioso.
Por lo tanto, el lenguaje principal para las dos aplicaciones será Java, se utilizará el mismo lenguajes en ambas plataformas (evitando, así, problemas de compatibilidad) por su simplicidad y semejanza con otros lenguajes ya conocidos (C/C++) y sobre todo por la inmensa oferta de librerías disponibles. Además una de las principales ventajas de Java, es que se trata de un lenguaje de programación multiplataforma, se puede ejecutar en cualquier máquina virtual de Java sin importar la arquitectura de la computadora.
Una vez elegido el lenguaje de programación (en este caso Java), nos toca elegir que entorno preferimos a la hora de empezar a desarrollar nuestra aplicación, en el caso del dispositivo PC elegimos Eclipse ya que es el entorno de desarrollo por excelencia para este lenguaje en la plataforma PC, pero en el caso de Android debíamos de hacer una elección, Eclipse o Android Studio. Por tener una experiencia previa con el entorno, utilizado en la asignatura de Programación de móviles Android en el grado de Ingeniería de Sistemas Audiovisuales y sabiendo que tendríamos la posibilidad de migrar proyectos entre los dos entornos se eligió finalmente el entorno de desarrollo Eclipse.
21
3.1.2 Protocolo de comunicación wireless: Wifi Para la comunicación entre los dispositivos que conforman el proyecto se decidió utilizar el protocolo de comunicación wireless Wifi.
Una de las razones principales para la elección de la tecnología Wifi es su popularidad y su expansión. A lo largo de los años la tecnología Wifi se ha ido expandiendo y siendo utilizada cada vez más gracias al aumento de la velocidad de la transmisión de datos en la conexión. Su presencia en nuestra sociedad actual es muy alta, presente en establecimientos para poder dar acceso a Internet a sus clientes o en universidades para sus alumnos, incluso hay ciudades con puntos Wifi gratuitos. Por supuesto también es usada en los hogares para poder conectar diversos dispositivos (ordenadores, móviles, Smart TVs) a Internet. Por lo tanto es mucho más probable encontrarnos una red Wifi que una red Bluetooth.
Aunque también requiera de un hardware adicional para poder crear la red y conectarse a ella, este añade más funcionalidades (conexión entre dispositivos, acceso a Internet) que el hardware Bluetooth, que solamente se usara para la interconexión entre dispositivos. Cabe decir que el coste del hardware utilizado para una red Wifi es más elevado que para una red de Bluetooth, aunque actualmente muchos equipos de ordenadores ya vienen con hardware compatible con redes Wifi, ya sean ordenadores portátiles o de sobremesa (tarjeta PCI conectada a la placa base o hardware instalado directamente en la placa base).
3.2 Tecnologías utilizadas: Dispositivo móvil
3.2.1 Sistema operativo: Android Nuestra elección de cara al sistema operativo para dispositivos móviles fue clara y sin dudas, sería una aplicación basada en Android.
A diferencia de los otros sistemas operativos, para publicar una aplicación en el Play Store (mercado de aplicaciones de Android) sólo hace falta un pago único, ese pago es la tasa impuesta por Google a los desarrolladores para poder publicar las aplicaciones en el mercado.
Una parte negativa a la hora de desarrollar aplicaciones en Android es el tema del diseño (en apartados posteriores se explicará con más detalle), dada la vasta multitud de terminales con diferentes características (pantallas, versiones, procesadores…) el diseño de la aplicación puede ser un proceso muy tedioso ya que requiere que la aplicación sea funcional en cada terminal distinto.
Examinando las ventajas y desventajas que nos aporta Android, es la clara opción para ser el sistema operativo en el que se desarrollará la aplicación móvil. Tiene la cuota de mercado más amplia de los sistemas operativos, multitud de alternativas a la hora de programar, y sin coste excesivo para el desarrollador.
22
3.2.2 Hardware Para el desarrollo de este proyecto se han necesitado dispositivos físicos, éstos se han usado para programar, testear...
Los dispositivos que se han usado son de uso cuotidiano, la mayoría de la sociedad tiene estos dispositivos en su casa, es decir, son de un uso extendido. Describiremos las características que los componen y la función que desempeñan dentro del proyecto.
Dispositivo Android (smartphone) El dispositivo Android usado es el terminal MotoG producido por la compañía Motorola. Motorola ha sido una compañía de subidas y bajadas en la industria de telefonía móvil, pero recientemente con la compra de Motorola por parte de Google y a su vez de Lenovo (20%) su relevancia en la industria ha estado creciendo, creando terminales de una relación calidad precio impresionante.
El terminal se adquirió en el año 2014, siendo la primera versión sacada a la venta (actualmente está en venta la segunda versión, MotoG2). Las características del terminal se muestran a continuación[1.11]:
Motorola MotoG Dimensiones 13 x 7 x 1.2 cm
RAM 1 GB Memoria interna 8 GB
Procesador QUALCOMM QUAD-‐CORE 1200 MHz
Pantalla LCD de 4.5' Resolución 720x1280
Versión Android Android 5.0.0 Lollipop
Una desventaja clara de este terminal es la ausencia de expansión de memoria a través de microSD, por lo tanto los datos que quieran guardar serán todos en la memoria interna (aplicaciones, imágenes, música...)
23
Por el otro lado, los terminales de Motorola llevan Android puro o nativo. Muchos fabricantes de terminales Android, personalizan sus terminales creando un estilo propio y a su vez aplicaciones que ya se encuentran instaladas cuando los adquieres. Pero en el caso de los terminales de Motorola no traen con ellos ninguna capa de personalización, por lo tanto a esto se le denomina Android puro (ausencia de una capa superior de personalización Android creada por el fabricante). Otros terminales de Google llevan Android puro, por ejemplo, todas las versiones de los terminales Nexus, tanto smartphones como tablets.
Otras de las ventajas que dispone este terminal es la actualización continua del sistema. Android se actualiza periódicamente con nuevas versiones que añaden funcionalidades, cambian la estética y aumenta el rendimiento del sistema. Al ser Android propiedad de Google, y éste propietario de Motorola, los terminales de Motorola pueden adquirir antes que otros terminales de otras compañías las nuevas versiones de Android, como pasa en este caso donde nuestra versión de Android se encuentra por encima de la mayoría (Android 4.4 KitKat).
En resumen, el terminal a usar es un dispositivo Android de gama media, con unas características técnicas buenas y precio asequible para la mayoría de personas.
PC (Personal Computer) Se necesitará un ordenador con un sistema operativo (Windows o iOS) para poder hacer uso del proyecto. Además se ha requerido la presencia de un ordenador para poder desarrollar la aplicación usando, para ello, una lista de programas (entre ellos el IDE Eclipse).
Hoy en día, los ordenadores más básicos son capaces de proporcionarnos toda la potencia necesaria para programar en dispositivos móviles, para nuestro caso se ha utilizado un ordenador portátil o laptop de la compañía HP. Las características del laptop se muestran a continuación [1.12]:
HP G62 – 140ES Microprocesador Intel Core i3-‐330M a
2.13 GHz RAM 4 GB DDR3
Disco Duro 500 GB Pantalla 17’
Resolución 1366x768 Sistema Operativo Windows 7 Home
Premium Red Fast Ethernet / Wifi
Como vemos en la tabla, el laptop elegido es uno de gama media, pero como hemos dicho antes, hasta uno más básico nos serviría para el desarrollo del proyecto.
Router WIFI Uno de los elementos claves de esta aplicación es la comunicación entre el dispositivo Android y el ordenador, esta comunicación se realizará mediante Wifi. Para que se puedan comunicar entre ellos los dispositivos se necesitará crear una red, esto nos lleva al router.
24
El router [1.13] es un dispositivo que nos proporciona la oportunidad de interconectar dispositivos creando subredes y dedicando direcciones IP a cada uno de los dispositivos conectados a la red, permitiendo la comunicación entre ellos (envió y recibo de paquetes).
Es un dispositivo muy popular y presente en cualquier casa, ya que es el medio más sencillo para acceder a Internet y crear una red local.
3.3 Tecnologías utilizadas: Programa PC
3.3.1 Hardware El hardware utilizado en este proyecto consta básicamente de un PC, una interfaz de audio y unos monitores de estudio autoamplificados.
PC El PC es la herramienta base para la realización de este proyecto. Será el encargado de ejecutar la aplicación junto con el entorno de desarrollo. Al tratarse de un procesador de efectos en tiempo real, necesitamos un procesador capaz de realizar todos los cálculos en el menor tiempo posible y minimizar así, el retardo entre la entrada y salida de audio. Es muy importante poder minimizar la latencia de todo el sistema, ya que una latencia elevada dificultará la ejecución cuando estemos tocando.
El PC utilizado para la implementación de la aplicación se trata de un Macbook Pro 13” del año 2011, con las siguientes características [2.1]:
Procesador Intel Core i5 de doble núcleo a 2,3 GHz Caché de nivel 3 Compartida de 3 MB
Memoria 4 GB de SDRAM DDR3 a 1.333 MHz Gráficos Intel HD Graphics 3000 con 384 MB de
SDRAM DDR3 Disco Duro Serial ATA de 500 GB a 5.400 rpm Pantalla Panorámica brillante de 13,3’ retroiluminada
por LED con resolución de 1280x800 pixeles. Audio Altavoces estéreo con refuerzo de graves,
micrófono omnidireccional y entrada combinada de audio/auriculares.
Ampliación Puerto Thunderbolt, puerto FireWire 800, dos puertos USB 2.0 y ranura para tarjetas SDXC
Interfaz de Audio La interfaz de audio es la encargada de recoger la señal de audio, realizar las conversiones A/D y D/A y enviar la señal resultante a la salida. En nuestro caso, la señal de entrada proviene de las pastillas de la guitarra eléctrica, las cuales transforman la vibración de las cuerdas en una señal eléctrica que posteriormente será enviada a los monitores.
Podemos encontrar dos tipos de interfaces de audio. Por un lado tenemos las interfaces integradas, las cuales van conectadas directamente a la placa base de nuestro PC y son lo que se denomina de forma común como “tarjeta de sonido”. La principal ventaja de este tipo de
25
interfaces es que vienen integradas con la gran mayoría de PCs, por lo que no necesitamos instalar drivers adicionales. Suelen disponer de una entrada de micro y una salida estéreo, con conectores Jack de 3.5mm. Por otro lado, encontramos las denominadas interfaces de audio externas, conectadas al PC mediante puertos USB, FireWire o Thunderbolt. Estas interfaces están orientadas a usuarios que busquen una mejor calidad de audio respecto a la que nos podría ofrecer una interfaz de audio integrada. Las interfaces externas, disponen de mejores preamplificadores de micrófono, mejores conversores A/D y D/A y disponen de conectores de entrada/salida orientados a micrófonos e instrumentos. De esta manera, podemos realizar todas las conexiones sin la necesidad de adaptadores, elementos que pueden empeorar la calidad de nuestra cadena de audio.
Para nuestro proyecto, disponemos de una interfaz de audio externa de la marca Focusrite, más concretamente el modelo Scarlett 2i2. Esta interfaz dispone de dos entradas combinadas que sirven tanto para conector de tipo Jack como XLR, además podemos escoger con un selector si el nivel de entrada de la señal es de línea o es nivel de micro/instrumento y así poder ajustar correctamente el nivel de ganancia de entrada.
Como podemos ver en la imagen anterior, en el panel delantero de la interfaz disponemos de las conexiones de entrada (situados a la izquierda), además del control de volumen general. Por otro lado, tenemos dos interruptores, el primero (de color rojo), nos permite activar o desactivar la alimentación “Phantom” por si utilizamos micrófonos de condensador. Debajo de éste encontramos el botón “Direct Monitor” que nos permite escoger si queremos la señal directa que está entrando por la interfaz o si queremos escuchar la señal procesada que proviene del PC. Por último, a la derecha encontramos una entrada de auriculares con un potenciómetro de volumen independiente del volumen general.
En la parte posterior de la interfaz, encontramos las conexiones de salida en formato Jack ¼” junto con el conector USB con el enviamos y recibimos los datos desde el PC.
Monitores Autoamplificados Finalmente, necesitamos una fuente de salida para poder escuchar la señal procesada, esta fuente de salida puede ser desde unos auriculares hasta unos altavoces o monitores, dependiendo de nuestras necesidades. En nuestro caso, disponemos de dos monitores de estudio autoamplificados, de la marca KRK, modelo RoKit RP5.
26
En la parte delantera, encontramos un altavoz tipo “woofer” de 5” orientado a reproducir las frecuencias graves y medias. Encima de éste, encontramos un altavoz tipo “tweeter” de 1” orientado a las frecuencias agudas.
En la parte trasera encontramos el panel de conexiones, que consta de 1 conector RCA no balanceado y dos conectores balanceados de tipo Jack y XLR. Además encontramos 3 potenciómetros con los que podemos regular el volumen, el nivel de frecuencias graves y el nivel de frecuencias agudas. Finalmente encontramos el botón de encendido y la conexión del cable de corriente.
Por lo tanto, el esquema de conexiones quedaría de la siguiente manera:
3.3.2 Software Dentro del apartado de herramientas software, explicaremos la librería utilizada para realizar el procesado de audio.
27
The Beads Project Para realizar la implementación de los efectos y toda la parte relacionada con el procesado de audio, hemos utilizado la librería The Beads Project[2.2]. Como hemos comentado anteriormente, se trata de una librería basada en lenguaje Java y orientada principalmente al procesado de audio.
Son varios los motivos que nos han impulsado al uso de esta librería. Uno de los más importantes se trata de la capacidad de procesado en tiempo real, ya que este es uno de los requisitos principales que debe cumplir la aplicación. Beads nos permite realizar el procesado de la señal con la rapidez suficiente, para que la diferencia de tiempo entre que tocamos una nota y la escuchamos por los altavoces, no nos dificulte a la hora de tocar nuestro instrumento.
Otro de los puntos a favor de Beads, es la gran cantidad de información de la que dispone. Desde un página web donde encontramos todas las clases y métodos explicados uno por uno [2.3], pasando por documentos con ejemplos prácticos [2.4] e incluso un foro [2.5] (en activo en el momento de la publicación de este proyecto) donde poder realizar consultas al creador de la librería, son algunas de las facilidades que ofrece The Beads Project.
28
4 Implementación del proyecto En este apartado del proyecto se analizarán los aspectos más importantes de cada aplicación, tanto por separado como el conjunto de ellas. Recordemos que este proyecto se basa en un procesador de efectos controlado por móvil, así que las dos plataformas tendrán principalmente desarrollos independientes, pero a su vez un desarrollo conjunto en la parte de comunicación entre los dispositivos.
4.1 Planificación del proyecto Lo primero que se estableció al iniciar el desarrollo del proyecto fue una división de las partes más importantes del proyecto y un periodo de trabajo para cada una de ellas. Así se estableció un cuadro de tareas o flujo de trabajo con fechas límites marcadas.
Periodo Duración limite Tarea 1 1 mes (15 Febrero a 15
Marzo) Inicio desarrollo de ambas aplicaciones. Diseño y lógica
programable básica. 2 1 mes (15 Marzo a 15
Abril) Integración entre dispositivos mediante protocolo Wifi.
3 1 mes (15 Abril a 15 Mayo)
Mejora visual. Integración de nuevas funcionalidades.
4 15 Mayo -‐ 1 Junio Testeo y corrección de errores.
Ampliamos con detalle las tareas realizadas en cada periodo de trabajo (Las explicaciones de cada proceso en detalle se exponen en apartados posteriores.)
Periodo 1. Inicio del desarrollo de la aplicación. Se empezó el desarrollo de ambas aplicaciones por separado, creando un diseño muy básico y genérico. Además se programaron las funcionalidades más básicas y simples, las de mayor prioridad. Periodo 2. Integración entre dispositivos mediante protocolo Wifi. Se creó una aplicación cliente muy sencilla solo dedicada al envío de mensajes al PC. Se hizo lo mismo en el PC, donde se implementó un servidor simple para recibir mensajes y mostrarlos por pantalla.
Con este ejemplo simple de una conexión cliente-‐servidor funcionando se introdujo en el proyecto, cada uno a su proyecto propio (PC – servidor y Android – cliente).
Se añadió una tabla a la base de datos donde se almacenaba los datos requeridos para la conexión.
Seguidamente se diseñó el formato del mensaje de envío y la creación de éste para cambiar el valor de un parámetro de un efecto. Después de comprobar que el formato del mensaje que enviábamos era el correcto se implementó la función para analizar el mensaje y poder realizar la actualización de los valores de los parámetros del efecto.
Se siguió el mismo proceso anterior para crear otro formato de mensaje el cual se enviaba cuando se creaba un nuevo preset o se escogía un preset existente, este formato debía enviar
29
todos los valores de los parámetros de cada efecto. Como en el caso anterior también se diseñó la función para analizar el mensaje y realizar las tareas correspondientes.
Por último se añadió a la aplicación un control de errores. Se trata de un mensaje de alerta cuando se manipula los valores de los efectos en la aplicación sin estar ésta conectada al servidor.
Periodo 3. Mejora visual y nuevas funcionalidades. Una vez visto que la aplicación base o sencilla funcionaba, a falta de corrección de errores menores, se introdujeron algunas nuevas funcionalidades a las aplicaciones.
Se personalizaron varios controles tanto en la aplicación móvil como en el programa de ordenador (botones, textos, imágenes…). Entre las funcionalidades añadidas nos encontramos con la posibilidad de importar o exportar las distintas configuraciones de efectos (en ambas aplicaciones).
Periodo 4. Testeo y corrección de errores. En este periodo se probaron las aplicaciones, tanto por separado como de forma conjunta (comunicación entre dispositivos) y se observaron ciertos errores menores, los cuales no afectaban a la lógica del programa, pero sí a la experiencia del usuario.
Finalmente se solucionaron los diferentes errores que se observaron a lo largo del periodo de testeo.
4.2 Implementación de la aplicación móvil En el siguiente apartado se analizara el desarrollo de la aplicación para la plataforma móvil Android, se explicarán los distintos aspectos que la componen, centrándonos sobretodo en la programación utilizada (clases, métodos, funciones…). Las imágenes puede que difieran en pequeños detalles respecto a la versión final de la aplicación.
4.2.1 Objetivos técnicos Antes de empezar a desarrollar la aplicación para Android, se propusieron diversos objetivos con las funcionalidades básicas que debía tener la aplicación. Una vez estos objetivos básicos se cumplieron, se decidió añadir otros más específicos para añadir más funcionalidades a la aplicación. Los objetivos se describen a continuación:
La aplicación debe tener un diseño funcional y que no resulte muy tosco. Permitirá el almacenaje de las distintas configuraciones de efectos (presets) para poder acceder a ellas cuando el usuario lo requiera.
La aplicación debe conectarse y comunicarse con el servidor que se encuentra en la aplicación de ordenador mediante un protocolo de comunicación wireless Wifi e informar al usuario de la situación en que se encuentra, si está conectado o no.
Además se implementara un apartado de información acerca de los efectos, tanto su descripción como el papel que representa en la cadena de efectos.
30
Estos eran los objetivos básicos de la aplicación, a partir de aquí se introdujeron unos objetivos adicionales para mejorar la aplicación, entre ellos la importación y exportación de presets.
Además se propuso la idea de crear un tutorial para explicar al usuario el funcionamiento del proyecto en conjunto (aplicación y ordenador) a la hora de iniciar la aplicación por primera vez.
Otros objetivos adicionales que se propusieron fueron la compatibilidad con tablets Android, es decir, adaptar el diseño para pantallas más grandes.
También se propuso la implementación de un sistema de compartición de archivos (generados a partir de la exportación de los presets) entre usuarios mediante tecnología en la nube.
4.2.2 Arquitectura: Modelo – Vista –Controlador La aplicación se diseña con el patrón de arquitectura de software de modelo-‐vista-‐controlador [1.14], esta arquitectura separa los datos, la lógica programable y la interfaz de usuario. Los componentes principales se pueden definir como:
Modelo Representa la parte de la aplicación encargada de la interacción con los datos, normalmente estos serán bases de datos. Puede recuperar información para ser mostrada a través de la vista, o manipular la información a través de las órdenes provenientes del controlador. Controlador Gestiona las peticiones o eventos producidos por el usuario y utiliza el modelo y la vista para responderlas. Es un intermediario entre la vista y el modelo. El orden seria así, el usuario hace una petición mediante un evento, el controlador analiza e identifica este evento, consulta al modelo para la captación de los datos necesarios y muestra estos datos usando la vista. Vista Realiza una presentación de los datos del modelo estando separada de los objetos del modelo.
En Android esta arquitectura es muy sencilla de implementar, ya que la vista se crea mediante lenguaje XML y en archivos separados de los archivos del código de la lógica de la aplicación, donde se pueden referenciar los diferentes controles de la vista y controlar los eventos de estos. Además en Android hay herramientas de gestión de base de datos SQL para poder así manipular los datos y crear modelos más fácilmente.
31
4.2.3 Desarrollo de la aplicación En este apartado explicaremos en detalle cada una de las funcionalidades de la aplicación, se hará en orden, como si un usuario probará por primera vez la aplicación.
Inicio de la aplicación por primera vez Al iniciar la aplicación, independientemente que sea la primera vez, aparecerá una pantalla de inicio de carga de la aplicación, la cual es una imagen que al cabo de aproximadamente un segundo desaparece y abre la aplicación. Ahora bien, si es la primera vez, antes de abrirse la aplicación principal se abrirá un tutorial de cómo funciona la aplicación y el proyecto conjunto. Se podrá acceder a este tutorial siempre que se quiera en la opción de menú Acerca De, la explicación de la implementación del tutorial se realiza en el apartado Acerca De, situado más adelante.
Al salir del tutorial o al cerrarse la pantalla de carga aparecerá la aplicación principal. Como hemos comentado en apartados anteriores, esta aplicación tiene un menú lateral con distintas opciones y al cual podemos acceder mediante el arrastrado del dedo desde el borde del lado izquierdo de la pantalla hacia la derecha o también presionando sobre un botón situado en la parte superior izquierda de la aplicación. Al iniciar la aplicación se cargará la primera opción de este menú por defecto (Home/Principal).
Para entender como el funciona el menú, partiremos de los más básico de las aplicaciones de Android, las actividades (activities [1.15]). Las actividades son componentes de la aplicación que nos proporcionan pantallas para que los usuarios interactúen, contienen el código y la lógica de la aplicación y pueden controlar o manipular los eventos de usuario.
A estas actividades se les puede asignar o enlazar un layout o diseño.
Los layouts [1.16] son diseños que se implementan por separado de las actividades, en ellos se añaden los distintos controles que nos proporciona Android (textos, listas, botones…), cabe decir que también se pueden diseñar controles personalizados en las actividades aunque es mucho más complicado y sofisticado, utilizando clases específicas para “pintar” en pantalla y controlar los eventos propios. Al ser controles por defecto del sistema Android, nos proporcionan una serie de métodos y clases que ayudan y simplifican la programación de la aplicación.
Al enlazar un layout con una actividad, podemos relacionar los controles de la vista con los objetos de la clase del controlador (la clase debe coincidir, es decir, utilizar un objeto de la clase Button con un control tipo botón en el layout) creados en el código. El proceso se puede realizar a través de una propiedad que todos los controles poseen la cual asigna un identificador único al control. Además de esta propiedad, los controles poseen muchas más (color, anchura, altura…), aunque dependiendo del tipo de control algunas propiedades pueden variar.
32
Los archivos del diseño o layouts se implementan con lenguaje XML, es un lenguaje parecido al HTML donde se utilizan marcas o etiquetas que contienen la información de la vista.
Los layouts se pueden diseñar de dos maneras, se puede programar el código directamente, o más fácilmente, usar el diseñador gráfico que nos proporciona Eclipse. Cuando se añade un control (o vista) al layout, se crea una etiqueta en el código XML, si hacemos alguna modificación al control (cambio de texto, color, forma) se insertará también en el código.
Para la colocación de los controles en la pantalla se usan unos contenedores, cada cual ordena o distribuye los controles de una manera diferente. Los más populares entre estos contenedores son el LinearLayout y RelativeLayout, en el primero los controles se colocan secuencialmente, uno al lado de otro (dependiendo la orientación, la cual puede ser vertical o horizontal), en cambio en el segundo contenedor se colocan los controles y se establece su posición en relación con la posición de los otros controles que hayan en el diseño, es decir, se hace referencia a la posición de otros controles para calcular la posición. En este proyecto se usa principalmente LinearLayout para el diseño de las pantallas, es un contenedor simple, además el problema con RelativeLayout ocurre cuando modificas la posición de un control, si este sirve de referencia a otros controles y lo movemos, los otros controles se moverán también y puede echar a perder el diseño.
Una característica sobre los diseños y en concreto sobre los contenedores es la siguiente, un contenedor puede albergar dentro de él otro contenedor, por ejemplo un LinearLayout con orientación vertical puede tener en su interior otro con orientación horizontal.
33
Android proporciona más tipos de contenedores, en la siguiente tabla se resumen todos con una descripción breve de cada uno:
Contenedor Descripción LinearLayout Coloca los controles en una dirección, horizontal o vertical. RelativeLayout Coloca los controles dependiendo de la posición de otros. TableLayout Coloca los controles en filas y columnas. AbsoluteLayout Permite definir la localización exacta de los controles. FrameLayout Marcador de posición en pantalla para mostrar un solo control. DrawerLayout Permite implementar un NavigationDrawer (menú lateral).
En esta aplicación se utilizan principalmente tres contenedores: LinearLayout, FrameLayout y obviamente DrawerLayout. Este último es muy importante, ya que gracias a él se pueden crear (cargar en él) diseños dinámicos.
Una vez explicado lo básico sobre las aplicaciones Android, explicaremos el funcionamiento del menú lateral. El menú lateral se implementa en una actividad principal (MainActivity), a ésta se le asigna un layout compuesto por un contenedor de tipo DrawerLayout.
El contenedor DrawerLayout nos permite crear el menú lateral, dentro de él se encuentra un contenedor de tipo FrameLayout que nos permitirá crear las pantallas con diseños dinámicos,
y un ListView (control de la vista de listado de objetos) que nos muestra las diferentes opciones que aparecen en el menú.
La actividad principal es la encargada de cargar los diferentes diseños para cada opción del menú, pero, ¿cómo puede una única actividad manejar distintos controles y vistas?, la respuesta a la pregunta anterior es una clase llamada Fragment.
Los Fragments [1.17] son parecidos a las actividades, representan la interfaz de usuario y su comportamiento en una actividad. Se puede combinar múltiples fragments para una actividad, como es el nuestro caso, o también un fragment puede ser usado por distintas actividades. Los fragments tienen que enlazarse con una actividad, y el ciclo de vida de ésta está ligado con sus fragments (si la actividad se cierra, todos sus fragments también). Sin embargo mientras una actividad este activa podemos manejar sus fragments de manera independiente.
En nuestro caso, se utiliza un fragment para cada opción del menú. Nuestra actividad principal es la encargada de escoger el fragment designado para cada opción (con un método condicional), y así cargar el fragment correspondiente. Cada
34
fragment (como si de una actividad se tratase) debe enlazarse con un layout, el cual se cargará al iniciar el fragment.
Además al iniciar por primera vez la aplicación y acceder a la actividad principal, se instalará la base de datos que se creará directamente con la clase modelo (SQLDataBase), mediante líneas de comando SQL. En esta creación de la base de datos se insertarán valores por defecto en cuanto a los datos de conexión y presets (se añadirá un preset por defecto).
La base de datos es muy simple, se utiliza básicamente para guardar información de la conexión, los parámetros de los presets y también información sobre los efectos, por lo tanto en nuestra base de datos solo tenemos tres tablas (en la sección Anexos se definen las tablas y sus campos).
Una vez explicado el funcionamiento inicial de la aplicación para la primera ejecución, vamos a explicar cada una de las opciones que podemos acceder en el menú lateral.
Home/Principal Es la pantalla principal de la aplicación, en ella se desarrolla la función más importante de toda la aplicación, la manipulación de los parámetros de los efectos y la comunicación entre dispositivos.
El diseño de este fragment es muy característico ya que dentro de él tiene implementado otro fragment, es decir, para cada efecto se ha diseñado un fragment adicional acorde con él y donde se muestran y se pueden editar los parámetros de las efectos. En la siguiente imagen se puede apreciar la distribución de los distintos controles del diseño, recordamos que el contenedor FrameLayout permite crear las vistas dinámicas.
En la parte superior aparece el nombre del preset seleccionado, cuando iniciamos la aplicación se cargará por defecto el primer preset de la lista guardada. En cambio, si no tenemos ningún
35
preset guardado en la memoria nos mostrará un mensaje para crear un preset (“¡Debes crear un preset antes!”), ya que si no se hace los datos introducidos no se guardarán.
Por debajo del texto del nombre del preset nos encontramos con las imágenes (pedales) de los distintos efectos que contiene la aplicación, estas imágenes se usan como botones, al presionar una se cargarán en el control de FrameLayout, el cual está situado más abajo, la vista con los distintos parámetros que tenga el efecto. Las distintas imágenes se han añadido dentro de un controlador llamado HorizontalScrollView lo que nos permite hacer el efecto scroll (deslizar la pantalla) en dirección horizontal para poder acceder a todas la imágenes si la pantalla del dispositivo que usamos no es lo suficientemente grande.
Como se ha comentado antes, debajo de las imágenes se encuentra el FrameLayout, en este se cargan los diseños de los parámetros de los efectos. Aunque hay distintos diseños para cada efecto, la estructura que se sigue para crearlos es idéntica para cada uno.
Primeramente tenemos en nombre del efecto y a su lado un interruptor que nos permitirá encender o apagar el efecto, en el caso del amplificador este interruptor no se ha añadido. Si continuamos bajando veremos los controles para poder manipular los valores de los parámetros, estos controles se llaman Sliders y es un control básico en la librería Android.
36
Por último tenemos la funcionalidad de conectividad y conexión, en esta parte podemos ver en la parte inferior un texto que nos indicará el estado de la conexión (conectado / desconectado) y encima de éste se encuentra un botón para empezar la conexión con el PC.
Al presionar el botón nos aparecerá una pantalla en forma de dialogo (tamaño reducido) para pedirnos los datos para la conexión, concretamente la dirección IP y el puerto a utilizar.
Una vez hayamos aceptado los datos introducidos la aplicación se intentará conectar con el servidor, si ha tenido éxito, el texto inferior cambiará a Conectado y se pondrá de color verde, por otro lado si ha tenido algún error o fallo de conexión el texto permanecerá en rojo.
Una vez conectados con el servidor, podremos manipular los parámetros de los efectos gracias a los controladores de tipo sliders, además la conexión se mantendrá activa aunque cambiemos de pantalla del menú, incluso si accedemos a otra actividad dentro de la aplicación. Si intentamos cambiar los parámetros de los efectos sin estar conectados, aparecerá un mensaje de alerta avisándonos de este problema, la aparición de este mensaje se puede desactivar en el menú de Opciones.
La explicación detallada de la conexión (clases utilizadas, métodos implementados…) se encuentra en el apartado de Conexión, situado más adelante en la memoria.
Presets En esta parte de la aplicación podemos ver la lista de presets creados por el usuario y que se encuentran almacenados dentro de la base de datos de la aplicación.
La vista se compone de un control ListView personalizado. El control ListView permite hacer listas, en su diseño original (el más básico), hace listas de cadena de caracteres (Strings). En nuestro caso se ha modificado su diseño para que además de una cadena de caracteres aparezca una imagen a su lado, además se ha añadido un texto adicional que nos visualiza el identificador del preset a mostrar.
37
En la parte inferior de este fragment podemos ver un botón el cual nos permite añadir presets a la lista, al presionarlo nos aparecerá un dialogo para que introduzcamos un nombre, este campo no puede estar vacío (no puede haber un preset sin nombre). Al aceptar se nos abrirá la pantalla o fragment Home con el nuevo efecto cargado, los valores que nos aparecen se crean por defecto.
Además podremos eliminar cualquier preset de la lista manteniendo pulsado la fila del preset durante un cierto periodo de tiempo, esta opción es irreversible, una vez eliminado no se puede volver a recuperar.
38
Efectos La funcionalidad de este fragment es informativa, nos muestra una lista de los efectos que se encuentran en la aplicación. No es el mismo control de tipo lista que nos encontramos en el fragment de Presets, este controlador va más allá, es una lista expandible o también se le puede llamar lista ramificada (tree-‐list).
Al presionar sobre alguna de las opciones de la lista se expandirá hacia abajo y se mostrará información básica sobre el efecto. Este control se asemeja mucho a la lista de presets, aunque su implementación en el código es mucho más complicada.
En este caso utilizamos un control llamado ExpandableListView, en este control se diferencian dos partes importantes, la fila padre y fila hijo. Los datos que se introducen en la lista tienen que tener un formato o estar ordenados de una manera para que el control pueda interpretarlos satisfactoriamente.
Además se ha personalizado el diseño de la fila hijo de la lista expandible, donde se le añadido una imagen (fondo de un color, éste corresponde con el del efecto) al lado del texto descriptivo del efecto para que el diseño quede mejor visualmente.
Exportar/Importar Este fragment es una funcionalidad añadida a la aplicación, es decir, se realizó después de completar las funcionalidades más importantes.
39
Tanto la exportación como la importación de archivos utilizan la misma ruta para el almacenado de archivos o la carga de éstos, respectivamente.
Los archivos se encuentran en una carpeta dentro de la memoria interna, esta carpeta se creará, si no existe, al iniciar la aplicación.
Exportar Permite guardar los presets que tengamos almacenados en nuestra base de datos en la memoria interna del dispositivo o terminal Android.
40
El archivo resultante es un archivo de tipo texto, el formato de salida es muy simple, parecido al que enviamos al servidor al cargar un preset desde el fragment Presets.
La imagen anterior muestra el contenido de un archivo generado al exportar un preset, el formato de este texto es simple, el primer valor es el nombre del preset, y los restantes son los valores de cada efecto ordenados.
La vista es muy parecida a la vista del fragment Presets, en ésta, el control ListView personalizado ocupa todo el tamaño de la pantalla. Al presionar sobre una fila de la lista aparecerá un mensaje indicándonos que el archivo ya ha sido creado.
Los archivos se guardan en la carpeta designada de la memoria interna con el mismo nombre del preset, si ya se encuentra un archivo con el mismo nombre, éste se sobrescribe.
Importación Permite la carga y almacenaje en la base de datos de presets mediante los distintos archivos de texto ubicados en la carpeta de la memoria interna.
41
La vista de esta actividad es idéntica a la anterior (Exportar), su única diferencia es la imagen utilizada en la lista. En esta lista se muestran los diferentes archivos que se encuentran en la carpeta.
Al presionar sobre una fila de la lista, el preset se almacenará en la base de datos. Para realizar esta operación se realiza un comando SQL para insertar en la base de datos un nuevo registro en la tabla de presets. Los valores introducidos serán los proporcionados por el contenido del archivo, estos valores están separados por una coma, y como en el caso del servidor, al saber que vamos a obtener todos los valores de todos los parámetros de cada efecto, no necesitamos incluir ningún identificador (ni de efecto ni de parámetro).
Esta función no tiene en cuenta si hay un preset con el mismo nombre y los mismos valores, por lo que puede haber presets duplicados en nuestra base de datos.
Opciones Este fragment se encarga del control de los parámetros de la configuración relacionados con la aplicación. Su diseño es muy distinto al resto de la aplicación ya que se usa una característica de Android llamada SharedPreferences [1.19], la cual nos permite guardar datos (preferencias) en la aplicación y que se pueden acceder desde cualquier actividad.
42
Uno de los requisitos para que el usuario pueda modificar estos parámetros es el diseño de la pantalla, esta se debe de hacer con unos controles específicos (explicado más adelante).
Acerca De En este último fragment se encuentra información básica sobre la aplicación. Podemos encontrarnos la versión que se está utilizando, los nombres de los desarrolladores del proyecto conjunto y la licencia de software.
Además se podrá acceder al tutorial que nos aparece la primera vez que iniciamos la aplicación. Este tutorial se basa en un control llamado ViewPager que nos permite hacer la visualización de layouts (en este caso, imágenes) y poder desplazarnos entre ellos con un simple movimiento deslizante (de lado) del dedo en la pantalla.
En nuestro caso se usa un único layout que se compone de un control ImageView que ocupa toda la pantalla, este control nos permite visualizar una imagen, la cual tenemos que enlazarla con el control.
Como se ha mencionado antes ViewPager permite la visualización de distintos layouts, para poder cargar cada layout se usará, nuevamente, la clase Fragment. Sólo se creará una clase extendida de Fragment, ya que su única función será la visualización de una imagen, al deslizar el dedo por la pantalla lo único que deberá hacer el fragment será identificar la posición donde nos encontramos dentro del control ViewPager y cargar la imagen correspondiente.
Cuando se muestre la última imagen del tutorial, al presionar sobre ella nos llevará al fragment principal de la aplicación.
43
4.2.4 Clases/Funciones En este apartado definiremos cada una de las características usadas en la programación de la aplicación, explicando tanto las clases utilizadas (existentes en el paquete por defecto Java y las creadas por nosotros mismos).
El proyecto se organiza en paquetes, éstos permiten organizar mejor el proyecto, cada uno de estos paquetes contienen un conjunto de clases.
A cada paquete se le asigna un nombre único para evitar colisiones de nombre, se usan para ello una estructura como la usada por los dominios de internet.
Paquete Actividades Este fue el primer paquete creado, por eso no tiene un nombre específico como los demás. En este paquete se encuentran las distintas actividades que se utilizan en nuestra aplicación.
44
Todas las clases de este paquete extienden de la clase Activity, con una excepción en la clase MainActivity la cual extiende de la clase ActionBarActivity.
Activity/ActionBarActivity La clase Activity [1.15] se hace cargo de la creación de la ventana para el usuario donde el desarrollador puede implementar la interfaz de usuario. Normalmente se presentan al usuario en pantalla completa, pero esto se puede cambiar para que aparezcan de diversas formas.
En la imagen anterior vemos el ciclo de vida de una actividad, cada uno de estos eventos (onCreate, onPause, onDestroy…) se puede capturar dentro de la propia actividad y así poder personalizar su comportamiento.
La clase ActionBarActivity es muy similar a la clase Activity, pero a diferencia de esta permite añadir características en versiones antiguas del sistema Android, en concreto del elemento ActionBar, éste lo podemos en la parte superior de la aplicación.
45
Gracias a esta actividad y a las librerías de apoyo, versiones anteriores de Android pueden utilizar este elemento. En nuestro caso es bastante importante ya que nuestra ActionBar tiene implementada la función de abrir el menú principal, gracias a un botón situado en ella.
Conectivity Esta actividad es la responsable de pedir o solicitar al usuario los datos para realizar la conexión con el servidor. Una de las características de esta actividad es su tamaño reducido (tamaño diálogo), característica que comparte con la actividad InsertPreset.
Tiene una función muy básica, recoger los datos introducidos y actualizarlos en la tabla correspondiente de la base de datos (Tabla COMS).
ExportActivity La función de esta actividad se basa en la generación de archivos a partir de los presets almacenados en la base de datos de la aplicación y guardar estos archivos generados en la memoria interna del terminal.
Para ello se utiliza la clase File que nos proporciona Java, en la siguiente imagen podemos ver la función principal de esta actividad, la cual permite crear un archivo y escribir en él.
46
Esta función recibe como parámetros de entrada el nombre del archivo a crear (name), y los datos que se introducirán en el archivo (data). Se usa la clase File para crear el archivo con el formato de texto (.txt), y las clases FileOutputStream y OutputStreamWriter se utilizan para poder escribir el mensaje en el archivo.
ImportActivity Esta actividad tiene la función inversa a la anterior, en este caso da de alta presets en la base de datos mediante archivos que se encuentran en la carpeta de la memoria interna del dispositivo Android.
Se utiliza, como en el caso anterior, la clase File, tanto para listar todos los archivos que hay en la carpeta como para leer un archivo en concreto. El siguiente código es invocado al presionar una opción del listado de archivos:
Identifica el archivo seleccionado en la lista y lo busca en la carpeta, una vez localizado se utilizan las clases BufferedReader y FileReader para crear una cadena de caracteres que será utilizada para insertar los datos en la base de datos.
Una vez se ha dado de alta el nuevo registro en la base de datos, y dependiendo de los parámetros de configuración (Opciones), se podrá cargar y mostrar la pantalla principal del preset recién importado.
47
Podemos ver en la imagen anterior, el código de la función para insertar los datos en la base de datos y la carga del preset (si se ha configurado así).
InsertPreset Esta actividad es similar a Conectivity ya que también tiene un tamaño reducido. Su función también es muy básica y simple, da de alta un preset con el nombre que se introduzca en el recuadro de texto y con unos valores por defecto (parámetros de los efectos).
Splash_Activity Es la actividad con la funcionalidad más simple de la aplicación, además es la primera actividad que se puede ver al iniciar la aplicación. Su función consiste en mostrar una imagen durante un tiempo y pasado este tiempo, iniciar la actividad principal (MainActivity). Ahora bien si es la primera vez que se ejecuta la aplicación iniciará la actividad del tutorial (TutoActivity).
48
Para determinar si es la primera vez que se inicia la aplicación se utiliza un campo de la base de datos (columna TUTO de la tabla COMS), cuando se inicia por primera vez este valor se actualiza y así evitar que inicie el tutorial cada vez que se abra la aplicación.
Esta es la función, la cual utiliza la clase TimerTask y Timer las cuales invocan a un código pasado un cierto tiempo, en nuestro caso ese tiempo se almacena en la variable SPLASH_SCREEN_DELAY, su valor es de mil milisegundos (un segundo).
TutoActivity Como se ha comentado anteriormente, la función básica de esta actividad es informativa, su objetivo es darle información al usuario sobre el funcionamiento de la aplicación y del sistema en conjunto (Android y PC).
En esta actividad se hace el uso de un fragment para poder mostrar imágenes en un mismo layout. Se utiliza el control ViewPager y su clase correspondiente, este control permite crear múltiples ventanas que se pueden acceder a ellas mediante el movimiento deslizante del dedo por la pantalla. Más adelante, se explicará el funcionamiento del fragment utilizado por esta actividad, ImageFragment.
MainActivity Esta es la actividad principal de la aplicación, se inicia al abrir la aplicación (después de Splash_Acitivity). Tiene el principal objetivo y función del control del menú lateral, eso implica la carga y visualización de los diferentes fragments que se enlazan con las opciones del menú.
Para ello se ha implementado una función condicional, dependiendo de la opción del menú seleccionado se carga un fragment u otro.
49
Además de la clase Fragment se utiliza una clase llamada FragmentManager que nos permite cargar el fragment en el contenedor de tipo FrameLayout indicado.
Paquete Adaptadores En este paquete se encuentran clases que se relación con el listado de datos, todas extienden a clases relacionada con los Adapters.
Los Adapters[1.18] permiten crear un puente o conexión entre los datos y el AdapterView, éste puede ser diferentes controles de vista como lista (ListView), rejilla (GridView) y lista desplegable (Spinner).
Dependiendo de la información a mostrar se extenderá de una clase u otra, ya que Android nos proporciona diversas clases de adaptadores (ArrayAdapter, BaseAdapter….). En nuestro caso se extienden de tres clases, BaseAdapter, ArrayAdapter y BaseExpandableListAdapter.
50
Una de las características que veremos en cada una de estas clases es la función getView, en esta función podemos elegir que layout se usara para el diseño de las filas de la lista y enlazaremos los datos a mostrar con el control de la vista que elijamos.
ImportListAdapter Esta clase, la cual extiende de ArrayAdapter se utiliza en aquellas actividades donde aparezcan listados de datos, en concreto en las actividades ExportActivity e ImportActivity. Con este adaptador, no sólo mostramos los datos en forma de listado por pantalla, además se muestra una imagen al lado del texto de cada columna.
La función getView es muy sencilla, ya que el layout utilizado para el diseño de las filas consta de una imagen fija y un texto, el cual nos servirá para mostrar los datos, en este caso, presets (ExportActivity) o archivos en la carpeta de la memoria interna (ImportActivity).
PresetListAdapter Muy similar a la clase anterior (también extiende de la clase ArrayAdapter), su única diferencia radica en el diseño de las filas, aunque esta diferencia es mínima ya que sólo se añade un texto adicional. Esta clase es utilizada para el listado de presets en la clase PresetsActivity.
Su función getView tampoco varía mucho con respecto a la clase anterior.
51
NavigationAdapter Extiende de la clase BaseAdapter, su función se centra en la visualización del listado del menú lateral. El diseño de las filas es muy similar a los anteriores, una imagen y texto a continuación, la diferencia radica en la imagen, en los casos anteriores era una imagen fija, en este caso para cada fila cambiará. Por otro lado los datos a mostrar son estáticos, es decir, en los casos anteriores la información se extraía de la base de datos y ésta es manipulable (se pueden insertar más registros en tablas o eliminarlos), en este caso los datos no variarán.
Podemos ver como en la función getView, carga una imagen y un texto dependiendo de la posición.
ExpandableListAdapter La función de la clase se basa en la visualización de una lista expandible, esta clase extiende de BaseExpandableListAdapter. Se utiliza solo en una actividad, EffectsActivity para mostrar la información sobre los distintos efectos. En esta clase podemos diferenciar entre la lista padre y lista hijo.
La lista padre es la principal, al clicar sobre un objeto de esta lista aparecerá la lista hijo asociada al padre. Solo se diseñó las filas para la lista hijo, es un diseño básico con una imagen
52
de un color básico y a su lado un texto descriptivo del efecto seleccionado. Tanto el color como el texto son distintos para cada objeto de la lista.
Al tener dos listas necesitaremos dos funciones getView, para este caso las funciones que se utilizan son getGroupView y getChildView.
Como podemos ver, las funciones no se diferencian con respecta a las utilizadas en los adaptadores anteriores.
Paquete Base de datos En este paquete podemos encontrarnos con una única clase utilizada para la manipulación de la base de datos.
SQLDataBase Clase que extiende de SQLiteOpenHelper y nos proporciona diversas herramientas para poder interactuar con la base de datos. La función principal de esta clase es la generación de la base de datos la primera vez que ejecutamos la aplicación. Se utilizan comandas SQL para crear las tablas e insertar unos valores por defecto, para así evitar errores de campos vacíos o nulos.
53
En la imagen podemos ver distintas funciones que se encargan del insertado de los primeros valores en la base de datos.
Paquete Clases En este paquete nos encontraremos con clases básicas, no extienden de ninguna clase, su función se basa en facilitar la escritura de código a la hora de programar.
BDEfectos Utilizada en la clase SQLBaseDatos para insertar los datos de los efectos (nombre, descripción).
En este caso se creaba una ArrayList (lista de valores) del tipo BDEfectos para facilitar la inserción de los datos.
Itm_object Esta clase es utilizada para la implementación del menú lateral, contiene las variables de la imagen (icono) y el nombre (titulo) de la opción del menú.
54
Esta clase es utilizada en la actividad principal y en el adaptador.
Preset Muy similar a la clase anterior, se utiliza en las actividades que listan los presets guardados en la base de datos (PresetsActivity y ExportActivity). Facilitan la implementación de la visualización de los datos por pantalla.
Paquete Conexiones En este paquete se encuentra una sola clase encargada de la conexión y envió de datos al servidor.
SocketClient Clase que extiende de la clase de Java: Socket [1.20]. En esta clase tenemos tres funciones básicas y las más importantes. La primera función tiene como objetivo la de conexión con el servidor.
Como podemos ver, solamente creando una variable de la clase Socket la cual le pasamos la dirección IP y el puerto. Para la desconexión con el servidor utilizamos una función de la clase Socket, llamada close.
Y por último, la función para el envió de datos.
55
Esta función recibe como entrada una cadena de caracteres y estos se escriben en el buffer o flujo de salida de la variable de tipo Socket.
Paquete Fragments (1) En el interior de este paquete se encuentran las clases más importantes de la aplicación, todas ellas extienden de la clase Fragment, explicada en secciones anteriores de esta memoria. Como ya se han explicado cada una de estas clases en apartados anteriores, en esta parte se comentarán sus funciones principales.
AboutFragment En esta clase no se implementa ninguna función relevante para la aplicación ya que solo es una pantalla para informar al usuario acerca del funcionamiento de la aplicación. Su única función es la carga de la actividad TutoActivity al presionar un botón.
CargarFragment Como en el caso anterior, en esta clase no se implementa ninguna función relevante, solamente se añaden listeners (captadores de eventos) para capturar los eventos al presionar los botones.
Al detectar el evento se iniciará la actividad correspondiente.
56
EffectsFragment El objetivo principal de este fragment es la visualización de los distintos efectos almacenados en la base de datos y así mostrar información sobre ellos.
Para realizar esta tarea utiliza nuestra clase SQLDataBase, con la cual realiza la consulta y muestra los datos en una lista expandible.
El código anterior permite la recuperación de los datos de la base de datos y los almacena en una variable que después se usará como parámetro de entrada para el adaptador de la lista expandible.
HomeFragment En el interior de esta clase se realiza la lógica de la conexión con el servidor, la carga de presets y la visualización de los distintos parámetros de cada efecto.
Para la conexión con el servidor, como se ha mencionado anteriormente, se recurre a una actividad adicional donde insertaremos los datos para la conexión. Una vez aceptados los datos introducidos comienza la conexión, este proceso se realiza en este fragment, concretamente en una función o método característica de la clase Activity o clases que derivan de ella llamada onActivityResult.
Este método nos permite captar el evento de aceptar los datos para la conexión y recuperarlos, es un modo de traspasar variables e información entre actividades.
57
En el método anterior podemos ver como recupera los datos introducidos (dirección IP y puerto) y con éstos crea un nuevo objeto o variable de la clase SocketClient (explicada anteriormente) para realizar la conexión. Además actualiza la interfaz gráfica dependiendo del resultado de la conexión con el servidor.
Otra de las grandes funcionalidades que tiene este fragment es la carga de los fragments de los parámetros de cada efecto, es decir, por cada efecto se carga un fragment (se muestran en el paquete próximo) con la interfaz gráfica para poder manipular los valores de los efectos. Este manejo o control sobre la carga de fragments se realiza mediante la clase FragmentManager, exactamente igual al control que se realiza en la actividad principal MainActivity. La diferencia radica en que ahora la carga de fragments dependerá de que efecto hayas presionado.
58
Por último, para poder cargar los presets, ya sean provenientes de la lista de presets almacenados o importación de presets, con todos los valores para cada efecto se realiza una consulta a la base de datos. En esa consulta se filtra el efecto cargado mediante un identificador que nos proporcionarán las clases de las cuales provenga el evento de la carga de preset. Una vez tengamos todos los valores recuperados de la base de datos, solo nos queda actualizar la interfaz gráfica y, si estamos conectados, enviar todos los valores al servidor.
OpcionesFragment Su función principal es la manipulación de los parámetros de configuración relacionados con la aplicación. Para ello usa una característica de Android llamada SharedPreferences[1.19], consiste en una serie de datos (preferencias) que almacena la aplicación para mejorar la experiencia del usuario. En nuestro caso tenemos tres parámetros de configuración.
Para el uso de las preferencias se requiere un diseño personalizado, distinto a las demás actividades o fragments. Se utilizan controles especiales designados para esta funcionalidad.
59
En la imagen anterior vemos el código del layout utilizado para crear la vista de este fragment.
La etiqueta key de los controles sirve como identificador de la preferencia y así poder recuperar el valor de las preferencias en actividades. En todos los casos se ha utilizado un control tipo checkbox el cual solo puede tener dos estados posibles, activado o desactivado.
La primera preferencia, si esta activada, envía un mensaje al servidor cada vez que se modifica el valor del parámetro. Por otro lado si esta desactivado solo enviara el mensaje al servidor cuando el usuario deje de modificar el parámetro.
La segunda preferencia sirve para que se no se muestren por pantalla mensajes de aviso cuando intentamos enviar valores y no estamos conectados.
La tercera preferencia configura la reacción de la aplicación al importar un preset a partir de un archivo, si esta activada, al elegir el archivo se inserta el preset en la base de datos y aparece la pantalla principal, si por otro lado esta desactivada solo realiza la inserción en la base de datos.
PresetsFragment La funcionalidad de este fragment es listar los presets almacenados en la base de datos y poder insertar nuevos. Además podemos eliminar presets de nuestra base de datos.
Para poder acceder a un preset o eliminarlo se usan listener, estos captan los eventos al presionar un objeto de la lista.
El código anterior muestra el listener para poder acceder al preset presionado. Lo primero que realiza es determinar el preset seleccionado a partir del nombre y posteriormente carga el fragment de HomeFragment con el id del preset seleccionado.
60
Más adelante nos encontramos el código para poder eliminar un preset, el listener capta el evento al presionar durante un cierto periodo de tiempo. Al captar ese evento crea una ventana de tamaño reducido para confirmar el borrado. Finalmente actualizamos la lista para que no aparezca el preset eliminado.
ImageFragment Este fragment se encarga de la visualización de las distintas imágenes que componen el tutorial de la aplicación.
En el código anterior vemos una función switch (dependiendo del valor introducido, en este caso fragVal, realiza una acción u otra), la cual es responsable de, a partir de la posición del control ViewPager (el cual se utiliza en la actividad TutoActivity), cargar el layout correspondiente.
También podemos ver que en el último layout implementamos un listener que se activa al presionar la imagen, y así inicia la actividad principal.
61
Paquete Fragments (2): Estos fragments son los encargados del envío de mensajes al servidor cuando detectan un cambio en los valores de los presets. Todos los fragments tienen un código idéntico (lógica programable), aunque su diseño sí varía.
Los diseños de estos fragmentos se componen de unos controles llamados SeekBar, son unas barras de progreso que se pueden modificar arrastrando el dedo por ellas, su valor estará condicionado por la posición.
Dependiendo de la configuración que hayamos elegido (preferencias), se enviará un mensaje cada vez que modifiquemos el valor de la SeekBar o cuando dejemos de modificarlo. Para controlar esto, Android nos ofrece captadores de eventos (listener) para detectar el cambio de la posición y para cuando “soltamos” el control (retirar el dedo del control).
En estos listeners también se realiza la función de la actualización de los campos en la base de datos de la tabla PRESETS. Esta actualización se realiza siempre cuando el listener detecta el evento al soltar el control.
62
Además en estos fragments se controla los errores al enviar mensajes, es decir, alerta al usuario mediante una ventana de tamaño reducido cuando no esté conectado al servidor e intente cambiar el valor del parámetro, la aparición de estos mensajes se puede desactivar en el menú de opciones de la aplicación.
Hay un control que solo se encuentra en el fragment para el efecto amplificador (Frag_Amp), este control permite seleccionar el canal que se va a utilizar mediante una lista despegable (Spinner), cada canal tendrá un número identificador asociado.
4.3 Implementación de la aplicación de PC Dentro de este apartado se presenta la estructura de la aplicación así como el diseño de las diferentes ventanas, además de los objetivos técnicos que se pretenden conseguir con la implementación de ésta.
4.3.1 Objetivos Técnicos El objetivo principal de esta aplicación es el de crear un entorno simple y cómodo para el guitarrista cotidiano que acostumbra a tocar en casa, ofreciendo una herramienta que se adapte a las necesidades que pueda tener de la manera más rápida y eficaz posible. Se pretende implementar una interfaz intuitiva, que no precise de grandes conocimientos en el campo de la informática musical y que pueda ser utilizada prácticamente por cualquier usuario.
La aplicación debe poder aplicar efectos en tiempo real, por lo que introducimos el concepto de latencia. La latencia es la diferencia de tiempo entre que tocamos una nota y la escuchamos procesada por los altavoces. Se trata de uno de los conceptos más importantes a tener en cuenta cuando queremos procesar audio en tiempo real, ya que una latencia elevada dificultará la coordinación cuando estemos tocando nuestro instrumento.
La latencia viene introducida por el tamaño del buffer de entrada/salida que utilicemos, cuánto más pequeño sea el buffer, menor será la latencia del sistema. A su vez, el tamaño mínimo de buffer que podremos utilizar dependerá de la velocidad del procesador de nuestro PC, junto con la frecuencia de muestreo que utilicemos.
Se considera una latencia aceptable todo lo que esté por debajo de aproximadamente 11ms [2.6]por lo que nuestra aplicación debe poder procesar todos los efectos simultáneamente sin sobrepasar este límite.
63
Por otro lado, los efectos deben disponer de parámetros configurables. Estos parámetros deben estar orientados a guitarra eléctrica, por lo que se deberá realizar un estudio sobre cuáles son los valores típicos utilizados en los efectos orientados a este instrumento, y sus diferencias con los efectos de carácter general.
La aplicación debe poder gestionar un sistema de “presets”. Un “preset” es una configuración general de los efectos con la que se modifican todos los parámetros simultáneamente para crear un determinado sonido. El usuario debe poder cargar presets ya creados (tanto por la aplicación de PC como por la aplicación Android) y guardar los suyos propios para utilizarlos posteriormente.
Finalmente, la aplicación debe ser capaz de conectarse a un dispositivo Android mediante una red WIFI. El dispositivo deberá poder utilizarse como controlador de los parámetros de los efectos, y a su vez como gestor de presets. Los cambios deberán aplicarse en tiempo real.
4.3.2 Desarrollo de la aplicación Con este proyecto, se busca crear una aplicación que no precise de grandes conocimientos dentro del campo de la informática musical, ofreciendo una herramienta flexible pero a su vez sencilla e intuitiva. Siguiendo con esta idea, se ha estructurado la aplicación utilizando como núcleo una ventana principal, a través de la cual podemos acceder a todas las funcionalidades disponibles.
Al iniciar la aplicación, nos aparece una pantalla de presentación donde se indica el nombre de la aplicación junto con un botón de inicio.
Como podemos observar, en la parte inferior izquierda de la pantalla se ha incluido un campo de texto indicándonos que debemos seleccionar nuestra interfaz de audio por defecto antes de iniciar la aplicación. Podemos seleccionar nuestra interfaz de audio desde “Preferencias del Sistema -‐> Sonido” en el caso de que estemos utilizando un Mac, o desde “Panel de Control -‐> Hardware y Sonido -‐> Sonido” en el caso de que utilicemos un PC con Windows.
64
Una vez hacemos click en el botón de inicio accedemos a la ventana principal. Dentro de la ventana principal se han situado todos los efectos junto a sus parámetros, además de los botones para acceder a las funciones extra como la gestión de presets, la configuración de la aplicación o la conexión con un dispositivo Android. De esta manera, agrupamos todas las funcionalidades de la aplicación en un mismo sitio y evitamos tener que buscar entre varios menús y submenús para realizar las configuraciones.
Los efectos han sido implementados con la intención de simular el diseño de los pedales analógicos para guitarra eléctrica, ya que de esta manera conseguimos acercarnos a la forma de configurar los efectos que se ha utilizado desde los inicios de este instrumento. Utilizando este tipo de diseño podemos tener todos los efectos agrupados en una misma ventana, de manera que podemos modificar todos los parámetros desde el mismo sitio y sin tener que hacer click sobre cada uno de ellos. Además de la simplicidad, otra de las ventajas que nos ofrece este tipo de diseño es que podemos tener una imagen clara de cómo está configurada la cadena de audio y cuál es el orden en el que se están aplicando los efectos.
Se ha realizado la implementación de cuatro módulos de efecto organizados en forma de cadena, por lo que cada módulo utilizará como señal de entrada la salida del último efecto encendido anterior a él. Cada uno de los módulos dispone de una serie de parámetros, configurables mediante un slider, una lista desplegable o un botón.
65
Todos lo módulos tienen un botón de encendido y apagado excepto el módulo denominado como Amp. Este módulo pretende simular el sonido y los parámetros de un amplificador de guitarra eléctrica por lo que se trata del módulo principal de la aplicación. Por esta razón se ha considerado que este módulo debe estar siempre encendido.
Además de los módulos de efecto, se han añadido dentro de la ventana principal una serie de botones que pretenden cubrir las demás funcionalidades de la aplicación. Por un lado tenemos el botón de configuración, mediante el cual accedemos a una ventana donde podemos modificar parámetros como el tamaño del buffer o el puerto a utilizar en la conexión con el dispositivo Android. De esta manera, aseguramos el correcto funcionamiento de la aplicación en cualquier tipo de PC.
El campo “Connection Port” se rellena de forma dinámica, es decir, la aplicación revisa sobre una lista de puertos predefinida, si están libres u ocupados. Utilizando este método aseguramos que los puertos visibles en la lista desplegable estarán disponibles para realizar la conexión.
Por otro lado, encontramos el botón que nos permite establecer la conexión con nuestro dispositivo controlador Android. Al hacer click en este botón, se abre una ventana donde encontramos la dirección IP y el puerto que deberemos introducir en nuestro dispositivo móvil para realizar la conexión.
66
Además de la IP y el puerto necesarios para la conexión, esta ventana nos permite saber si ya estamos conectados con algún dispositivo. Si no estamos conectados con ningún dispositivo nos aparecerá en la pantalla el mensaje “Waiting…”. Una vez realicemos la conexión correctamente, el mensaje cambiará a “Connected!” y ya podremos utilizar nuestro dispositivo controlador.
Para realizar la conexión entre dispositivos es necesario tener la ventana anterior abierta, ya que al hacer click en el botón de conexión ponemos a escuchar el servidor que nos permite obtener datos desde el dispositivo, mientras que si hacemos click en el botón de “Cancel” se cerrará la conexión, impidiendo la comunicación.
Finalmente, se han añadido dos botones para realizar la gestión de presets, uno para importar un preset creado previamente y otro para exportar un preset que hayamos configurado y queramos guardar. El botón de importar presets, abre una ventana que nos permite escoger un fichero situado en cualquier directorio de nuestro PC.
Por otro lado, el botón de exportar presets, genera un archivo con la configuración que tenemos en el momento de hacer click y nos permite guardarlo en cualquier ubicación que deseemos.
67
Además de los botones de gestión de presets, se ha añadido un campo de texto que nos indica el nombre del preset que tenemos cargado en ese momento. Al abrir la aplicación este campo aparecerá como “No Preset Selected” y en el momento en que importemos un archivo, este campo indicará el nombre del preset. De la misma manera, cuando exportemos una configuración, este campo indicará el nombre con el que hemos guardado el archivo.
Se ha añadido una funcionalidad que nos permite saber cuándo se ha cargado un preset y se ha modificado posteriormente. Cada vez que carguemos un preset y lo modifiquemos se añadirá un asterisco al nombre del preset, de esta manera podremos saber que el preset ha sido modificado respecto a sus valores originales.
4.3.3 Efectos Dentro de este apartado, explicaremos en detalle cada uno de los efectos incluidos en la aplicación, así como sus parámetros y rangos de valores escogidos para cada uno de ellos. Además, explicaremos el porqué del orden escogido para la cadena de efectos.
Amp Definición Dentro del módulo definido como Amp se pretende simular un amplificador de guitarra clásico, por lo que no se trata de un solo efecto, sino de un conjunto de ellos.
Antes de explicar la estructura del módulo Amp, debemos conocer cómo funciona un amplificador de guitarra analógico. Existen muchos tipos de amplificadores para guitarra eléctrica, desde amplificadores de transistores hasta amplificadores que utilizan válvulas para amplificar el sonido, pasando por amplificadores con procesadores digitales integrados entre otros. A pesar de que cada amplificador tienes sus características concretas, hay diversos parámetros que podemos considerar comunes para la gran mayoría de ellos, son los siguientes:
-‐ Canales: La gran mayoría de amplificadores disponen de varios canales. Los canales de un amplificador definen el tipo de sonido en términos de distorsión. Entre los más
68
comunes encontramos, el canal de tipo Clean(sin distorsión), el canal Overdrive (poca distorsión) y el canal High Gain (mucha distorsión). Dependiendo del estilo y el sonido que necesitemos, utilizaremos un canal u otro.
-‐ Ecualizador: El ecualizador nos permite acentuar o atenuar determinadas bandas de frecuencia, permitiéndonos ajustar el sonido a nuestro gusto. Por norma general, los amplificadores de guitarra eléctrica disponen de ecualizadores pasivos, por lo que solo son capaces de atenuar bandas de frecuencia. Normalmente se utiliza un ecualizador paramétrico de 3 bandas, donde se distingue entre frecuencias graves, medias y agudas. Dependiendo de cada amplificador, tendremos un ecualizador independiente para cada canal o un ecualizador compartido entre los diversos canales.
-‐ Controles de ganancia y volumen: Dependiendo del amplificador, podemos encontrar el control de ganancia denominado de formas diferentes (Gain, Drive, Distortion…). El control de ganancia regula el nivel de señal que llega a la etapa de pre-‐amplificación del equipo. Este control nos permite saturar la señal, creando así el sonido característico de una guitarra eléctrica con distorsión. Dependiendo del nivel de ganancia que apliquemos tendremos más o menos saturación, y como consecuencia, más o menos distorsión. Por otro lado, el control de volumen modifica el nivel de ganancia en la etapa de potencia del amplificador, es decir, el volumen general. En el caso de los amplificadores que disponen de una etapa de potencia a válvulas, este control añade además una leve distorsión que caracteriza a este tipo de amplificadores.
El módulo Amp, por lo tanto, pretende simular un amplificador de guitarra con todos los controles listados anteriormente.
Parámetros Utilizando como referencia la idea reflejada en el apartado anterior, los parámetros que podemos modificar dentro del módulo Amp son:
69
-‐ Drive: El parámetro Drive nos permite controlar el nivel de ganancia de la señal, es decir, nos permite controlar el nivel de saturación que sufrirá la señal de entrada. Dependiendo del nivel de saturación que apliquemos, tendremos más o menos distorsión. El parámetro Drive varía según un tanto por ciento, donde 0% significa que no aplicaremos saturación a la señal y 100% que aplicaremos el nivel máximo de distorsión.
-‐ Low: El parámetro Low nos permite regular la cantidad de frecuencias graves que eliminamos sobre nuestra señal. Para implementar este parámetro, utilizamos un filtro pasa altos sobre el cual modificaremos la frecuencia de corte.
Para decidir qué frecuencias consideramos como graves, debemos tener en cuenta el rango de frecuencias de un altavoz de guitarra eléctrica. El rango frecuencial de un altavoz de guitarra eléctrica oscila aproximadamente entre los 70 y los 5000 Hz [2.7], por lo que para simular este comportamiento, debemos situar nuestras frecuencias de corte sobre estos valores.
Después de realizar una serie de pruebas, se han considerado como frecuencias graves las comprendidas entre los 70 y los 200 Hz. Por lo tanto, el parámetro Low al 100% se corresponde con una frecuencia de corte de 70 Hz mientras que al 0% corresponderá con una frecuencia de 200 Hz.
-‐ Mid: El parámetro Mid nos permite regular la cantidad de frecuencias medias que eliminamos sobre la señal de entrada. Para implementar el parámetro Mid, utilizaremos un filtro del tipo “Notch” o rechaza banda, sobre el cual modificaremos la ganancia. Consideraremos un valor de 0 dB como el máximo (100%), y un valor de -‐100 dB como el mínimo (0%) del parámetro Mid.
Consideramos el rango de frecuencias medias como el comprendido entre los 200 y los 3000 Hz, por lo que situaremos nuestro filtro rechaza banda centrado en los 1500 Hz, de forma que abarquemos todo el rango de frecuencias consideradas como medias.
-‐ High: El parámetro High nos permite regular la cantidad de frecuencias agudas que eliminamos sobre nuestra señal. Para implementar este parámetro, utilizamos un filtro pasa bajos sobre el cual modificaremos la frecuencia de corte.
De la misma manera que en el parámetro Low, tenemos que tener en cuenta el valor máximo sobre el rango de frecuencias de los altavoces de guitarra eléctrica, 5000 Hz. En este caso, la frecuencia de corte del filtro oscilará entre 3000 y 5000 Hz, siendo 3000 un valor del 100% y 5000 un valor del 0%.
-‐ Volume: Mediante el control Volume modificamos el volumen general del amplificador. Este control nos permite aumentar o disminuir el nivel de ganancia de la señal de salida sin modificar el nivel de saturación de la señal, por lo tanto, nos permite amplificar la señal de una forma limpia y clara. El control de volumen resulta muy útil para regular el volumen en caso de que apliquemos una ecualización muy extrema y queramos tener a la salida el mismo nivel que teníamos antes de aplicarla.
70
-‐ Channel: Finalmente disponemos del parámetro Channel. El parámetro Channel nos
permite escoger entre los canales del amplificador. Como hemos comentado anteriormente, dependiendo del canal tendremos un tipo de sonido u otro, generalmente definido por el tipo de distorsión. En nuestro módulo Amp disponemos de tres canales distintos. Por un lado el canal “Clean” o limpio, el cual nos ofrece un sonido con un nivel de ganancia bajo (leve distorsión) apto para estilos como el Jazz o el Pop. Por el otro lado tenemos el canal llamado “Overdrive”, que nos permite obtener un sonido sutilmente distorsionado y está orientado a estilos como el rock. Finalmente disponemos del canal “Distortion” el cual nos permite obtener un sonido muy distorsionado apto para estilos mas pesados como el heavy metal.
Compressor Definición El compresor es uno de los efectos más infravalorados que podemos encontrar dentro del mundo de la guitarra eléctrica. Esto es debido a que se trata de un efecto orientado principalmente a grabaciones de audio realizadas en estudios de grabación. Por otro lado, se trata de un efecto complicado de configurar correctamente si no se tienen los conocimientos adecuados, ya que dispone de muchos parámetros de configuración y es necesario un conocimiento previo para poder utilizarlo correctamente.
Todos estos factores, añadidos a que el efecto provocado por el compresor es muy sutil y a veces inapreciable por oídos inexpertos, provoca que muchas veces no se tenga en cuenta las posibilidades que ofrece y se prescinda de su uso. Aún y así, un compresor configurado correctamente y colocado en la posición adecuada de la cadena de audio puede suponer una gran mejora de nuestro sonido final.
Un compresor se trata de un procesador de dinámica, que como bien indica su nombre, comprime el rango dinámico de la señal de entrada. El rango dinámico de una señal es la diferencia que hay entre el valor de amplitud más elevado o nivel de pico y el nivel de ruido de fondo del sistema. El compresor controla el nivel de pico de la señal, y en caso de que supere un determinado límite o threshold, reduce la ganancia de ésta un cierto nivel o ratio.
71
En la figura anterior, podemos observar el funcionamiento de un compresor sobre una señal de entrada, para determinados valores de ratio. A partir del valor de Threshold (20 dB), la señal empieza a comprimirse según el ratio especificado. En el caso de ratio igual a infinito, no hablamos de compresión sino de limitación, ya que para cualquier valor de entrada la señal de salida siempre tendrá el nivel definido mediante el parámetro Threshold.
Parámetros Los parámetros que podemos configurar dentro del módulo Compressor, son:
-‐ Attack: El ataque o attack, es el tiempo que tarda el compresor en reducir la ganancia de la señal desde que detecta un valor de amplitud que sobrepasa el umbral escogido. En nuestro caso, podemos escoger valores de ataque comprendidos entre 10 y 500 milisegundos. Un tiempo de ataque rápido, provocará una disminución repentina del nivel de ganancia de la señal, por lo que escucharemos variaciones en el volumen, mientras que un tiempo de ataque lento provocará una ligera distorsión en la señal debido a la falta de tiempo para comprimirse.
-‐ Release: El release, es el tiempo que tarda el compresor en dejar de actuar una vez se ha comprimido la señal, es decir, el tiempo que tardará la señal en volver a su ganancia original una vez comprimida. Podemos escoger valores de release comprendidos entre 100 y 500 milisegundos.
Un release muy corto, provocará cambios repentinos en el volumen de la señal, de la misma manera que cuando tenemos un tiempo de ataque muy corto. Por otro lado, un tiempo de reléase muy largo, puede producir que la señal vuelva a ser comprimida antes de haber recuperado su ganancia original por lo que se podrían ocasionar pérdidas en sonidos con poca ganancia.
72
-‐ Threshold: El umbral, o más comúnmente denominado threshold, es el límite a partir del cual el compresor empieza a actuar. Cada vez que la señal sobrepase el threshold definido, se reducirá la ganancia de ésta. Habitualmente se define el valor del threshold en dB, pero la librería beads utiliza un valor entre 0 y 1 donde 0 corresponde a un valor de 0 dB y 1 corresponde a un valor de -‐∞ dB.
Un threshold de 0 dB, querrá decir que no estamos comprimiendo la señal ya que corresponde al nivel máximo que puede alcanzar la señal en el contexto de audio digital y por otro lado, un threshold de -‐∞ dB corresponderá a una señal comprimida continuamente.
-‐ Ratio: Finalmente tenemos el parámetro ratio. El ratio, nos indica en que proporción se disminuirá la ganancia de la señal una vez comprimida, por ejemplo, un ratio de 2:1 significará una reducción del 50% de la ganancia total. En nuestro caso, podemos escoger entre un ratio de 1:1 (señal sin comprimir), hasta un ratio de 30:1. Utilizar un ratio de compresión muy elevado provocará el efecto llamado limitador. Un limitador comprime toda la señal que sobrepase el nivel de threshold hasta el nivel de éste, eliminando así picos indeseados y permitiendo subir el volumen general sin sobrepasar los 0 dB de máximo.
Un compresor bien configurado, nos permitirá mejorar nuestro sonido en determinadas ocasiones, haciendo que todas las notas se escuchen a un volumen similar y mejorando el sustain de la guitarra.
Delay Definición El efecto de delay es uno de los primeros efectos de audio que se crearon y aún hoy en día es uno de los efectos más simples pero a la vez más utilizados dentro del mundo del audio. Constituye la base de efectos más complejos como podrían ser el chorus, el flanger o la reverberación y permite al usuario crear un sonido con más profundidad.
Existen diversos tipos de delay, podemos encontrar desde un delay simple hasta efectos de delay más complejos como el feedback delay, el multitap delay o el stereo delay.
Todos los tipos de delay, se basan en la idea del delay simple, el cual coge un fragmento de la señal de entrada, le aplica un retardo y suma este fragmento retardado a la señal original. Además del retardo, se le aplica una ganancia determinada (típicamente menor a 1) al fragmento retardado, creando así un efecto similar al de un eco.
73
En nuestro caso, buscamos un delay orientado a guitarra eléctrica, por lo que nos hemos basado en modelos comerciales de este efecto y hemos implementado un delay del tipo feedback. El feedback delay consiste en crear un delay simple y utilizar la salida de éste como señal de entrada del efecto, creando así un una realimentación. Con esta técnica conseguimos crear un efecto de delay con diversas repeticiones, separadas entre si por el parámetro llamado Delay time . Para dar realismo al efecto y poder controlar la realimentación, tenemos que aplicar una ganancia cada vez más pequeña a la señal realimentada, ya que sino estaríamos creando un efecto de delay que no se atenuaría nunca.
Parámetros Los parámetros que podemos configurar dentro del módulo Delay, son:
-‐ Delay Time: El delay time o tiempo de delay, define el tiempo de separación entre cada uno de los retardos, por lo que para un delay time corto tendremos todos los retardos concentrados en un espacio de tiempo pequeño mientras que para un delay time grande, tardaremos más tiempo en escuchar cada uno de los retardos.
Debemos tener en cuenta que para configurar correctamente el tiempo de delay, este debe corresponderse con el tempo (BPM) de la canción o el riff que estemos tocando. Es importante configurar el delay de esta manera para evitar repeticiones en momentos indeseados. Para saber que delay time se corresponde con el tempo que estamos utilizando, debemos aplicar la siguiente fórmula:
74
𝐷𝑒𝑙𝑎𝑦 𝑡𝑖𝑚𝑒 (𝑚𝑠) =𝑁𝑜𝑡𝑒 𝐷𝑖𝑣𝑖𝑠𝑖𝑜𝑛 ∗ 240.000
𝐵𝑃𝑀
La variable Note Division nos indica el número de repeticiones que aparecerán en cada compás. Por ejemplo, si tenemos un compás del tipo 4/4 tendremos 4 golpes o beats por cada compás. Entonces si queremos que nuestro delay cree una repetición por cada golpe, definiremos la variable Note Division como 1/4. En caso de que quisiéramos dos repeticiones por cada golpe, definiríamos la variable Note Division como 1/8. Además de este tipo de divisiones, podemos encontrar las llamadas dotted y triplet, las cuales si indican añadiendo a la fracción un punto o una letra T respectivamente. Para calcular el tiempo de delay con una variable Note Division del tipo dotted, tenemos que calcular el tiempo de delay utilizando la forma normal de la variable Note Division y multiplicar el resultado por 1.5. En el caso del tipo triplet, multiplicaremos el resultado por 2/3.
Por otro lado, la variable BPM (beats per minute) nos indica el tempo de la canción o el riff que estamos tocando. El tempo o BPM define el número de golpes o pulsaciones que caben dentro de un minuto. Cuanto más grande sea el número de BPM, más rápido será el ritmo de la música. Dependiendo del estilo musical, tendremos un rango de tempos u otro, por ejemplo, en música del estilo Pop/Rock el tempo está comprendido entre 100 y 140 BPM mientras que en estilos como el Heavy Metal, el tempo oscila entre los 120 y los 180 BPM.
En nuestro caso, hemos definido el rango de delay time entre 0 y 2000 milisegundos para abarcar prácticamente cualquier combinación, ya que un delay time de 2000 milisegundos corresponde con un BPM igual a 60 para un factor Note Division de 1/2, valores muy por debajo de la normalidad.
-‐ Feedback: El parámetro feedback controla la atenuación entre las diversas repeticiones. Un valor de feedback elevado, provocará que escuchemos un gran número de repeticiones mientras que un valor pequeño provocará una rápida atenuación del efecto. En nuestro caso el valor de feedback oscila entre 0% y 100%, donde 0% significará que no escucharemos ninguna repetición y 100% que las repeticiones serán prácticamente infinitas.
-‐ Mix: El parámetro mix controla el volumen del efecto sobre la señal directa por lo que nos permite aplicar el efecto con más o menos intensidad dependiendo de nuestras necesidades. Se define mediante un tanto por ciento, donde con un ajuste del 0% únicamente escucharemos la señal directa y con un ajuste del 100% escucharemos la señal directa y la señal con efecto al mismo volumen.
El efecto de delay es especialmente útil en partes instrumentales o partes donde predomine la guitarra solista, ya que nos permite alargar el sustain de la guitarra añadiendo amplitud y profundidad al sonido creando un sonido ambiental.
75
Reverb Definición La reverberación es el sonido que se refleja dentro de un espacio cerrado, y que permanece después de que la fuente emisora haya dejado de emitirlo. Cuando emitimos un sonido dentro de una habitación, recibimos por un lado el sonido directo que proviene de la fuente emisora y por el otro, el sonido reflejado o reverberación que proviene del sonido reflejado por las paredes del recinto. Este sonido reflejado es una copia atenuada y retardada de la señal original, factores que dependerán del tamaño y forma de la sala junto con la posición donde estén situados la fuente emisora y el receptor.
Por lo tanto, dependiendo del tamaño de la habitación donde este situada la fuente emisora tendremos un tiempo de reverberación diferente. Cuanto mayor sea la habitación, mayor será el retardo y por lo tanto el tiempo de reverberación, ya que el sonido reflejado tardará más en llegar a nuestros oídos.
El efecto de reverberación es uno de los más utilizados dentro del mundo del audio, ya que nos permite simular las características acústicas de un espacio determinado y aplicárselas a nuestra señal. De esta forma podemos añadir realismo a nuestras pistas de audio a la vez que podemos situarlas en el espacio, dotándolas de más o menos profundidad.
Parámetros Los parámetros que podemos configurar dentro del módulo Reverb, son:
-‐ Room Size: El room size, modifica el tamaño de la sala o lo que es lo mismo, el tiempo
de reverberación de nuestro efecto. Beads define el parámetro room size como un valor entre 0 y 1, siendo 0 un tiempo de reverberación nulo (únicamente escuchamos la señal directa) y 1 el tiempo de reverberación máximo. Podemos entonces crear el efecto de estar en una habitación pequeña y con poca reverberación configurando el room size con un valor cercano a 0, de la misma manera que podemos simular la reverberación que se crearía dentro de una catedral con un valor próximo a 1.
-‐ Mix: El parámetro mix, nos permite definir la cantidad de señal reverberada que escucharemos respecto a la señal directa, es decir, nos permite modificar el volumen de la señal reverberada. De la misma forma que en el efecto de delay, modificamos el nivel de señal reverberada mediante el tanto por ciento, donde con un ajuste del 0% únicamente escucharemos la señal directa y con un ajuste del 100% escucharemos las dos señales al mismo volumen.
76
El parámetro mix está presente en la gran mayoría de efectos disponibles actualmente, tanto analógicos como digitales. En el efecto de reverberación este parámetro tiene especial importancia, ya que nos permite aplicar dicho efecto de una forma más sutil. Utilizándolo correctamente, podemos por ejemplo crear una reverberación con un room size grande pero a bajo volumen, consiguiendo de esta manera un sonido ambiental y con profundidad, manteniendo a su vez la claridad de la señal directa.
Dentro del mundo de la guitarra eléctrica, podemos utilizar la reverberación para dar profundidad a nuestro sonido tanto en partes de solos con distorsión como en partes instrumentales utilizando el canal limpio. Es común utilizar el efecto de reverberación conjuntamente con el efecto de delay para acentuar aún mas la sensación de profundidad.
Orden de la cadena de efectos El orden de la cadena de efectos es el siguiente:
Después de realizar varias pruebas y consultar referencias externas [2.8]se ha decidido utilizar el orden anterior, dejando los efectos de saturación, ecualización y dinámica al principio de la cadena y los efectos en dominio temporal al final de ésta. El objetivo principal de utilizar este orden es el de poder controlar correctamente los efectos de delay y reverberación.
Los efectos de delay y reverberación, utilizan copias atenuadas de la señal de entrada que después se sumarán a la señal original para crear el efecto. Si tenemos en cuenta que los efectos de saturación y procesado de dinámica dependen de la amplitud de la señal, situar los efectos de delay y reverberación al principio de la cadena puede producir resultados indeseados cuando apliquemos los demás efectos. Es decir, colocar los efectos en dominio temporal antes de los efectos de dinámica, puede producir que estos últimos no cumplan con su función correctamente debido a las variaciones en el nivel de la señal.
4.3.4 Programación La parte de programación de la aplicación se puede dividir en dos partes generales. Por un lado tenemos la programación utilizada para realizar el procesado de la señal, implementada mediante la librería “The Beads Project” y la cual engloba desde la conexión y comunicación entre software y hardware hasta la aplicación de los efectos y la configuración de sus parámetros. Por otro lado, tenemos toda la programación relacionada con la implementación de la interfaz gráfica, incluyendo una ventana de inicio, la ventana principal donde encontramos los efectos, una ventana de configuración y la ventana de conexión con un dispositivo Android.
77
Interfaz Gráfica Podemos dividir la interfaz gráfica de la aplicación en cuatro ventanas principales, la ventana de inicio, la ventana principal, la ventana de configuración y la ventana de conexión. A continuación veremos cómo están implementadas cada una de ellas y los elementos que las componen.
Ventana de Inicio (Intro_Frame) Se trata de una ventana muy sencilla que pretende introducir la aplicación. Esta ventana contiene el título de la aplicación, un texto informativo y un botón de inicio. Además, al iniciar la aplicación, nos aparece una animación de esta ventana en forma de “Fade In”. Para crear el efecto de “Fade In” utilizamos una clase de Java llamada FadeIn() [2.9]dentro de la cual se utiliza una variable alpha para aumentar la opacidad de la imagen de fondo.
Ventana principal (Main_Frame) La ventana principal es la ventana donde se ubican los efectos y través de la cual podemos realizar todas las operaciones de la aplicación. A través de la ventana principal podemos configurar los parámetros de todos los efectos, conectarnos con un dispositivo Android, importar y exportar presets o realizar las configuraciones necesarias para el correcto funcionamiento de la aplicación.
Para realizar la implementación la interfaz gráfica, utilizamos una librería de Java llamada Swing. Swing nos permite crear y combinar componentes gráficos tales como frames, botones, sliders y campos de texto entre otros, por lo que se trata de una librería muy potente en cuanto a diseño gráfico se refiere[2.10].
Podemos separar la ventana principal en dos secciones. Por un lado tenemos la parte superior, donde encontramos los efectos junto a los parámetros y sliders de configuración y por el otro, en la parte inferior de la ventana encontramos los botones que nos permiten realizar las demás operaciones disponibles en la aplicación.
Para generar la ventana que contendrá todos los botones y parámetros utilizamos un componente de Swing llamado JFrame. La clase JFrame nos permite generar ventanas, dentro de las cuales podemos añadir otros componentes. Para declarar el objeto JFrame principal utilizamos:
public static JFrame frame; ... frame = new JFrame("Guitar Effects Chain");
De esta forma creamos el objeto frame que después incluirá los demás elementos de la aplicación. Dentro de la declaración del JFrame incluimos el string con el título de la aplicación, nombre que aparecerá en la barra superior de la ventana junto a los botones de cerrar, minimizar y expandir.
Una vez declarado el frame principal, podemos empezar a añadir los demás componentes que compondrán la ventana. Empezaremos explicando los componentes que componen cada efecto, así como las funciones asociadas a cada elemento.
78
Para crear cada uno de los efectos, empezamos por crear un componente del tipo JPanel. La clase JPanel nos permite crear ventanas y añadir componentes dentro de ellas, de forma similar a la clase JFrame. Es necesario utilizar la clase JPanel ya que JFrame se considera una clase de tipo “padre”, por lo que no podemos añadir un JFrame dentro de otro.
Creamos un componente de tipo JPanel para cada efecto:
public JPanel amp_panel = new JPanel(null); public JPanel compressor_panel = new JPanel(null); public JPanel delay_panel = new JPanel(null); public JPanel reverb_panel = new JPanel(null);
La clase JPanel nos permite definir un Layout Manager para cada panel. Un Layout Manager se trata de un componente capaz de posicionar los elementos dentro de un panel. En nuestro caso, sin embargo, hemos optado por estructurar cada uno de los elementos manualmente ya que de esta manera podemos situar los elementos de forma más sencilla.
Definimos cada JPanel utilizando el comando null ya que de esta forma evitamos utilizar el Layout Manager que viene dado por defecto.
Una vez tenemos definidos cada uno de los paneles, tenemos que situarlos en la pantalla. La clase JPanel dispone de un método que nos permite posicionar cada uno de los componentes, a la vez que definimos su tamaño. Se trata de la función setBounds(int x, int y, int width, int height), donde las variables x e y definen la posición del elemento (situando la esquina superior izquierda) y las variables width y height definen el tamaño del componente. Una de las principales ventajas del método setBounds es que podemos utilizarlo con la gran mayoría de componentes de la librería Swing, por lo que más adelante lo utilizaremos para posicionar los demás elementos.
Debajo de cada uno de los paneles, encontramos los sliders que nos permiten controlar los parámetros de cada efecto.
Para definir cada uno de los sliders utilizamos la clase JSlider, incluida dentro de la librería Swing. Además, para cada parámetro deberemos definir dos campos de texto, uno para el nombre del parámetro y otro para el valor actual de éste. Para esta tarea utilizaremos la clase JLabel, la cual nos permite definir campos de texto.
public JLabel parameter_title_label; public static JSlider parameter_slider; public static JLabel parameter_value_label; ... parameter_title_label = new JLabel("Title"); parameter_slider = new JSlider(0,100,50); parameter_value_label = new JLabel("Value");
En el caso del parámetro Channel, dentro del módulo Amp, utilizamos una lista desplegable en vez de un slider. Para definir este tipo de listas, la librería Swing dispone de la clase JComboBox, la cual podemos inicializar directamente con los valores deseados, o añadirlos posteriormente mediante el método addItem().
79
public static JComboBox buffer_size_box = new JComboBox(new String[] {"Clean","Overdrive","Distortion"});
Finalmente, tenemos que definir un botón que nos permita encender o apagar los efectos. En java, podemos definir botones mediante la clase JButton, de la siguiente manera:
public static JButton module_button; ... module_button = new JButton("Title");
Para controlar los sliders, botones, listas desplegables y poder asignarles acciones, añadimos una serie de elementos llamados listeners. Un listener consiste en una función que nos permite capturar un evento (click de ratón, presionar una tecla…) y asignar una tarea al componente. Dependiendo de si se trata de un slider, un botón o una lista desplegable, definiremos un tipo de listener diferente. En el caso de los sliders utilizaremos la función addChangeListener() y para los botones y las listas utilizaremos addActionListener().
Slider_name.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEventt e) { // TODO Auto-generated method stub //Actions } });
Button_name.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub //Actions } });
ComboBox_name.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub //Actions } });
Cada vez que hagamos arrastremos un slider, hagamos click en un botón o seleccionemos un elemento de una lista, se ejecutará el código situado dentro de las funciones stateChanged y actionPerformed. De esta manera asociamos a cada uno de los componentes las acciones necesarias.
En la parte inferior de la aplicación, encontramos los botones que nos permiten realizar las demás operaciones de la aplicación. Por un lado tenemos los botones de configuración y conexión con un dispositivo Android, situados en la esquina inferior izquierda y derecha respectivamente. Cada uno de estos botones abrirá una ventana nueva en la parte central de la aplicación, donde podremos realizar los cambios necesarios en el caso de la configuración, o establecer la conexión con el dispositivo externo que vayamos a utilizar como controlador.
80
En el caso del botón de conexión, además de abrir la ventana ponemos el servidor a escuchar, de forma que al hacer click en el botón la aplicación, ésta estará esperando a que se introduzcan los datos en la aplicación móvil. Para poner el servidor en modo escucha, inicializaremos un objeto de la clase server de la siguiente manera:
new Server();
Además de estos dos botones, tenemos los botones que nos permiten importar y exportar presets, así como el campo de texto que nos indicará el nombre del preset que tenemos cargado en este momento.
Definimos cada uno de los botones mediante la clase JButton, además de la función addActionListener() para controlar cada uno de ellos.
Para implementar los botones de importar y exportar presets necesitamos implementar dos ventanas que nos permitan seleccionar ficheros y directorios de nuestro PC. Necesitaremos una ventana para realizar la importación, seleccionando la ubicación donde está situado el fichero con el preset, y otra para realizar la exportación, permitiéndonos seleccionar un nombre y un directorio para guardar el archivo.
Para generar este tipo de ventanas, Java dispone de la clase JFileChooser incluida en la librería Swing. La clase JFileChooser nos permite crear ventanas de diálogo tanto para seleccionar un fichero como guardar uno creado previamente en el directorio que seleccionemos.
JFileChooser name = new JFileChooser();
Para definir el tipo de ventana que queremos utilizar, utilizaremos los métodos showOpenDialog() y showSaveDialog() para abrir una ventana que nos permita escoger un archivo o una que nos permita guardarlo en un directorio, respectivamente.
Una vez nos hemos definido las ventanas, tenemos que crear una variable donde se almacenará nuestro fichero. Para esta tarea utilizaremos la clase File, la cual nos permite generar un fichero en el cual podemos leer o escribir datos. Utilizaremos el método getSelectedFile() de la clase JFileChooser para definir nuestro objeto File.
File selectedFile = name.getSelectedFile();
Finalmente, en función de si queremos escribir en el fichero o leer de uno ya creado, utilizaremos las clases FileWriter, FileReader y BufferedReader. La clase FileWriter nos permite escribir datos en un objeto de tipo File, se define de la siguiente manera:
FileWriter save_writer =new FileWriter(fileObject_name);
81
Donde la variable fileObject_name se corresponde con el objeto File creado previamente. Por otro lado, utilizamos las clases FileReader y BufferedReader para escribir datos en el fichero que exportaremos. La clase FileReader nos permite leer datos escritos en un fichero y utilizándola conjuntamente con la clase BufferedReader podemos leer el archivo línea por línea. Para definir estas dos clases, crearemos el objeto FileReader directamente dentro del objeto BufferedReader, de la siguiente manera:
BufferedReader br = new BufferedReader(new FileReader(selectedFile));
Una vez tenemos definidos estos objetos, ya podemos leer y escribir en los ficheros correspondientes, utilizando el método write y el método readLine() respectivamente.
Ventana de configuración (Config Frame) La ventana de configuración nos permite modificar el tamaño del buffer de entrada y salida utilizado en la cadena de audio, junto al puerto a utilizar en la conexión entre dispositivos. Para definir la ventana de configuración utilizamos un JFrame con la particularidad de que en este caso, eliminaremos los botones de cerrar y minimizar mediante la función setUndecorated(true).
Definimos una lista desplegable para cada una de las opciones, utilizando de nuevo la clase JComboBox. En el caso del tamaño de buffer, definimos las opciones por defecto utilizando las potencias de 2 comprendidas entre 32 y 512 muestras. Sin embargo, en el caso de los puertos de conexión, debemos asegurarnos de que están disponibles antes de añadirlos como opción a nuestra lista, para ello utilizamos el siguiente código[2.11]:
private boolean isPortInUse(String hostName, intportNumber) { boolean result; try { Socket s = new Socket(hostName, portNumber); s.close(); result = true; } catch(Exception e) { result = false; } return(result); }
La función anterior nos permite comprobar si un puerto (portNumber) está disponible para una determinada Ip (hostName). En caso de que el puerto esté disponible, retornará el valor false.
Finalmente, definimos dos botones mediante la clase JButton, los cuales nos permiten guardar o cancelar los cambios realizados.
82
Ventana de conexión (Connection Frame) La ventana de conexión nos permite poner a escuchar el servidor a través del cual se recibirán los datos de nuestro dispositivo Android, además de indicarnos la IP y el puerto que tenemos que utilizar para la conexión. Definimos la ventana de conexión de la misma manera que la ventana de configuración, utilizando un JFrame junto al método setUndecorated(true) para eliminar los botones de cerrar y minimizar.
Para obtener la dirección Ip de nuestro ordenador, utilizamos la clase GetIp [2.12]. Mediante la instrucción GetIp.getLocalAdress().getHostAdress(), obtenemos la dirección Ip en caso de que estemos conectados a un router, en caso de que estemos desconectados la instrucción nos devolverá un campo null.
Además de la Ip, encontramos el puerto de conexión que tengamos definido dentro de la ventana de configuración.
Audio Dentro de la programación relacionada con el procesado de la señal encontramos:
Conexión con el hardware Para poder obtener la señal de entrada, tenemos que conectar nuestra aplicación con la interfaz de audio donde está conectada la fuente de sonido. Para realizar esta tarea, utilizamos la clase AudioContext. AudioContext nos permite configurar el formato de la señal de entrada y salida, mediante un objeto de la clase IOAudioFormat, el dispositivo de entrada y salida y el tamaño del buffer de entrada/salida.
Mediante la clase IOAudioFormat definimos el formato de la señal de entrada y salida. Consta de los siguientes campos:
♦ Boolean bigEndian: Definición de la arquitectura, True para “bigEndian” y false para “littleEndian”.
♦ Int bitDepth: Definición del número de bits por muestra. ♦ Int inputs: Definición del número de entradas. ♦ Int outputs: Definición del número de salidas. ♦ Float sampleRate: Definición de la frecuencia de muestreo. ♦ Boolean signed: Definción del tipo de datos, true para “signed” y false
para “unsigned”.
En nuestro caso, hemos optado por dejar la configuración que viene por defecto, la cual consiste en:
♦ Arquitectura bigEndian ♦ 16 bits por muestra ♦ 2 entradas ♦ 2 salidas ♦ 44.1 KHz de frecuencia de muestreo ♦ Signed
83
Finalmente tenemos que definir el tamaño del buffer de entrada/salida. Es necesario disponer de un buffer donde poder almacenar los datos entrantes para después enviarlos a la salida, ya que en caso de no tenerlo, podríamos escuchar ruidos indeseados producidos por la pérdida de datos. El tamaño del buffer es uno de los parámetros más importantes a tener en cuenta ya que nos definirá la latencia total del sistema. Un buffer de tamaño inadecuado podría producir que no podamos tocar nuestro instrumento correctamente debido a la diferencia de tiempo entre que tocamos una nota y la escuchamos.
El tamaño de buffer mínimo que podemos escoger, viene condicionado principalmente por la velocidad del procesador de nuestro PC junto con la velocidad de muestreo escogida. Cuanto mayor sea la velocidad del procesador, menor podrá ser el tamaño del buffer y por lo tanto, menor será la latencia total.
Para asegurar un correcto funcionamiento de la aplicación en cualquier PC, el tamaño del buffer de entrada/salida debe ser un parámetro configurable por el usuario. Dentro de la pestaña de configuración de nuestra aplicación, podemos escoger el tamaño de buffer que mejor se adapte a nuestro sistema, escogiendo entre los valores 32 (por defecto), 64, 128, 256 o 512 muestras. Para garantizar el correcto funcionamiento, es importante que escojamos siempre el tamaño de buffer más pequeño que nuestro sistema permita.
Por lo tanto, juntando estas características definimos nuestro AudioContext de la siguiente manera:
ac = new AudioContext(32);
Adquisición de la señal de entrada Antes de obtener la señal de entrada proveniente de nuestra interfaz, debemos entender un concepto introducido por la librería Beads, los UGen. Un UGen (o unit generator) se define como una unidad de procesado de audio para cero o más canales de entrada y salida. Podemos considerar un Ugen como un flujo de audio (con o sin efecto) mediante el cual podemos realizar una serie de operaciones. Una de las principales ventajas de esta estructura es que podemos conectar Ugens entre sí para crear un flujo de audio más complejo, generando así una cadena de audio tal y como la encontraríamos en el mundo analógico.
Para empezar a trabajar con esta estructura, debemos definir el UGen básico que contendrá la señal de entrada. Para esto, definimos un nuevo objeto de la clase UGen:
public static UGen microphoneIn;
Una vez tenemos definido el UGen, le asignamos el valor de la señal de entrada mediante el método getAudioInput() de la clase AudioContext.
microphoneIn = ac.getAudioInput();
De esta manera, obtenemos el UGen básico con el valor de la señal de entrada que proviene de nuestro instrumento.
Procesado de los efectos Una vez tenemos nuestro UGen base con la señal de entrada, podemos empezar a aplicar los efectos. Beads dispone de multitud de clases implementadas con un gran número de efectos y
84
funciones que podemos aplicar a nuestra señal. En nuestro caso, la aplicación está orientada a su uso con guitarra eléctrica, por lo que los efectos y parámetros escogidos están basados en configuraciones típicas para este instrumento.
Amp Como hemos comentado anteriormente, el módulo Amp consta de varios efectos. En primer lugar implementamos el efecto de distorsión, utilizando la función WaveShaper incluida en la librería Beads.
La función WaveShaper nos permite modificar la señal de entrada aplicándole una función de transferencia definida previamente[2.13][2.14]. Además de esto nos permite limitar la señal de salida, definir una ganancia de entrada y de salida(preGain/postGain) y el parámetro WetMix, que controla la cantidad de señal original respecto a la señal con el efecto.
public static WaveShaper OD; public float[] WaveShape = {-1f, -0.75f, -0.5f, -0.25f, 0f, 0.25f, 0.5f, 0.75f, 1f}; ... OD = new WaveShaper(ac, WaveShape); OD.addInput(microphoneIn);
Para definir la función de transferencia, utilizamos un array de valores comprendidos entre -‐1 y 1. Este array será el que utilizaremos posteriormente para definir el objeto WaveShaper.
OD.setPreGain(5f); OD.setPostGain(8f);
Una vez inicializado el objeto Waveshaper, definimos los demás parámetros. En primer lugar definimos la ganancia de entrada o “preGain” mediante el método setPreGain(float).La ganancia de entrada se corresponde con el parámetro Drive, ya que cuanto mayor sea en nivel de la señal de entrada mayor será la saturación de la señal. Por otro lado definimos el parámetro postGain, el cual se corresponde con el parámetro Volume definido en el módulo Amp. Para implementar cada uno de los canales, modificamos el nivel de preGain máximo que puede alcanzar cada uno de ellos. En el caso del canal Overdrive el nivel máximo es de 4 y para el canal Distortion es de 25. En el caso del canal Clean, además de la ganancia tenemos que modificar el parámetro WetMix, ya que queremos la señal sin distorsión. Utilizamos el método setWetMix(0), para indicar que únicamente queremos escuchar la señal original.
Una vez tenemos definida la distorsión y los diversos canales, implementamos los filtros que componen el ecualizador. Beads nos permite implementar filtros de todo tipo mediante la función BiquadFilter, de la siguiente manera:
public static BiquadFilter filter_low; public static BiquadFilter filter_mid; public static BiquadFilter filter_high, filter_high2; ... filter_low = new BiquadFilter(ac, BiquadFilter.HP, 100.0f, 0.7f); filter_mid = new BiquadFilter(ac, BiquadFilter.NOTCH, 1500.0f, 0.7f); filter_high = new BiquadFilter(ac, BiquadFilter.LP, 4000.0f, 0.7f); filter_high2 = new BiquadFilter(ac, BiquadFilter.LP, 5000.0f, 0.7f);
85
Definimos un filtro de tipo pasa altos (HP) con frecuencia de corte en 100 Hz para el parámetro Low, un filtro de tipo rechaza banda (NOTCH) con frecuencia central de 1500 Hz para el parámetro Mid y un filtro de tipo pasa bajos (LP) con frecuencia de corte en 4000 Hz para el parámetro High. Además de la frecuencia de corte, la clase Biquadfilter nos permite definir el parámetro Q de cada filtro.
Después de realizar una serie de pruebas, se ha decidido añadir otro filtro pasa bajos con frecuencia de corte en 5000 Hz y así eliminar las frecuencias agudas sobrantes creadas por el efecto de distorsión.
Compressor Para definir el compresor, empezamos creando un objeto de la clase Compressor:
public static Compressor C;
Como en el caso anterior, debemos asignar a nuestro objeto Compressor el objeto de la clase AudioContext creado previamente:
C = new Compressor(ac);
Una vez inicializado el objeto Compressor, asignamos los valores iniciales de los parámetros configurables:
C.setAttack(30); C.setDecay(200); C.setRatio(4.0f); C.setThreshold(0.6f);
Por un lado tenemos los parámetros Attack y Release, los cuales se definen en milisegundos mediante los métodos setAttack(float attack) y setDecay(float decay) respectivamente. Por otro lado, el parámetro Ratio se define mediante un valor de tipo float que nos indicara la relación de compresión, en el ejemplo definimos un ratio de compresión de 4:1 mediante el valor 4.0. Por último el parámetro Threshold se define con un valor comprendido entre 0 y 1mediante la función setThreshold(float threshold).
Finalmente tenemos que realizar las conexiones de entrada/salida del módulo situándolo correctamente en la cadena de audio. En el caso del módulo Compressor la señal de entrada corresponderá a la señal de salida del módulo Amp, por lo que realizamos la conexión de la siguiente manera:
C.addInput(filter_high2);
Delay Beads nos permite definir el efecto de delay mediante las clases TapIn y TapOut, por lo que antes de empezar tenemos que crear un objeto de cada clase:
public static TapIn delayIn; public static TapOut delayOut;
La clase TapIn permite almacenar datos de audio en forma de pequeños fragmentos, de esta manera, podemos almacenar los fragmentos de audio que serán utilizados posteriormente para crear el efecto de delay. Para inicializar el objeto delayIn, tenemos que incluir nuestro
86
objeto AudioContext junto al tamaño máximo del buffer (en milisegundos) donde se almacenarán las muestras.
El tamaño máximo de buffer que definamos para nuestro objeto TapIn, corresponderá con el tiempo máximo de delay que podremos aplicar. Como indicábamos en el apartado de efectos, definimos el tiempo máximo de delay como 2000ms, por lo tanto definimos el objeto delayIn como:
delayIn = new TapIn(ac, 2000);
Por otro lado, tenemos la clase TapOut. La clase TapOut nos permite crear un efecto de delay utilizando un objeto de la clase TapIn. Definimos nuestro objeto TapOut mediante nuestro AudioContext, el objeto de la clase TapIn con el cual almacenamos los datos, el tipo de interpolación y el tiempo de delay inicial:
delayOut = new TapOut(ac, delayIn, TapOut.ALLPASS, (float) 100.0);
Beads nos permite definir diversos tipos de interpolación dentro de la clase TapOut. Al definir un efecto de delay digital, es necesario aplicar un proceso de interpolación entre las diversas muestras para evitar el denominado “zipper noise”[2.15]. El “zipper noise” es un tipo de ruido similar al producido por una distorsión y que puede producirse al modificar los parámetros de un efecto digital. Esto es debido a que los valores de los parámetros en un efecto digital, varian de forma escalonada y no de forma continua como sucede con los efectos analógicos [2.16].
Un vez definido nuestro objeto TapOut, podemos modificar el tiempo de delay mediante el método setDelay(float delay).
Para poder implementar el efecto de feedback delay, tenemos que definir un proceso de realimentación. El proceso de realimentación consiste en conectar la salida del efecto de delay con la entrada del mismo, de esta manera podemos crear un retardo sobre la señal ya retardada.
Utilizaremos un UGen del tipo Gain para crear el efecto de realimentación. La clase Gain, se trata de una clase de tipo UGen que nos permite modificar el nivel de ganancia para una señal de entrada. Definimos el objeto Gain de la siguiente manera:
public static Gain delayGain; ... delayGain = new Gain(ac, 1, 0.75f);
Dentro de la clase Gain, añadimos como parámetros el objeto AudioContext, el número de entradas y salidas y el nivel de ganancia inicial. Para implementar la realimentación de nuestro delay necesitamos que la ganancia sea un valor comprendido entre 0 y 0.99, ya que de esta manera las repeticiones del delay se atenuarán cada vez más, creando el efecto deseado. Modificando el nivel de ganancia del objeto variamos el parámetro denominado como feedback, ya que cuanto menor sea la ganancia, antes dejaremos de escuchar las repeticiones.
Finalmente, definimos la entrada del objeto delayGain utilizando el objeto delayOut, el cual contiene la señal con el retardo.
delayGain.addInput(delayOut);
87
Una vez creado el objeto delayGain, conectamos la salida del efecto a al entrada del mismo para crear la realimentación y con ello el efecto de feedback:
delayIn.addInput(delayOut);
En el caso del delay, debemos tener en cuenta si el módulo compresor está encendido o no para decidir que objeto UGen utilizamos como entrada, por lo tanto:
• Módulo Compressor Encendido -‐ delayIn.addInput(C); • Modulo Compressor Apagado -‐ delayIn.addInput(filter_high2);
Reverb Para definir el efecto de reverberación, empezamos creando un objeto de la clase Reverb:
public static Reverb R;
Una vez definimos el objeto de la clase Reverb, tenemos que inicializarlo pasándole el objeto de la clase AudioContext que hemos definido anteriormente y que contiene la información sobre la interfaz hardware y el formato de audio:
R = new Reverb(ac);
Hecho esto, damos los valores iniciales a los parámetros. En el caso de el efecto de reverb, configuramos el tamaño de la habitación o “room size” con el método setSize(float size).
R.setSize(0.5f);
El parámetro room size puede coger valores entre 0 y 1, por lo que lo inicializamos con el valor medio 0.5. Añadimos la letra f para especificar el valor como tipo float.
Finalmente, para definir el parámetro mix utilizaremos un UGen del tipo Gain. De esta forma podremos controlar el nivel de señal que llega al efecto, permitiéndonos controlar el volumen de éste.
public static Gain reverbGain; reverbGain = new Gain(ac, 1, 0.75f);
De la misma forma que en el caso del efecto de delay, creamos el objeto reverbGain utilizando como parámetros nuestro objeto AudioContext, el número de entradas y el nivel de ganancia inicial.
Por último, como en los casos anteriores realizamos las conexiones de entrada/salida mediante la función addInput(UGen). En el caso del módulo Reverb, debemos tener en cuenta si los módulos Compressor y Delay están encendidos, por lo que tenemos tres posibilidades:
• Módulo Delay Encendido reverbGain.addInput(delayGain);
• Módulo Delay Apagado/Módulo Compressor Encendido reverbGain.addInput(C);
88
• Módulo Delay Apagado/Módulo Compressor Apagado
reverbGain.addInput(filter_high2);
Envío de la señal procesada al sistema de escucha Una vez tenemos los efectos definidos e inicializados, ya podemos realizar la conexión con la interfaz de audio para enviar la señal procesada a los altavoces. Para enviar la señal procesada a los altavoces, utilizamos de nuevo el método addInput(UGen), pero esta vez debemos aplicarlo sobre el objeto AudioContext que contiene la información sobre la interfaz.
Cuando definimos el objeto AudioContext, definimos a su vez un Ugen llamado out. Beads declara este UGen como punto de salida para los demás UGens de la aplicación. Para realizar la conexión de salida, debemos tener en cuenta que cuando aplicamos un efecto que afecte al eje temporal de la señal (delay o reverberación) tenemos que enviar a la salida tanto la señal con el efecto como la señal original ya que si no solo escucharíamos la señal con el retardo.
Por lo tanto debemos establecer una lógica que nos permita controlar los UGens que enviamos a la salida en función de los módulos que tengamos activados. Empezamos por el final de la cadena, en caso de que el módulo Reverb esté encendido:
• Módulo Reverb Encendido/Módulo Compressor Encendido
ac.out.addInput(R);
ac.out.addInput(C);
• Módulo Reverb Encendido/Módulo Compressor Apagado
ac.out.addInput(R);
ac.out.addInput(filter_high2);
En caso de que el módulo Reverb esté apagado, comprobaremos el módulo de Delay:
• Módulo Delay Encendido/Módulo Compressor Encendido
ac.out.addInput(delayGain);
ac.out.addInput(C);
• Módulo Delay Encendido/Módulo Compressor Apagado
ac.out.addInput(delayGain);
ac.out.addInput(filter_high2);
Por último comprobamos el módulo Compressor:
• Módulo Compressor Encendido
ac.out.addInput(C);
• Módulo Compressor Apagado
ac.out.addInput(filter_high2);
89
En caso de que el módulo del efecto compresor esté apagado, enviaremos a los altavoces directamente la salida del módulo Amp, por lo que como mínimo tendremos siempre un módulo activo.
Debemos tener en cuenta que al apagar un modulo, tenemos que eliminar el UGen de éste de la cadena de audio general. Para eliminar un UGen de la cadena de audio utilizamos:
ac.out.removeConnection(0,UGen ,0); ac.out.removeConnection(1,UGen ,0);
Tenemos que utilizar el método removeConnection() dos veces, ya que éste solo nos permite eliminar un canal con cada definición.
4.4 Comunicación entre dispositivos Como se ha comentado a lo largo del proyecto, el dispositivo móvil (que actúa como cliente) se comunica con el ordenador (servidor) mediante el protocolo Wifi. En este caso explicaremos el funcionamiento tanto del cliente como del servidor por separado.
Para realizar la conexión con el servidor desde el terminal Android se base en una clase que llamamos ClienteSocket, ésta extiende de la clase Socket [1.20] perteneciente al paquete de Java. Utilizamos la herencia de las clases para aprovechar los métodos de conexión (de la clase padre Socket) con el servidor, además se implementa una función para poder enviar mensajes.
El formato del mensaje es muy sencillo, aquí podemos ver un ejemplo:
Este mensaje en concreto se crea cuando cambiamos el valor del parámetro X del efecto Y. Vemos como los distintos caracteres o valores del mensaje están separados por un símbolo de punto y coma (;), esto nos permite facilitar la función de parseo (interpretación del texto para crear una estructura de datos para ser usada en un programa) en el servidor.
El primer valor que nos encontramos es el identificador del efecto, cada uno tiene un número asociado a él.
Después nos encontramos con el identificador del parámetro del efecto, como en el caso anterior cada parámetro tiene un número asociado.
Por último, tenemos el valor del parámetro a actualizar.
Una vez este mensaje llegue al servidor, éste tiene que verificar cada uno de estos valores para determinar que hay que modificar. Esta función la realiza por partes, en el orden del mensaje,
90
es decir, primero identifica el efecto, después el parámetro y por ultimo le asigna el valor que se encuentra al final del mensaje.
En la función anterior se determina el efecto que se debe cambiar. La función para conocer el parámetro del efecto es muy parecida.
En el código anterior vemos como determina el parámetro y asigna el valor.
Ahora bien, cuando cargamos un preset en la aplicación, se envía la información de todos los efectos (valores de sus parámetros). Al enviar todos los valores de cada preset no hace falta un identificador para cada efecto ni de parámetro ya que se enviarán los distintos valores en orden. Así en el servidor solo leerá los valores y sabiendo el orden en que se envían solo tiene que actualizar los parámetros.
En la sección de anexos se encuentran las tablas con los distintos identificadores para cada efecto y parámetro.
91
5 Conclusiones Fijándonos en los objetivos generales planteados en el inicio de esta memoria, podemos afirmar que se han cumplido de forma satisfactoria. Hemos conseguido implementar dos aplicaciones para distintas plataformas y que además interactúan entre ellas mediante una conexión sin cables, en este caso mediante el protocolo de comunicación wireless Wifi.
Se ha conseguido desarrollar una aplicación para ordenador que permite aplicar efectos en tiempo real utilizando una estructura de módulos encadenados. Además se ha conseguido que la aplicación funcione independientemente, sin necesidad de un dispositivo móvil conectado.
Por último se ha logrado implementar la importación y exportación de los presets en ambas aplicaciones, incluyendo la compatibilidad de archivos entre ellas.
Por otro lado, consideramos que gracias a este proyecto hemos incrementado nuestros conocimientos tanto los relacionados con el procesado de audio, como con la programación en lenguaje Java. Además hemos ampliado nuestro conocimiento sobre el funcionamiento de una comunicación Wireless usando el protocolo Wifi.
5.1 Mejoras A parte de los objetivos definidos al inicio del proyecto, durante el desarrollo de la aplicación han ido surgiendo ideas y mejoras para ambas aplicaciones. Además a lo largo del desarrollo nos hemos encontrado con distintos problemas y errores, la mayoría se han solucionado con relativa facilidad.
Las primeras posibles mejoras a realizar en el proyecto serían los objetivos que no se han llegado a cumplir.
Por lo que respecta a la aplicación Android, las mejoras más importantes y con más prioridad serian: la compatibilidad con tablets (diseñar una interfaz adaptada a la pantalla de las tablets), la compartición de archivos mediante tecnología en la nube o también integración de la aplicación en las redes sociales (poder compartir presets por Internet).
En el caso de la aplicación de PC, las mejoras posibles serían, por orden de prioridad: el uso de knobs (sliders personalizados) incluidos en la imagen de cada pedal de efecto, la simulación de la respuesta impulsional de un altavoz de guitarra (utilizando una respuesta impulsional real) y la extensión de la cadena de efectos.
92
6 Bibliografía y referencias [1.1].Android Studio. Android Developer. https://developer.android.com/sdk/index.html [1.2].Wifi vs Bluetooth. ADSL Zone. http://www.adslzone.net/2014/11/27/wifi-‐vs-‐bluetooth-‐diferencias-‐ventajas-‐e-‐inconvenientes/ [1.3].Bluetooth. Wikipedia. http://en.wikipedia.org/wiki/Bluetooth [1.4].Wifi. Wikipedia. http://en.wikipedia.org/wiki/Wi-‐Fi [1.5].Sistema Operativo Móvil. Wikipedia. http://es.wikipedia.org/wiki/Sistema_operativo_m%C3%B3vil [1.6]. Comparativa sistemas operativos móviles. Wikipedia. http://en.wikipedia.org/wiki/Comparison_of_mobile_operating_systems [1.7]. iOS. Wikipedia. http://es.wikipedia.org/wiki/IOS [1.8]. Windows Phone. Wikipedia. http://es.wikipedia.org/wiki/Windows_Phone [1.9]. Android. Wikipedia. http://es.wikipedia.org/wiki/Android [1.10]. StackOverflow. http://stackoverflow.com/ [1.11] Motorola MotoG. Amazon. http://www.amazon.es/Motorola-‐Moto-‐GB-‐Smartphone-‐Quad-‐Core/dp/B00GOYN5TE [1.12]. HP – G62. HP. http://support.hp.com/es-‐es/document/c02063900 [1.13]. Router. Wikipedia http://es.wikipedia.org/wiki/Router [1.14]. Modelo-‐Vista-‐Controlador. Wikipedia. http://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador [1.15]. Activity. Android Developers. http://developer.android.com/reference/android/app/Activity.html [1.16] Layouts. Android Developers. http://developer.android.com/guide/topics/ui/declaring-‐layout.html
93
[1.17]. Fragments. Android Developers. http://developer.android.com/guide/components/fragments.html [1.18].Adapter. Android Developers https://developer.android.com/reference/android/widget/Adapter.html [1.19].Shared Preferences. Android Developers. http://developer.android.com/reference/android/content/SharedPreferences.html [1.20]. Socket. Android Developers. http://developer.android.com/reference/java/net/Socket.html [2.1]. MacBook Pro Specifications https://support.apple.com/kb/SP619?locale=es_ES [2.2]. The Beads Project http://www.beadsproject.net [2.3]. JavaDocs. The Beads Project http://www.beadsproject.net/doc/ [2.4].Sonifying Processing: The Beads Tutorial. Evan Merz http://computermusicblog.com/blog/sonifyingprocessing/ [2.5]. Beads Discussion Group. Google Groups https://groups.google.com/forum/?hl=en#!forum/beadsproject [2.6]. Latencia Mínima. Musicador http://www.musicador.com/la-‐latencia-‐de-‐audio-‐en-‐los-‐ordenadores-‐parte-‐2/ [2.7]. Loudspeaker Specifications. Celestion http://celestion.com/category/4/Guitar/size/25/12%22Diameter/ [2.8]. Orden Pedales. Pedalesdeguitarra. http://pedalesdeguitarra.com/orden-‐de-‐los-‐pedales-‐la-‐guia-‐definitiva/ [2.9]. FadeIn Class. StackOverflow. http://stackoverflow.com/questions/20346661/java-‐fade-‐in-‐and-‐out-‐of-‐images [2.10]. Swing. Oracle Docs http://docs.oracle.com/javase/7/docs/api/javax/swing/package-‐summary.html [2.11]. Used Ports Class. StackOverflow. http://codereview.stackexchange.com/questions/31557/checking-‐if-‐a-‐port-‐is-‐in-‐use [2.12]. GetIp Class. StackOverflow. http://stackoverflow.com/questions/9481865/getting-‐the-‐ip-‐address-‐of-‐the-‐current-‐machine-‐using-‐java [2.13]. WaveShaper. Wikipedia. http://en.wikipedia.org/wiki/Waveshaper
94
[2.14]. WaveShaping. Columbia Music. http://music.columbia.edu/cmc/musicandcomputers/chapter4/04_06.php [2.15]. Delay Line Interpolation. Stanford University. https://ccrma.stanford.edu/~jos/pasp/Delay_Line_Interpolation.html [2.16]. Zipper Noise. SweetWater. http://www.sweetwater.com/insync/zipper-‐noise/]
95
7 Anexos Para no saturar la memoria del proyecto se ha decidido subir el código completo a la plataforma GitHub.
Se puede acceder mediante el siguiente enlace:
https://github.com/GuitarEffectsChain
Base de datos Android.
La base datos del terminal Android se compone de tres tablas.
Tabla: COMS Función: Almacena los datos de la última conexión. Además de un campo para habilitar el tutorial de la aplicación la primera vez que se inicia. Campo Tipo Descripción ID Numero Identificador, no usado. IP Texto Dirección IP del último servidor al que se ha conectado. PUERTO Texto Puerto del último servidor al que se ha conectado. TUTO Numero Activa el tutorial solo la primera vez que se ejecuta la aplicación.
Tabla: EFECTOS Función: Almacena información sobre los efectos que se utilizan. Campo Tipo Descripción ID Numero Identificador, no usado. NOMBRE_EFECTO Texto Nombre del efecto. DESCRIPCION Texto Descripción del efecto.
Tabla: PRESETS
Función: Almacena las distintas configuraciones de los efectos. Campo Tipo Descripción ID Numero Identificador del preset. NAME Texto Nombre del preset. AMP_GAIN Numero Valor ganancia del amplificador. AMP_BASS Numero Valor graves del amplificador AMP_MID Numero Valor medios del amplificador AMP_TREBLE Numero Valor agudos del amplificador AMP_VOLUME Numero Valor volumen del amplificador AMP_CHANNEL Numero Identificador canal usado en el amplificador. COMP_ONOFF Numero Interruptor encendido/apagado. COMP_ATTACK Numero Valor ataque del compresor. COMP_DECAY Numero Valor decay del compresor. COMP_RATIO Numero Valor ratio del compresor. COMP_THRESHOLD Numero Valor umbral del compresor.
96
DELAY_ONOFF Numero Interruptor encendido/apagado. DELAY_TIME Numero Valor tiempo del delay. DELAY_FEEDBACK Numero Valor feedback del compresor. DELAY_MIX Numero Valor mix del delay. REVERB_ONOFF Numero Interruptor encendido/apagado. REVERB_SIZE Numero Valor size del reverb. REVERB_MIX Numero Valor mix del reverb.
Identificadores efectos y parámetros.
Cada efecto y parámetro de éstos tiene asociado un identificador para poder interpretar el mensaje en el servidor, a continuación se muestran una tabla resumiendo los identificadores utilizados.
Identificador Efecto
Efecto
Identificador Parámetro
Parámetro
1
Amplificador
1 Drive
2 Graves
3 Medios
4 Agudos
5 Volumen
6 Canal
2
Compresor
1 Attack
2 Decay
3 Ratio
4 Threshold
5 On/Off
3
Delay
1 Time
2 FeedBack
3 Mix
4 On/Off
4
Reverb
1 Size
2 Mix
3 On/Off