71
La ventana de diálogo tiene el aspecto siguiente:
Tabla 39 – Ventana de test de la interfaz de usuario
La señal de test es enviada constantemente mientras la ventana de diálogo siga abierta, bajo la configuración actual.
4.3.1.5.
ANALIZAR GRÁFICAMENTE LOS CANALES DE ENTRADA Y
SALIDA
Con objeto de analizar en detalle el procesado realizado, se ofrece un analizador de la señal que muestre todos los canales de salida y entrada por separado y los representa comparándolos entre ellos tanto en señal en el tiempo como en espectro en frecuencia. El gráfico representa en ambos campos un trozo de señal correspondiente a la ventana temporal seleccionada a través del parámetro Time scope que establece el periodo de la ventana y el cursor de la ventana que selecciona el instante temporal de la primera muestra de la ventana.
72
4.3.1.6.
CODIFICAR UN ARCHIVO DE AUDIO
La interfaz de usuario ofrece la posibilidad de codificar un archivo de audio sin compresión, esto es, un archivo en formato wave. Una vez codificado el archivo puede ser utilizado como archivo fuente del decodificador en la ventana principal. Para cargar un archivo de fuente como un archivo salida del codificador hay que hacer click en Source Load from encoder. Tras esto aparecerá la ventana de diálogo del codificador, que permitirá cargar un archivo en bruto, configurar el codificador y aplicar la codificación en ese orden. La ventana tiene la siguiente estructura:
Figura 39 – Ventana de codificador de la interfaz de usuario
Campo Descripción
Open Selecciona el archivo de audio de entrada del codificador
Bitstream
Indica el nombre del archivo bitstream que será creado (la ruta de la carpeta donde será creado siempre coincidirá con la ruta de la carpeta del archivo de entrada)
Buried Si se encuentra marcado, el bitstream será superpuesto en el archivo de salida
del codificador, y no será necesario crear archivo bitstream
Tree config Selecciona la configuración del árbol del codificador (véase Tabla 13)
Reset Restablece la configuración del codificador a los valores por defecto
Apply Aplica el codificador y crea el archivo de audio de salida
Cancel Cierra la ventana sin establecer el nuevo archivo de salida del codificador como
archivo fuente del decodificador
OK Cierra la ventana estableciendo el nuevo archivo de salida del codificador como
archivo fuente del decodificador
73
4.3.1.7.
BARRA DE MENÚ DE LA INTERFAZ DE USUARIO
Figura 40 – Barra de opciones de la ventana principal de la interfaz de usuario
Barra de menú
Source
Load from file Load from
encoder
Bitstream
Load from file
Buried Decoder Upmix type Normal Blind Binaural Stereo Decoding type Low High Binaural upmix quality Parametric Filtering HRTF mode Kemar Vast MPS VT Input Decode source Show channels chart Effect Lista de efectos disponibles
Output Export as file Show channels chart Test audio device
74
4.3.2.
APLICACIÓN EJECUTABLE VÍA LÍNEA DE COMANDOS
Esta versión debe ser usada a través de la línea de comandos del sistema. El uso de los argumentos de la aplicación, explicados en la tabla de abajo, se imprime por pantalla mediante el argumento de muestra de ayuda –h o siempre que se usen incorrectamente los argumentos.
Argumento Descripción
-s Ruta/Archivo.wav Ruta del archivo de audio SAC codificado que servirá de entrada en la aplicación
-bs
Ruta/Archivo.bs Ruta del archivo de bitstream de SAC asociado al archivo de audio SAC que servirá de entrada en la aplicación
buried
Si el flujo bitstream está incluido en el archivo de entrada con configuración buried en la codificación (valor por defecto si no se indica este argumento)
-ds Ruta/Archivo.wav Ruta del archivo de audio SAC decodificado sin efectos aplicados que será creado por la aplicación
-o Ruta/Archivo.wav Ruta del archivo de audio SAC decodificado tras los efectos que será creado por la aplicación como salida de la misma
-ut
0 Parámetro de decodificación upmix type con valor normal (valor por defecto si no se indica este argumento)
1 Parámetro de decodificación upmix type con valor blind
2 Parámetro de decodificación upmix type con valor binaural
3 Parámetro de decodificación upmix type con valor stereo
-dt 0
Parámetro de decodificación decoding type con valor low
(valor por defecto si no se indica este argumento)
1 Parámetro de decodificación decoding type con valor high
-bq
0 Parámetro de decodificación binaural quality con valor
parametric (valor por defecto si no se indica este argumento)
1 Parámetro de decodificación binaural quality con valor
filtering
-hm
0 Parámetro de decodificación HRTF model con valor kemar (valor por defecto si no se indica este argumento)
1 Parámetro de decodificación HRTF model con valor vast
2 Parámetro de decodificación HRTF model con valor MPS VT
-fx Ruta/Archivo.fx Ruta del archivo de configuración del efecto
75
El ejemplo siguiente se ejecutaría en la terminal desde el directorio donde se encuentra la aplicación, y conteniendo el subdirectorio Folder donde se encuentran los archivos de audio de entrada, bitstream y configuración del efecto.
./saceffects -s Folder/source.wav -bs Folder/bitstream.bs -ds
Folder/input.wav -o Folder/output.wav -dt 1 -ut 3 -hm 0 -fx Folder/effects.fx
Fragmento de código 16 – Ejemplo de ejecución de la aplicación ejecutable vía línea de comandos
4.3.2.1.
ARCHIVO DE CONFIGURACIÓN DEL EFECTO
Para facilitar el uso de la aplicación por línea de comandos, los parámetros del efecto se introducen mediante un archivo XML guardado con extensión personalizada *.fx. El archivo indica la configuración del efecto mediante las siguientes etiquetas:
Etiqueta Descripción Formato
<effect> Nombre del efecto a aplicar
Se indica simplemente el nombre del efecto sin comillas, incluyendo cualquier carácter o espacio.
<channels>
Canales
seleccionados para aplicar el efecto
Cada canal se referencia como ch seguido del índice del canal (comenzando por 0). El valor del canal es indicado tras un signo = después de la referencia del canal. La sentencia finaliza con el signo ;. El valor booleano true se puede escribir como true, True, TRUE ó 1. El resto de valores indican un valor false. Si no se incluye la sentencia de un canal existente, dicho canal tiene valor false por defecto.
<levels>
Nivel de señal de entrada de cada uno de los canales antes del efecto
Cada canal se referencia como ch seguido del índice del canal (comenzando por 0). El valor del canal es indicado tras un signo = después de la referencia del canal. La sentencia finaliza con el signo ;. Si no se incluye la sentencia de un canal existente, dicho canal tiene valor 1 por defecto.
<params>
Valor de los parámetros del efecto
Cada parámetro se referencia con el nombre del parámetro, y su valor es indicado tras un signo = después de la referencia del parámetro. La sentencia finaliza con el signo ;. Existen 5 tipos de valores de parámetros (véase Descripción del control de interfaz de usuario):
Los dos tipos numéricos (int y double) son indicados de forma simple con números y punto decimal en el caso del último.
El tipo string se envuelve entre dobles comillas (“valor”).
El tipo bool debe ser igual a true, True, TRUE ó 1 para un valor true y cualquier otro valor para false.
76 A continuación, se muestra un ejemplo de archivo de configuración de efecto:
<effect>Compressor</effect> <channels> ch0 = true; ch1 = true; ch2 = false; ch3 = false; ch4 = false; ch5 = false; </channels> <levels> ch0 = 1; ch1 = 0.75; ch2 = 0; ch3 = -0.5; ch4 = -1; ch5 = 2; </levels> <params> level = 0.5;
string = Cadena de caracteres; bool = true;
</params>
Fragmento de código 17 – Ejemplo de archivo de configuración de efecto
Los parámetros de los efectos implementados se resumen en la siguiente tabla. Sin embargo, se recomienda revisar las tablas de parámetros de cada efecto, donde se muestran en más detalle.
Efecto Parámetro Tipo Breve descripción
Compresor (Tabla 17)
threshold double Umbral de potencia de entrada
ratio double Pendiente de la ganancia
type enum Tipo downward o upward
function enum Efecto de compression o expansion
Ecualizador
(Tabla 19) bandx double Nivel de la banda x (de 0 a 9)
Reverb (Tabla 20)
phase double Nivel de variación de fase
roomsize double Nivel de los ecos tardíos
damping double Nivel de caída de los ecos con las altas frecuencias
method enum Efecto de reverb JCRev o freeverb
Panorama
(Tabla 30) x2x double
Nivel de la componente de señal proveniente del canal de entrada x hacia el canal de salida x
77
4.3.2.2.
MENSAJES DE CONSOLA
La aplicación devuelve por consola una serie de mensajes que dan información acerca del proceso que se está llevando a cabo. Estos mensajes están estandarizados según la función consolelog(). Las tabulaciones del mensaje están adaptadas para coincidir en número de espacios a las tabulaciones de la terminal de Linux. El formato que siguen los mensajes de consola es:
Figura 41 – Formato de mensaje de consola
El origen del mensaje suele señalar la clase desde donde se originó el mensaje o la clase a la cual se refiere el propio mensaje. El campo que indica el tipo de mensaje puede tener cualquiera de los siguientes valores descritos en la tabla:
Tipo Fuente Descripción
info Azul El mensaje contiene información a tener en cuenta por el usuario de carácter informativo
warning Amarillo El mensaje informa de una advertencia en el proceso
error Rojo El mensaje informa de un error en el proceso progress Verde El mensaje informa del estado del proceso actual
interaction Magenta El mensaje informa de una interacción que ha realizado el
usuario (sólo para la aplicación con interfaz de usuario) general Cian Mensaje de tipo general
78
4.4.
GUÍA DE IMPLEMENTACIÓN DE NUEVOS EFECTOS
Para futuras implementaciones de nuevos efectos, se ha definido un entorno que facilite la inclusión de estos en la aplicación, acorde con el Objetivo de proyecto 3. En este apartado se explica algunos detalles para tener en cuenta a la hora de crear nuevos efectos.
El nuevo efecto debe ser escrito en una clase C++ (referida a partir de ahora como ClaseEfecto), por lo que comprenderá dos archivos, un archivo de código fuente .cpp y un archivo de cabecera .h (mencionados de aquí en adelante como ArchivoEfecto.h y ArchivoEfecto.cpp). La definición de la clase del efecto se realiza con la siguiente sentencia escrita en el archivo de cabecera:
class ClaseEfecto AS_EFFECT {
}
Fragmento de código 18 – Declaración de la clase de los nuevos efectos
La clase del efecto debe de disponer de un constructor de clase, siguiendo el formato:
class ClaseEfecto AS_EFFECT {
public:
ClaseEfecto();
}
Fragmento de código 19 – Cabecera del constructor de los nuevos efectos
ClaseEfecto::ClaseEfecto() AS_EFFECT_CONSTRUCTOR {
}
Fragmento de código 20 – Código fuente del constructor de los nuevos efectos
Además, para incluir algunas funcionalidades predefinidas para los efectos, hay que incluir los archivos de la clase EffectBase de la siguiente manera:
// Effect base header #include "EffectBase.h"
Fragmento de código 21 – Inclusión de la clase EffectBase de los nuevos efectos
La aplicación de los efectos es llamada a través de la función apply. Es por esto por lo que hay que declarar e implementar una función con el siguiente aspecto:
class ClaseEfecto AS_EFFECT {
public:
ClaseEfecto();
void apply(float **input, float **output, int samples, std::vector<SACBitstream::ChannelType::channeltype> channels);
}
Fragmento de código 22 – Cabecera de la función para aplicar el efecto de los nuevos efectos
void ClaseEfecto::apply(float **input, float **output, int samples,
std::vector<SACBitstream::ChannelType::channeltype> channels) { }
79
Por último, como se explica en el apartado de Etiquetas de representación, se da la posibilidad de representar una gráfica de valores en la interfaz de usuario. Los valores, asignados en la clase del efecto, son devueltos a la interfaz mediante la función plot. Al igual que la función anterior, hay que implementarla siguiendo un determinado formato. Esta función es opcional si se da el caso en que no se haya indicado ninguna representación de tipo gráfica en la Descripción del control de interfaz de usuario.
class ClaseEfecto AS_EFFECT {
public:
ClaseEfecto();
void apply(float **input, float **output, int samples, std::vector<SACBitstream::ChannelType::channeltype> channels);
std::vector<std::vector<double> > plot(std::string chart); }
Fragmento de código 24 – Cabecera de la función para asignar valores a las gráficas de los nuevos efectos
std::vector<std::vector<double>> Compressor::plot(std::string chart) { }
Fragmento de código 25 – Código fuente de la función para asignar valores a las gráficas de los nuevos efectos
El argumento de la función chart hace referencia al campo id del gráfico al que se solicita su presentación (véase Tabla 50). La función debe devolver un vector de dos dimensiones, siendo la primera dimensión el eje del valor (horizontal o vertical) y la segunda el índice del par de valores.
const int N; // número total de pares de valores de la gráfica
std::vector<std::vector<double>> values = std::vector<std:.vector<double>>(2, std:.vector<double>(N));
values[0][n] = x; // valor x del par de valores n values[1][n] = y; // valor y del par de valores n
Fragmento de código 26 – Variable a devolver en la función para asignar valores a las gráficas de los nuevos efectos
Las siguientes variables ya se encuentran definidas en los efectos creados (no es necesario declararlas ni gestionarlas) por lo que pueden ser usadas. Como es obvio, no se debe crear variables con el mismo nombre que estas.
Variable Tipo Uso
effect
std::pair
<Effect::effectID, std::string>
Contiene el identificador y el nombre del efecto seleccionado
fs int Indica la frecuencia de muestreo de la señal
params std::map<std::stri
ng, std::string>
Contiene un mapa nombre-valor de los parámetros seleccionados por el usuario
Tabla 45 – Variables restringidas en la implementación de nuevos efectos
La siguiente sentencia recupera el valor actual en formato de cadena de caracteres del parámetro con identificador “paramID” en este caso:
std::string value = params[“paramID”]
80 También existe una lista de funciones predefinidas. Algunas de ellas han sido creadas para facilitar el desarrollo del efecto.
Función Tipo Uso
apply bool Función necesaria para el efecto
plot std::vector<std::vector<double>> Función necesaria para el efecto
getEffects
std::map
<Effect::effectID,
std::string> No se recomienda su uso
getEffect Effect::effectID No se recomienda su uso
setParams void No se recomienda su uso
getParams std::map<std::stri
ng, std::string> No se recomienda su uso getChannels std::vector<bool> No se recomienda su uso getLevels std::vector<double> No se recomienda su uso
getTag std::string No se recomienda su uso
getTagMap std::map<std::string, std::string> No se recomienda su uso
getInt int Puede ser usada por los efectos (véase Tabla 53)
getDouble double Puede ser usada por los efectos (véase Tabla 53)
getString std::string Puede ser usada por los efectos (véase Tabla 53)
getBool bool Puede ser usada por los efectos (véase Tabla 53)
Tabla 46 – Funciones restringidas en la implementación de nuevos efectos
Las cuatro últimas funciones anteriores han sido creadas para obtener en el formato adecuado el valor de los parámetros del efecto.
int integer = getInt(params[“integerparam”]); double real = getDouble(params[“realparam”]); std::string text = getString(params[“textparam”]); bool booelan = getBool(params[“booelanparam”]);
81
4.4.1.
INCLUSIÓN DEL EFECTO
Siempre que se incluya nuevos efectos se es necesario configurar el programa para que recompile incluyendo los nuevos efectos. La compilación de la aplicación por línea de comandos se realiza mediante un programa de configuración que configura el Makefile encargado de compilar. En el caso de la aplicación que incluye interfaz la compilación únicamente puede configurarse y realizarse a través de Qt Creator.
En los siguientes subapartados se explican detalladamente todos los pasos en los dos casos. Se debe tener en cuenta que ArchivoEfecto equivale al nombre del archivo .h y .cpp del nuevo efecto creado, y ClaseEfecto equivale al nombre de la clase del nuevo efecto creado (se sugiere que ambos coincidan).
4.4.1.1.
APLICACIÓN CON INTERFAZ DE USUARIO
Para compilar la interfaz de usuario es necesario descargar Qt Creator y las librerías Qt en https://info.qt.io/download-qt-for-application-development. Los pasos para importar el nuevo efecto implementado correctamente son:
1. Copiar el archivo de código fuente (.cpp) a src/effects/ 2. Copiar el archivo de cabecera (.h) a src/effects/
3. Copiar el archivo de Descripción del control de interfaz de usuario (.xml) a src/interface/effects/
4. Abrir el proyecto de la aplicación (interface.pro) con Qt Creator y configurar el proyecto si es necesario
5. En la aplicación Qt Creator añadir los tres archivos copiados al proyecto haciendo click con el botón secundario sobre la carpeta del proyecto y eligiendo la opción de añadir nuevos archivos
Figura 42 – Importación de los archivos de nuevo efecto en el proyecto
6. En la aplicación Qt Creator añadir el archivo anterior de descripción del control de interfaz de usuario (copiado en el paso 3) a media.qrc haciendo click sobre el propio archivo media.qrc, eligiendo la opción abrir con el editor, seleccionando la carpeta del prefijo /imports y haciendo click sobre añadir y añadir archivos.
82
Figura 43 – Importación del archivo de descripción del control de interfaz de usuario
7. En el archivo src/effects/Effect.h añadir la línea
#include “ArchivoEfecto.h”
según la descripción 1. FILES
8. En el archivo src/effects/Effect.h añadir la línea EFFECT(ClaseEfecto, “ClaseEfecto”)
según la descripción 2. LIST (hay que tener especial cuidado en añadir el símbolo ”/“ al final de cada línea de efecto añadido siempre que no sea la última línea para continuar con la definición de la variable de macros)
9. En el archivo src/effects/Effect.h añadir la línea
public ClaseEfecto
según la descripción 3. INHERITANCE OF CLASSES (hay que tener especial cuidado en añadir el símbolo “, /“ al final de cada línea de efecto añadido siempre que no sea la última línea para continuar con la definición de la variable de macros) 10. En la función Effect::apply dentro del archivo src/effects/Effect.cpp
añadir las líneas
case effectID::ClaseEfecto:
ClaseEfecto::apply(input, output, samples, channels);
break;
dentro de la sentencia switch-case de la función
11. En la función Effect::plot dentro del archivo src/effects/Effect.cpp añadir las líneas
case effectID::ClaseEfecto:
return ClaseEfecto::plot(chart);
dentro de la sentencia switch-case de la función 12. Compilar la aplicación a través de Qt Creator
83
4.4.1.2.
APLICACIÓN EJECUTABLE VÍA LÍNEA DE COMANDOS
1. Copiar el archivo de código fuente (.cpp) a src/effects/2. Copiar el archivo de cabecera (.h) a src/effects/ 3. En el archivo src/effects/Effect.h añadir la línea
#include “ArchivoEfecto.h”
según la descripción 1. FILES
4. En el archivo src/effects/Effect.h añadir la línea EFFECT(ClaseEfecto, “ClaseEfecto”)
según la descripción 2. LIST (hay que tener especial cuidado en añadir el símbolo