Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Tribunal calificador:
a
1. Resumen: Estudio sobre el panorama actual del desarrollo de aplicaciones de audio de alto
rendimiento en entornos multiplataforma escritos en lenguaje C++. Abordado desde la
perspectiva terica de los fundamentos fsicos del sonido, la tecnologa electrnica, los
sintetizadores musicales, software libre para el desarrollo de aplicaciones y enfoque terico y
prctico sobre los principios del tratamiento digital de seales.
4. Traduccin del resumen: Study on currently available multi-platform libraries in C++ for
high-performance audio application development. Theoretical approach to the physics of sound,
audio synthesizer hardware, open-source software for audio applications and signal processing
principles.
6. ndice
1. Resumen...........................................................................................................................
6. ndice................................................................................................................................
7. Listas de figuras...............................................................................................................
8. Cuerpo..............................................................................................................................
8.1.1
Contexto........................................................................................................
8.1.2
Trabajos anteriores........................................................................................
8.1.3
Aportaciones y conclusiones.........................................................................
10
8.2.1
Contexto........................................................................................................
10
8.2.2
11
8.2.3
Trabajos anteriores........................................................................................ 12
8.2.4
Aportaciones y conclusiones.........................................................................
12
12
8.3.1
Contexto........................................................................................................
12
8.3.2
13
8.3.3
Trabajos anteriores........................................................................................ 13
8.3.4
Aportaciones y conclusiones.........................................................................
13
14
8.4.1
Contexto......................................................................................................... 14
8.4.2
Trabajos anteriores........................................................................................ 15
8.4.3
Aportaciones y conclusiones.........................................................................
15
16
8.5.1
Contexto......................................................................................................... 16
8.5.2
17
8.5.3
Trabajos anteriores........................................................................................ 18
8.5.4
Aportaciones y conclusiones.........................................................................
18
18
8.6.1
Contexto........................................................................................................
18
8.6.2
19
8.6.3
Aportaciones y conclusiones.........................................................................
20
20
8.7.1
Contexto........................................................................................................
20
8.7.2
22
8.7.3
Trabajos anteriores........................................................................................ 22
8.7.4
Aportaciones y conclusiones.........................................................................
22
23
28
11. Anexos.............................................................................................................................
29
7. Listas de figuras
Figura 8.1 Umbrales de tolerancia al sonido......................................................................
10
11
14
17
8. Cuerpo
8.1 Captulo 1
8.1.1 Contexto
En este captulo se abordan varios conceptos de la teora bsica del sonido. Se
comienza introduciendo al lector en los conceptos de generacin de la onda y
cmo sta es transmitida por el espacio. Para explicar estos conceptos se
exponen diversos ejemplos ilustrativos. Posteriormente, se aborda en el
captulo los tipos de onda que se dan en la naturaleza.
Otro aspecto que se aborda en este captulo son los conceptos de las
magnitudes de la onda: periodo, longitud de onda, frecuencia y amplitud,
aspectos stos fundamentales en la fsica de la onda. Tan importante como los
conceptos de magnitudes es la ecuacin matemtica que describe la onda, de
la cual se realiza un desarrollo terico.
A continuacin se explica uno de los conceptos fundamentales que sern de
gran utilidad para poder seguir el tratado y que son de importancia relevante en
el captulo 7 de Tratamiento Digital de Seales. Estos son la representacin de
la seal en el dominio del tiempo y en el dominio de la frecuencia. Dentro de
este apartado tambin se realiza una introduccin al concepto de espectro.
Se explica tambin en este captulo el Teorema de Fourier que demuestra que
cualquier funcin peridica continua, con un nmero finito de mximos y
mnimos, puede desarrollarse en una serie trigonomtrica uniformemente
convergente, llamada serie de Fourier.
Las conceptos de ondas armnicas y el ruido con sus respectivas
representaciones en el dominio y en la frecuencia son un tema tambin tratado
en este captulo.
Posteriormente se pasa a introducir la teora de la propagacin del sonido a
travs de diferentes medios fsicos y sus caractersticas. Se describen las
velocidades que alcanza el sonido en el agua, la madera y el acero.
En el tercer apartado del primer punto del captulo se menciona, sin llegar a lo
exhaustivo, el funcionamiento del odo humano, sus principales rganos
componentes y cmo se relacionan estos con el cerebro para producir la
sensacin acstica. Por tanto, se explican cada una de estas partes que son: el
odo externo, el odo medio y el odo interno. Como ejemplo ilustrativo se
expone un diagrama de bloques que relaciona cada parte del odo con un
sistema digital de audio.
Dentro de este apartado se definen a grandes rasgos las principales cualidades
del sonido que son: intensidad, tono, timbre y duracin.
Es conocido por todos el rango de frecuencias que abarca el espectro audible,
esto es, un rango que va desde los 20 a los 20000 Hz. Como ejemplo prctico
se representa mediante una tabla los diferentes rangos de frecuencia de las
diferentes octavas musicales.
Se incluye en este apartado un grfico con los umbrales de la tolerancia
humana de los sonidos en decibelios; como se muestra en la siguiente figura:
8.2 Captulo 2
8.2.1 Contexto
Este captulo se centra principalmente en la programacin en DirectX con
Visual C++ para la generacin de audio con DirectSound.
El captulo comienza con una introduccin a la filosofa de DirectX, desarrollada
principalmente para los juegos en plataformas Windows que siempre han
necesitado de altas prestaciones. Se explica conjuntamente la arquitectura de
DirectX que es esencialmente una arquitectura software por capas, como se
muestra en la figura 8.5:
DirectX
HAL
HEL
Hardware
10
Archivos de sonido
11
8.3 Captulo 3
8.3.1 Contexto
En este captulo se aborda la programacin en la librera OpenAL. Esta librera
es una versin multiplataforma de DirectSound de la compaa Creative Labs.
Para iniciar el captulo se introduce al lector en la arquitectura de OpenAL,
mucho ms sencilla y directa que la de su homlogo DirectX.
Una vez explicado el funcionamiento de la arquitectura, se comienza a exponer
al lector los fundamentos bsicos para la programacin en OpenAL. Para ello
se ha dividido el apartado en las siguientes secciones a fin de seguir una
metodologa ms pedaggica. Los apartados sobre la programacin OpenAL
son los siguientes:
Inicializacin
12
Reproduccin de sonido
Posicionamiento 3D
Salida de la aplicacin
Gestin de errores
de
alto
rendimiento
y muy utilizada
actualmente
en
13
8.4 Captulo 4
8.4.1 Contexto
En este captulo sobre tecnologa MIDI se exponen todos los aspectos tericos
sobre la interfaz para la interconexin de instrumentos musicales digitales.
En el principio del captulo se presenta al lector en una breve historia de MIDI,
as como el origen y la concepcin de este sistema innovador que sigue
perdurando en la actualidad.
14
mensajes midi. Para ello se explican los fundamentos de los canales MIDI y los
mensajes de canal: note on, note off, poly aftertouch, channel aftertouch, etc.
Adems de los mensajes de canal se explican los mensajes de sistema
exclusivo, necesarios para controlar los dispositivos y que permiten el uso de
un lenguaje ajeno al protocolo musical, y que al ser propietario de cada sistema
se requiere saber su especificacin segn cada fabricante.
Para entender esta terminologa se explican en el captulo los fundamentos de
transmisin y recepcin SYX.
Al finalizar el captulo se explican los fundamentos del tiempo MIDI y su
sincronizacin.
Web
bastante
afamada
entre
los
desarrolladores
llamada
15
8.5 Captulo 5
8.5.1 Contexto
Una vez explicados los conceptos bsicos sobre MIDI se introduce al lector en
los fundamentos de programacin de estos sistemas. Para entender los
entresijos tcnicos de la programacin en MIDI se ha centrado el captulo en la
librera de software libre DirectMIDI. Esta librera est basada en DirectX y
actualmente se encuentra disponible para sistemas Windows de 32 bits. Este
1
software utiliza una licencia GNU LGPL que, segn Richard Stallman , es un
mtodo para licenciar software de tal forma que su uso y modificacin
permanezcan siempre libres y queden en la comunidad, permitiendo su uso
libremente por otros desarrolladores sin coste alguno.
Para comenzar la explicacin sobre el uso de la librera se introduce
primeramente al lector en los fundamentos de las interfaces COM ms
importantes de DirectMusic que permitirn la implementacin de las
funcionalidades.
Despus se explica cmo obtener el software del repositorio de software libre
2
SourceForge .
Posteriormente se ilustra mediante grficos la arquitectura de objetos que
constituyen la librera y sus objetivos dentro del sistema de clases.
Para mostrar el uso de la librera en C++ se han seguido los siguientes pasos
en la metodologa:
Inicializacin de objetos
16
Terminacin la aplicacin
3
4
17
8.6 Captulo 6
8.6.1 Contexto
En este captulo se aborda el tema fundamental para el programador de
aplicaciones de audio, que es el problema de aadir capacidades de
reproduccin y manipulacin de ficheros de audio conocidos.
Para comenzar, se introduce una seccin sobre el estado actual de las libreras
de reproduccin de audio. Posteriormente se presenta al lector la librera de
5
http://audiere.sourceforge.net/
18
La clase AudioDevice
La clase OutputStream
Reproduccin y efectos
Por ltimo se explica cmo acceder al buffer PCM para obtener las muestras.
En este caso se ilustra un ejemplo que invierte un fichero de msica MP3.
Para finalizar el captulo se describen las caractersticas de los principales
formatos de audio. Los formatos que se explican en este captulo son:
WAV
AIFF
MPEG:MP3
XM / MOD
19
8.7 Captulo 7
8.7.1 Contexto
El captulo final del tratado se orienta a los fundamentos del Tratamiento Digital
de Seal. Este tema es transcendente por su amplia difusin en el entorno
acadmico y profesional y porque su repercusin en el desarrollo de
aplicaciones tanto de imagen como de audio ha sido muy importante en estos
ltimos aos.
El captulo comienza explicando los aspectos ms relevantes de la historia del
tratamiento digital de seales y sus mbitos de aplicacin. Posteriormente, se
comienza a introducir al lector en los algoritmos bsicos utilizados en el audio
que se clasifican en lineales y no lineales. A continuacin se pasa a explicar los
fundamentos de los dos tipos de filtros existentes: los filtros IIR y FIR, que son
los acrnimos de Infinite Impulse Response y Finite Impulse Response
respectivamente. Para explicar estos conceptos se detallan con grficos sus
20
21
22
9.1 Captulo 1
Libros
La Web
6. http://www.mrfizzix.com/instruments/
7. http://www.ehu.es/acustica/espanol/fisiologia1/siaues/siaues.html
8. [Herrera] http://sam.atlantes.org/
9. [Wikipedia] http://es.wikipedia.org/wiki/Cualidades_del_sonido
23
13. [Wikipedia]
http://es.wikipedia.org/wiki/S%C3%ADntesis_mediante_tabla_de_ondas
9.2 Captulo 2
Libros
La Web
17. [Gimeno]
http://usuarios.multimania.es/andromeda_studios/paginas/tutoriales/articulo02.
htm
9.3 Captulo 3
Manuales
19. [Creative Labs] OpenAL Programmer's Guide - OpenAL Versions 1.0 and 1.1
24
La Web
9.4 Captulo 4
Libros
La Web
24. http://home.roadrunner.com/~jgglatt/
9.5 Captulo 5
La Web
25
9.6 Captulo 6
Libros
La Web
29. [Arribas]
http://www.lpi.tel.uva.es/~nacho/docencia/ing_ond_1/trabajos_01_02/formatos_audi
o_digital/html/midiformat.htm
26
9.7 Captulo 7
Libros
La Web
27
Hz: Hertzios
28
11. Anexos
A continuacin se adjunta el tratado terico correspondiente al proyecto de fin de carrera.
Esta obra est bajo una licencia Reconocimiento 3.0 Espaa de Creative Commons.
Para ver una copia de esta licencia, visite http://creativecommons.org/licenses/by-sa/3.0/es/
o envie una carta a Creative Commons, 171 Second Street, Suite 300, San Francisco,
California 94105, USA.
29
Desarrollo de
Aplicaciones de
Audio en C++
Un enfoque prctico
Carlos Jimnez de Parga Bernal - Quirs
Prefacio
Es evidente el auge en capacidad de cmputo de los sistemas con
microprocesador en la actualidad. En un breve perodo de tiempo, hemos
pasado de procesadores de 8 bits con una capacidad computacional baja, a
procesadores de 64 bits con un alta frecuencia de reloj y gran capacidad de
clculo. As mismo, y paralelamente a este desarrollo en microprocesadores
para ordenadores personales, ha surgido una industria de fabricacin de
dispositivos externos que permiten realizar tareas de E/S impensables hace
veinte aos, en especial, los dispositivos de procesamiento de sonido como son:
tarjetas de audio, DSPs (procesadores digitales de seal) y mdulos hardware
de sntesis de sonido, basados en los ltimos avances de la electrnica de fsica
acstica, software y multiprocesadores.
El sonido digital se ha convertido en objeto de estudio y forma parte de
nuestra cultura de hoy en da. Como ejemplos caben destacar: la msica, donde
ya no es difcil escuchar temas o composiciones donde se inserte un sonido
digital, los videojuegos, donde las ltimas tecnologas se abren paso para
producir efectos ms realistas que introducen al jugador en una atmsfera de
gran verosimilitud, el cine, con efectos acsticos en tres dimensiones que
realzan las escenas, y un amplio rango de investigaciones que van desde la
compresin de audio y reconocimiento de voz, hasta la Inteligencia Artificial.
En lo que respecta a la programacin de sonido profesional en
computadores personales, especialmente en Windows, Linux y Mac OS, se han
desarrollado componentes software accesibles a travs del API del sistema
operativo, que permiten acceder a funciones de bajo nivel de manejo de puertos
MIDI y realizar E/S de formas de onda PCM a travs de los canales de audio de
las tarjetas; abstrayendo la complejidad de la programacin del hardware.
Estas APIs son esenciales para comprender el modelo de programacin de
aplicaciones de audio profesionales, donde la latencia debe ser lo ms baja
posible y poder conseguir as las mximas garantas de rendimiento y
fiabilidad.
Tan importante como conocer el software de abstraccin de las
funcionalidades bsicas de una tarjeta, es la teora elemental del sonido, como
son: su comportamiento fsico, sus parmetros, conversin A/D y D/A, la
percepcin humana de las vibraciones acsticas en el espacio y los teoremas
fundamentales de fsica.
Es lgico que en un mundo donde la seal de sonido es computable y
analizable, sea posible realizar un tratamiento digital de seal para poder
manipularla, filtrarla, mezclarla y conseguir efectos en tiempo real sobre las
muestras capturadas por algn dispositivo externo. Esto, por lo tanto, es un
tema trascendental a nivel actual y profesional.
iii
ndice
Dedicatoria....................................................................................................................
Prefacio.........................................................................................................................
ndice............................................................................................................................
i
iii
v
1
3
3
3
4
6
8
8
10
12
13
15
15
17
18
20
20
23
29
34
34
34
34
37
38
40
43
45
45
45
46
46
47
47
48
52
52
52
53
54
55
56
57
57
58
58
59
60
61
63
64
65
3. OpenAL...........................................................................................................
3.1 Introduccin a OpenAL........................................................................
3.2 Arquitectura de OpenAL......................................................................
3.3 Programacin con OpenAL..................................................................
3.3.1 Inicializacin.............................................................................
3.3.2 Trabajar con buffers..................................................................
3.3.3 Reproducir sonido.....................................................................
3.3.4 Posicionamiento 3D..................................................................
3.3.5 Salida de la aplicacin...............................................................
3.3.6 Gestin de errores.....................................................................
3.4 Ventajas de OpenAL............................................................................
Bibliografa y referencias.................................................................................
67
67
67
69
69
71
73
74
76
77
77
78
79
81
81
81
82
84
84
87
88
88
88
90
90
93
94
95
96
98
99
5. Programacin MIDI....................................................................................
5.1 Introduccin..........................................................................................
5.2 La API DirectMusic de DirectX...........................................................
5.2.1 Caractersticas principales........................................................
101
101
102
102
vi
103
104
104
106
107
107
107
108
109
111
112
118
119
120
121
123
123
124
124
126
127
128
129
133
133
133
134
136
141
143
145
147
147
148
148
150
150
152
153
158
158
158
158
159
163
163
164
165
vii
APNDICE.................................................................................................................
A1. Mensajes de la especificacin MIDI 1.0.................................................
A2. Lista de mensajes de controladores MIDI 1.0.......................................
A3. Lista de instrumentos GM1 (General MIDI 1.0)..................................
A4. Tabla de frecuencias de notas musicales en Hertzios...........................
viii
173
173
176
179
181
Parte I
Conceptos preliminares
f =
1
T
Amplitud
Amplitud (A)
Amplitud (A)
Tiempo
Periodo (T)
siendo A y k constantes.
Si admitimos que a medida que transcurre el tiempo el tren de ondas se propaga con
velocidad v hacia la derecha sin deformarse, la ecuacin que describe el movimiento es
de la siguiente forma:
y(x,t) = A sen k(x vt)
V(t)
V
Amplitud (A)
Tiempo
T = 1/F
Sin embargo, existe otra manera de representacin de una seal. Consideremos la forma
de onda de la figura 1.7. Esta seal sinusoidal viene descrita por la amplitud V, la
frecuencia F y la fase . Estos tres parmetros junto con el conocimiento de que la seal
es sinusoidal son suficientes para dibujar la forma de onda del voltaje; la tripleta (V, F,
) especifica completamente la seal. Si consideramos despreciable la fase, es decir,
=0, trataremos entonces con la amplitud V y la frecuencia F; ahora el par (V,F)
especifica completamente la seal. En esta interpretacin F y V pueden tomar cualquier
valor positivo y la seal puede representarse grficamente como muestra la figura 1.8.
(V,F)
Componente espectral
F = 1/T
f
0
1/T
2/T
3/T
4/T
n =1
n =1
10
e ja + e ja
2
donde, definiendo C0 = A0, x(t) puede expresarse en trminos de una nica serie sobre
todos los nmeros enteros:
x(t ) =
Cne ( j 2 / T )
n =
a0 =
1T
x(t )dt
T0
an =
2 T
x(t ) cos(2nt / T )dt
T 0
bn =
2 T
x(t ) sen(2nt / T )dt
T 0
11
12
13
v=
14
V =
331.3
t
1+
273.15
15
En la figura 1.13 puede observarse la relacin de las funciones del odo con un
procesamiento computerizado del mismo:
16
Odo externo
Odo medio
Odo interno
Pabelln auricular +
Conducto auditivo +
Membrana timpnica
Martillo +
Yunque +
Estribo
Vestbulo+
Cclea
Preamplificador
procesador
Micrfono de
alta calidad
Analizador de frecuencias
Tono: Es la respuesta del odo a la frecuencia del sonido. Con el tono se percibe
si los sonidos son graves, agudos o medios. La mayora de los sonidos que
escuchamos estn compuestos de varias frecuencias, por tanto, el tono que se
percibe depende de la frecuencia dominante.
17
18
Pr ef
Como la referencia es 2 10 -5 Pa, resulta que los decibelios SPL valen medidos en Pa:
P
NivelSPL = 20log
-5
2 10
19
Instrumentos de percusin:
El ejemplo ms caracterstico es el tambor. La peculiaridad principal de este
instrumento es que el sonido se genera golpeando un mazo o baquetas contra una
membrana, llamada comnmente parche, que cubre la abertura de una caja de
resonancia generalmente cilndrica.
Los instrumentos de percusin se basan principalmente en la vibracin y en la
resonancia. Cuando se golpea la membrana se produce una deformacin de la misma
que genera una vibracin del aire que hay dentro del mismo. El cuerpo del tambor
empieza a resonar, junto con la membrana, produciendo un sonido alto y grave
procedente de su estructura.
La frecuencia de resonancia de la caja del tambor se define segn la ecuacin:
20
0.764 F
f =
D
1/ 2
f =
1.03kv
L2
Instrumentos de viento:
Los instrumentos de viento generan sonido por medio de vibraciones producidas
en el interior de tubos. Los cambios de frecuencia del sonido se producen como
consecuencia de acortar o alargar la longitud de los tubos, cerrando y abriendo pequeos
orificios creados en los mismos. Existen tres categoras de instrumentos de viento, en
atencin al material constructivo y a la forma de generar la vibracin: metal (ej.
trompeta), madera (ej. flauta) y rganos.
La ecuacin para determinar la longitud de onda en un instrumento de viento
donde el tubo est abierto por ambos extremos es:
2L
n
y la ecuacin para un instrumento de viento abierto por slo por un extremo es:
4L
(2n + 1)
21
v=
m
1/ 2
= f
L
f =
22
23
Generadores de envolvente
Un generador de envolvente es un circuito que genera una seal que permite
controlar un parmetro dentro de un sistema de sntesis. La seal envolvente se suele
usar para modular la amplitud de la seal armnica, y de esta manera simular las
variaciones de amplitud de un instrumento de cuerda. Otros tipos de envolvente se
utilizan para modular el tono o pitch de la seal.
Normalmente, los generadores de envolvente, son del tipo ADSR (Attack, decay,
sustain, release) o traducido al espaol (ataque, decaimiento, sostenido, liberacin)
como se puede ver en la siguiente figura:
25
Amplificador
Los amplificadores que utilizan los sistemas analgicos son del tipo VCA o
amplificadores controlados por tensin que tienen la peculiaridad que su ganancia puede
ser controlada por un voltaje adicional. El VCA es el complemento indispensable para
producir una envolvente de amplitud.
Para implementar un VCA se suelen usar amplificadores operacionales de
transconductancia, aunque tambin se puede implementar con componentes discretos.
En la siguiente figura se observa la circuitera para implementar un VCA.
26
Filtro paso-bajo
Filtro paso-banda
Figura 1.23 Tipos de filtro
Filtro paso-alto
Filtro elimina-banda
27
28
30
=1
=5
=25
Figura 1.27 Representacin temporal de una seal modulada en FM, en funcin del
ndice de modulacin.
31
32
Desplazamiento de tonos: con esta tcnica se puede lograr que a partir de una
muestra de sonido que representa una nota determinada se puedan generar otras
notas del mismo instrumento. Para conseguir esto se aplican diferentes filtros a
la seal original que junto con un aumento o reduccin de la frecuencia de
reproduccin de la seal da lugar a la nueva nota. Este sistema es ms fcil de
implementar por software y es el que utilizan muchos VST (Instrumentos
Virtuales Digitales) comerciales, como el de la figura 1.28.
Figura 1.28 Software VST con sntesis de tabla de ondas con desplazamiento de tonos.
33
34
Voltios
8
7
6
5
4
3
2
1
0
Tiempo
Voltios
8
7
6
5
4
3
2
1
0
Tiempo
35
Voltios
8
7
6
5
4
3
2
1
0
Tiempo
001 010 001 011 010 100 101 100 101 011
36
37
38
fs/2
fs
interpolacin
t
filtrado digital
filtro analgico
banda imagen
fs/2
fs
Figura 1.35 Comparacin entre la conversin D/A bsica (arriba) y la conversin con
oversampling (abajo)
El desarrollo del oversampling ha evolucionado paralelamente al de los
convertidores D/A sigma-delta, tambin conocidos como one bit stream. Estos
convertidores no reconstruyen la seal analgica desde cero para cada muestra, sino que
suman o restan la diferencia necesaria para que la seal alcance el nivel deseado. Esta
diferencia se muestrea con un nico bit de resolucin, de ah el nombre one bit stream.
Esta simplificacin se compensa con una mayor frecuencia de muestreo, pues
para poder reproducir grandes variaciones de la seal en saltos de 1 LSB se requiere que
su valor se actualice mucho ms rpido que la frecuencia original de muestreo. Sin
embargo las etapas analgicas del convertidor D/A son ms sencillas, lo cual reduce su
consumo.
39
Bibliografa y referencias
Libros
Fsica COU A.Candel, J.Satoca, J.B. Soler, F.Tejerina, J.J. Tent. Editorial Anaya,
1990.
Apuntes Redes 3 IT Informtica de Sistemas Universidad de Murcia, 1997.
Tcnicas de Grabacin modernas David Miles Huber, Robert E. Runstein, 6 edicin.
Editorial Omega, 2007.
Diseo y desarrollo Multimedia, Sistemas, Imagen, Sonido y Vdeo Manuel-Alonso
Castro Gil, Antonio Colmenar Santos, Pablo Losada de Dios, Juan Peire Arroba.
Editorial Ra-ma, 2002.
Tecnologa Bsica del Sonido I Ignasi Cuenca David, Eduard Gmez Juan. Editorial
Paraninfo, 2006.
La Web
Wikipedia:
Concepto de sonido:
http://es.wikipedia.org/wiki/Cualidades_del_sonido
Funcionamiento del odo:
http://es.wikipedia.org/wiki/O%C3%ADdo
Otros URL:
The Physic of Instruments
http://www.mrfizzix.com/instruments/
Sistema auditivo humano:
http://www.ehu.es/acustica/espanol/fisiologia1/siaues/siaues.html
Sntesis analgica musical:
http://sam.atlantes.org/ Avelino Herrera Morales
Tcnicas de sntesis digital:
http://en.wikipedia.org/wiki/Frequency_modulation_synthesis
http://es.wikipedia.org/wiki/S%C3%ADntesis_mediante_tabla_de_ondas
40
http://es.wikipedia.org/wiki/Octava
http://www.analog.com/en/content/0,2886,761%255F795%255F91588%255F0,00.html
http://www.virtins.com
http://www.renoise.com/
41
Parte II
Programacin
2.1 Qu es DirectX?
2.1.1 Introduccin
En los inicios del desarrollo de aplicaciones multimedia en Windows era muy difcil
poder escribir cdigo eficiente que pudiera controlar con xito los efectos de vdeo y
audio en este sistema operativo. Aunque el objetivo de Windows era aislar al
programador del hardware, lo cual era origen de numerosas dificultades de operatividad
en sistemas MS-DOS, sin embargo este aislamiento no gust al principio a los
desarrolladores multimedia pues seguan con el hbito de trabajar directamente con el
hardware para poder as sacar el mximo rendimiento a las aplicaciones.
Paulatinamente, fueron aceptndose las dificultades que implicaba programar
aplicaciones en MS-DOS: falta de uniformidad en la plataforma, imposibilidad para
manejar una gama amplia de dispositivos hardware de entrada/salida multimedia,
dificultad para acceder al conocimiento especfico de cada arquitectura, hardware y
recursos software, sistema operativo mono-usurario y mono-tarea, etc.
DirectX ha permitido abrir la puerta a las funciones de Windows (sin pedir al
programador que sacrifique el rendimiento) y poder abstraer de esta manera la
complejidad del acceso al hardware. El objetivo de los creadores de DirectX era hacer la
plataforma Windows un entorno atractivo para programar aplicaciones multimedia. As,
desde la aparicin de esta tecnologa han surgido juegos con movimientos suaves,
animaciones cristalinas y sonido de alta calidad.
Los desarrolladores consiguieron una nueva plataforma muy rica, de gran rendimiento y
con gran operatividad; y los fabricantes de hardware dispondran de un mercado ms
amplio para sus productos. Se haba conseguido al fin la independencia del dispositivo
que facilita el desarrollo de aplicaciones multimedia a gran escala.
DirectX consta de unas libreras en cdigo binario que abstraen las funciones de acceso
al hardware y al mismo tiempo consigue un alto rendimiento. Se distribuye como un
programa que se instala junto a las libreras del sistema y se proporciona adicionalmente
y dirigido a profesionales del sector del desarrollo multimedia un SDK (Software
Development Kit) que incluye las libreras estticas y cdigo fuente para poder crear
aplicaciones DirectX. La versin actual de DirectX es la 11 que est disponible
solamente para Windows Vista y Windows 7.
45
Rapidez
Disminuir la latencia
Ser humilde
DirectX
HAL
HEL
Hardware
46
47
48
Objeto1
Interfaz1
Interfaz2
- metodo1
- metodo1
- metodo2
- metodo2
- metodo3
- metodo3
IID_IInterfaz1
IID_IInterfaz2
Uno de los componentes principales de modelo COM son las interfaces, que,
aunque este concepto no existe en programacin C++, s existe en otros lenguajes como
Java. Las interfaces en C++ se implementan como clases abstractas. Toda interfaz en
COM deriva de la interfaz IUnknown. Por lo tanto, una interfaz es una clase que
contiene un conjunto de punteros a funciones que se encuentran en la tabla de mtodos
virtuales VMT que genera el compilador.
El cliente de un objeto COM no acceder directamente al objeto, sino que lo har a
travs de sus interfaces. Lo nico que poseer el cliente ser un puntero a la interfaz que
implementar los mtodos que llevan a cabo la lgica de negocio.
Interfaz IUnknown: Como se ha mencionado anteriormente todas las interfaces
derivan de IUnknown. Si nos fijamos en el grfico 2.3, podemos observar que para
acceder al resto de las interfaces se entra por la interfaz de arriba:
49
IUnknown
Interfaz 2
Objeto COM
Interfaz 3
Figura 2.3
50
51
52
Buffer primario
Dispositivo
Buffers por hardware (si
disponibles)
una
estructura
de
tipo
Descripcin
Tipo de formato. Debe ser
WAVE_FORMAT_PCM
Nmero de canales 1(mono), 2 (estreo)
Frecuencia de muestreo(en hertzios):
Normalmente 11.025, 22.050, 44.100
Velocidad media de transferencia
(nSamplesPerSec * nBlockAlign)
Bytes por muestra (nChannels *
nBitsPerSample / 8)
53
utilizar
la funcin
Descripcin
Puntero al GUID del dispositivo, o NULL
para el dispositivo por defecto
Direccin del puntero que se iniciar
mediante la llamada
Debe ser NULL
Tabla 2.2
<windows.h>
<mmsystem.h>
<dsound.h>
<SDKsound.h>
<math.h>
<string>
<sstream>
#include "directsound.h"
int _tmain(int argc, _TCHAR* argv[])
{
// Inicializa COM
CoInitialize(NULL);
IDirectSound8* pDS = NULL;
HRESULT
hr;
const LPCWSTR tituloVentana = (LPCWSTR) L"Directsound - Captulo
2";
SetConsoleTitle(tituloVentana);
// Crea IDirectSound a partir del dispositivo primario
if( FAILED( hr = DirectSoundCreate8( NULL, &pDS, NULL ) ) )
printf("Error al crear DirectSound (codigo numero=%d)\n",hr);
54
Ventajas
Mejor cooperacin con
otras aplicaciones.
DDSCL_PRIORITY
Permite modificar el
formato primario.
DDSCL_EXCLUSIVE
Desventajas
No se puede modificar el
formato primario, por lo
que se est restringiendo al
formato de salida por
defecto de DirectSound.
Podra terminar
modificando la salida de
otra aplicacin.
Podra no ser apropiado
silenciar todas las
aplicaciones de fondo.
Requiere un controlador de
DirectSound; no se pueden
reproducir buffers
secundarios; las
aplicaciones restantes
pierden sus buffers.
Tabla 2.3
55
56
57
Notas
Se utiliza para posicionamiento en 3D del
sonido, si y slo si se crea una interfaz
IDirectSound3DBuffer. No puede
combinarse con DSBCAPS_CTRLPAN
DSBCAPS_CTRLALL
Establece todos los controles
DSBCAPS_CTRLDEFAULT
Establece controles por defecto
DSBCAPS_CTRLFREQUENCY
Cambia la frecuencia de reproduccin
DSBCAPS_CTRLPAN
Cambia el pan (balance)
DSBCAPS_POSITIONNOTIFY
Informa o notifica sobre el
posicionamiento
DSBCAPS_CTRLVOLUME
El buffer va a sufrir cambios de volumen
DSBCAPS_LOCHARDWARE
Buffer canalizado por hardware
DSBCAPS_LOCSOFTWARE
Buffer canalizado por software
DSBCAPS_STATIC
Buffer esttico
DSBCAPS_PRIMARYBUFFER
El buffer es primario
DSBCAPS_MUTE3DATMAXDISTANCE Hace que los buffers 3D sean ms
eficientes reduciendo el nmero de
clculos necesarios.
Tabla 2.4
58
Descripcin
Puntero a la estructura de descripcin del
buffer.
Recibe el puntero a la interfaz
Debe ser NULL
Tabla 2.5
A continuacin se muestra el cdigo que lo hace posible:
/ Crea un buffer secundario con sonido
LPDIRECTSOUNDBUFFER*
LPDIRECTSOUND3DBUFFER*
DWORD
CWaveFile*
const int
apDSBuffer
apDS3DBuffer
dwDSBufferSize
pWaveFile
NUM_BUFFERS
=
=
=
=
=
NULL;
NULL;
NULL;
NULL;
3;
59
60
Parmetro
DWORD dwWriteCursor
DWORD dwWriteBytes
DWORD lplpvAudioPtr1
LPDWORD lpdwAudioBytes1
LPVOID lplpAudioPtr2
LPDWORD lpdwAudioBytes2
DWORD dwFlags
Descripcin
Desplazamiento a la zona en la que
comenzar la parte bloqueada.
Nmero de bytes a bloquear.
Recibe la direccin de inicio de bloqueo.
Recibe el tamao de bloqueo, o la primera
porcin si el bloqueo es circular.
Recibe la direccin de la segunda porcin
del bloqueo; si no lo es, recibe NULL.
Recibe el nmero de bytes de la segunda
porcin del bloqueo si ste es circular; si
no lo es, recibe 0.
DSBLOCK_FROMWRITECURSOR o
DSBLOCK_ENTIREBUFFER
Tabla 2.6
En el fragmento de cdigo siguiente se muestra el ejemplo del bloqueo del buffer antes
de la reproduccin.
VOID*
pDSLockedBuffer
= NULL; // Puntero a la memoria bloqueada
DWORD
dwDSLockedBufferSize = 0;
// Tamao de la zona bloqueada
DWORD
dwWavDataRead
= 0;
// Cantidad de datos del fichero
WAV a leer
// Bloquea el buffer
if( FAILED( hr = apDSBuffer[i]->Lock( 0,dwDSBufferSize,
&pDSLockedBuffer,&dwDSLockedBufferSize,
NULL, NULL, 0L ) ) )
printf("Error de bloqueo del buffer (codigo
error=%d)", hr );
// Empieza a leer desde el inicio del fichero
pWaveFile->ResetFile();
if( FAILED( hr = pWaveFile->Read( (BYTE*) pDSLockedBuffer,
dwDSLockedBufferSize,&dwWavDataRead ) ) )
printf("Error leyendo el fichero de audio (codigo error=
%d)", hr );
DWORD dwAudioBytes2
62
Descripcin
Direccin de inicio del bloqueo.
Nmero de bytes en la primera porcin
del bloqueo.
Direccin de inicio del buffer si se
produjo desbordamiento del buffer, si no
es as, NULL.
Nmero de bytes en la parte del buffer que
Descripcin
Debe ser 0.
Debe ser 0.
0 o DBSPLAY_LOOPING.
Tabla 2.8
case '1':
if (FAILED (hr = apDSBuffer[0]->Play( 0, 0, 0)))
printf("Error al reproducir buffer 1 (codigo error =%d)",
hr );
break;
63
64
Bibliografa y referencias
Libros
A fondo DirectX Bradley Bargen, Peter Donnelly. Microsoft Press, 1998.
Programacin COM y COM+ Alan Gordon . Anaya Multimedia, 2001.
Sistemas Distribuidos: conceptos y diseo Colouris, Dolimore, Kindberg. Pearson
Addison Wesley, 2001
La Web
MSDN (Microsoft Developer Network):
http://msdn2.microsoft.com/es-es/default.aspx
Francisco ngel Gimeno Domnech Andrmeda Studios
http://usuarios.multimania.es/andromeda_studios/paginas/tutoriales/articulo02.htm
65
C A P T U L O 3 OpenAL
OpenAL
67
C A P T U L O 3 OpenAL
perspectiva del programador de aplicaciones requiere de muy poco tiempo de
codificacin y de mantenimiento para cumplir los requisitos.
De la misma forma que OpenGL, OpenAL consta de dos secciones de la API: el ncleo
basado en las llamadas a las funciones y la API ALC que es usada para manejar
contextos de renderizacin, uso de recursos y bloqueo multiplataforma. Adems,
imitando a su predecesor, OpenAL incluye una librera de alto nivel para
programadores, llamada ALUT, con convenciones de llamadas muy parecidas a la
GLUT de OpenGL cuyo cometido es simplificar algunas tareas complicadas como es la
lectura de un fichero WAV.
Dispositivo n1
Listener
Contexto n1
Source 1
Source 2
Source 3
Source 4
Buffer 1
Buffer 2
Buffer 3
Buffer 4
68
Mac OSX
GNU/Linux
BSD
Solaris
IRIX
C A P T U L O 3 OpenAL
Windows PC
XBox 360
Descripcin
Un string describiendo el dispositivo
Tabla 3.1
Descripcin
Puntero al dispositivo
Atributos:
ALC_FREQUENCY
ALC_MONO_SOURCES
ALC_REFRESH
ALC_STEREO_SOURCES
ALC_SYNC
Tabla 3.2
En este captulo utilizaremos el compilador Microsoft Visual C++ .NET 2010 que es el ms avanzado
en Windows 64 bits hasta la fecha de publicacin de este tratado.
69
C A P T U L O 3 OpenAL
alcMakeContextCurrent
Parmetros
ALContext *context
Descripcin
Puntero al contexto
Tabla 3.3
En caso de error, la funcin devolver la constante booleana ALC_FALSE, y en caso de
xito devolver ALC_TRUE.
Con estas llamadas tan simples podemos activar un dispositivo y un contexto de
renderizacin para reproducir buffers de sonidos y activar sources y listeners.
Por ltimo, dentro de la seccin de inicializacin, existe la posibilidad de indagar en
OpenAL la presencia de extensiones hardware, mediante la llamada a la funcin:
alIsExtensionPresent
Parmetros
ALCdevice *device
const ALCchar *extname
Descripcin
Puntero al dispositivo del cual interesa
averiguar extensin
Cadena indicando la extensin
Tabla 3.4
<conio.h>
<windows.h>
<math.h>
<string>
<sstream>
#include "al.h"
#include "alc.h"
#include "AL/alut.h"
70
C A P T U L O 3 OpenAL
3.3.2 Trabajar con buffers
Depus de iniciar la aplicacin es preciso generar el primer elemento bsico de la
arquitectura de OpenAL: el buffer. Con este objeto podremos almacenar formas de
ondas provenientes de ficheros WAV y reproducirlas ms tarde.
La funcin que lleva a cabo este cometido es:
alGenBuffers
Parmetros
Descripcin
ALsizei n
Nmero de buffers a generar
ALuint *buffers
Puntero a un array de valores ALuint que
almacenar el nombre de los nuevos
buffers.
Tabla 3.5
Una vez creado el buffer es posible almacenar en l datos en formato PCM
provenientes de un fichero WAV. Para realizar esta operacin se utiliza una funcin de
alto nivel definida en la librera externa alut.h que permite leer ficheros en formato
WAV.
alutLoadWAVFile
Parmetros
ALbyte* strFile
ALenum* format
ALvoid *data
ALsizei *size
ALsizei *freq
ALboolean *loop
Descripcin
Nombre del fichero
Formato del fichero
Datos en PCM
Tamao del fichero
Frecuencia de sampleo
Bucle de reproduccin del fichero
Tabla 3.6
Por ltimo, y una vez ledos los datos PCM en un array, se proceder a copiarlos
dentro del objeto buffer con la siguiente funcin:
alBufferData
Parmetros
ALuint buffer
ALenum format
Descripcin
Nombre del buffer a llenar con datos
Puede ser uno de los siguientes:
AL_FORMAT_MONO8
AL_FORMAT_MONO16
AL_FORMAT_STEREO8
AL_FORMAT_STEREO16
Puntero a los datos de audio
El tamao de los datos en bytes
Frecuencia de muestreo
Tabla 3.7
71
C A P T U L O 3 OpenAL
Esta funcin tambin puede leer datos en formatos diferentes a PCM si se utilizan
las extensiones apropiadas.
Con todo esto, el cdigo necesario para implementar la generacin y carga de datos en
el buffer es como se muestra en el siguiente ejemplo:
// Genera los buffers
ALuint
buffer[NUM_BUFFERS];
alGenBuffers(NUM_BUFFERS, buffer);
printf("Generando buffers...\n");
if ((error = alGetError()) != AL_NO_ERROR)
{
printf("alGenBuffers :", error);
terminaAplicacion();
return;
}
// Carga los ficheros WAV
ALsizei size,freq;
ALenum format;
ALvoid *data;
ALboolean loop;
printf("Leyendo ficheros de audio...\n");
for(int i = 0; i < NUM_BUFFERS; i++)
{
std::string fichero,indice;
std::ostringstream iss;
iss << i+1;
fichero = "..\\media\\sonido" + iss.str() + ".wav";
alutLoadWAVFile((ALbyte*)fichero.c_str(), &format, &data,
&size, &freq, &loop);
if ((error = alGetError()) != AL_NO_ERROR)
{
printf("alutLoadWAVFile: %d", error);
// Delete Buffers
alDeleteBuffers(NUM_BUFFERS, buffer);
terminaAplicacion();
return;
}
// Copia a los respectivos buffers los datos
printf("Copiando a buffer...\n");
alBufferData(buffer[i],format,data,size,freq);
if ((error = alGetError()) != AL_NO_ERROR)
{
printf("alBufferData buffer 0 : %d", error);
alDeleteBuffers(NUM_BUFFERS, buffer);
terminaAplicacion();
return;
}
// Descarga el fichero WAV
alutUnloadWAV(format,data,size,freq);
if ((error = alGetError()) != AL_NO_ERROR)
{
printf("alutUnloadWAV : %d", error);
alDeleteBuffers(NUM_BUFFERS, buffer);
terminaAplicacion();
return;
}
}
72
C A P T U L O 3 OpenAL
3.3.3 Reproducir sonido
Como es habitual en toda aplicacin de sonido, debe exisitir algn objeto que
controle la reproduccin de audio. En OpenAL tenemos el objeto source que permite
llevar a cabo esta operacin:
alGenSources
Parmetros
ALsizei n
ALuint *sources
Descripcin
Nmero de sources a generar
Puntero a un array de valores ALuint con
los nombres de los sources
Tabla 3.8
Con el fin de reproducir el sonido debemos adjuntar los buffers, creados en la seccin
anterior, a los sources mediante la llamada a la siguiente funcin:
alSourcei
Parmetros
ALuint source
ALenum param
ALint value
Descripcin
Nombre del source al que hay que
establecer los atributos
Uno de los siguientes atributos:
AL_SOURCE_RELATIVE
AL_CONE_INNER_ANGLE
AL_CONE_OUTER_ANGLE
AL_LOOPING
AL_BUFFER
AL_SOURCE_STATE
Valor a establecer
Tabla 3.9
73
C A P T U L O 3 OpenAL
alDeleteSources(NUM_SOURCES, source);
alDeleteBuffers(NUM_BUFFERS, buffer);
terminaAplicacion();
return;
}
}
Descripcin
El nombre de la fuente a reproducir
Tabla 3.10
ALuint source
while( condicion )
{
switch( _getch() )
{
// Reproduce buffer 1
case '1':
alSourcePlay(source[0]);
Detener el sonido
alSourceStop(source[0]);
Rebobinar
alSourceRewind(source[0]);
o pausarlo
alSourcePause(source[0]);
3.3.4 Posicionamiento 3D
Esta es una de las caractersticas ms avanzadas de OpenAL, ya que permimte
utilizar diferentes configuraciones para manipular el sonido en tres dimensiones. Uno de
los elementos fundamentales para el posicionamiento 3D es el listener, que se podra
asemejar a los odos del sujeto que se encuentra sumergido en el espacio virtual.
Normalmente, los listeners suelen establecerse en la posicin de la cmara, de manera
que sensacin acstica concuerde con la percepcin visual. As mismo, es posible
aplicar un gran nmero de parmetros sobre el listener para controlar la orientacin,
posicin y la velocidad. Este objeto debe ser nico en la aplicacin, lgicamente, ya que
el sonido procesado mediante el mismo es luego dirigido a los canales estreo de los
altavoces.
74
C A P T U L O 3 OpenAL
Respecto al posicionamiento 3D de un sonido en OpenAL es posible llevarlo a cabo
llamando a la siguiente funcin:
alSourcefv
Parmetros
ALuint source
ALenum param
ALfloat *values
Descripcin
Source al que hay que establecer los
atributos
Atributo a establecer. Puede ser uno de los
siguientes:
AL_POSITION
AL_VELOCITY
AL_DIRECTION
Un puntero a un array de valores a
establecer
Tabla 3.11
75
C A P T U L O 3 OpenAL
Figura 3.3 Descripcin del efecto de giro de 360 creado sobre el oyente en el ejemplo
anterior
Tambin es importante liberar los buffers y los sources creados para manejar audio.
Las funciones alDeleteBuffers y alDeleteSources son las responsables de destruir los
objetos buffer y source que se hayan creado durante la ejecucin de la aplicacin. De
esta manera se liberar el espacio de memoria utilizado para dicho propsito en el
sistema. El siguiente fragmento de cdigo ha sido utilizado en el ejemplo para liberar
los objetos sources y buffers en el momento de romper el flujo de control para salir de la
aplicacin:
alDeleteSources(NUM_SOURCES, source);
alDeleteBuffers(NUM_BUFFERS, buffer);
terminaAplicacion();
76
C A P T U L O 3 OpenAL
Ya slo faltara, por ltimo, salir de la aplicacin OpenAL mediante a la llamada:
aluExit()
3.3.6 Gestin de errores
Cuando se produce una situacin anmala en la llamada a cualquier funcin de
OpenAL se genera un estado de error en la librera que informa con un cdigo el tipo de
error que se ha producido. Evidentemente, este tipo de gestin de errores se realiza
mediante consulta utilizando la funcin:
ALenum alGetError(ALvoid)
77
C A P T U L O 3 OpenAL
Como conclusin se puede destacar que OpenAL se presenta como una gran alternativa
a otras libreras de sonido por sus mltiples ventajas a la hora del desarrollo de software
de audio.
Bibliografa y referencias
referencias
Manuales
OpenAL Programmer's Guide - OpenAL Versions 1.0 and 1.1
La Web
Wikipedia:
http://en.wikipedia.org/wiki/OpenAL
78
Parte III
MIDI
C A P T U L O 4 Introduccin a MIDI
Introduccin a MIDI
4.1 Qu es MIDI?
4.1.1 Un poco de historia
Al comienzo del desarrollo de la tecnologa musical, todos los sintetizadores
eran monofnicos, es decir, slo eran capaces de reproducir una sola nota al mismo
tiempo.
A finales de la dcada de los 70 hizo su aparicin el sintetizador digital y trajo consigo
el problema de la incompatibilidad entre sistemas de fabricados por cada compaa. De
este modo se hizo necesario la creacin de un lenguaje comn que abstrajera las
caractersticas tcnicas de cada marca y permitiera la comunicacin entre sistemas.
En 1982 , Dave Smith, de la empresa Sequential, propuso poner de acuerdo a las
grandes compaas para crear un protocolo de comunicacin entre sistemas que fuera
respetado por el convenio o norma. El fundamento de su idea era poder interconectar los
instrumentos digitales para hacer sonar a ms de un aparato a la vez, creando as un
efecto de polifona musical.
El estndar MIDI fue propuesto inicialmente en un documento dirigido a la
Audio Engineering Scoiety. La primera especificacin MIDI se public en agosto de
1983.
El primer sintetizador capaz de soportar la especificacin fue el Prophet 600 de
Sequential (figura 4.1). En 1996 todos los instrumentos que ostentaban el logotipo
respetaban el estndar.
MIDI es el acrnimo de Interfaz Digital de Instrumentos Musicales, y
actualmente el estndar es ampliamente utilizado en la industrial musical; aunque es
tambin muy utilizado en otros muchos sistemas, no slo instrumentos musicales. As,
por ejemplo, podemos encontrar la tecnologa MIDI implementada en sistemas para
controlar la secuencia de luces de un espectculo en directo o controlar aparatos de
edicin de sonido, entre otras muchas aplicaciones.
81
C A P T U L O 4 Introduccin a MIDI
82
C A P T U L O 4 Introduccin a MIDI
Cabe aclarar que MIDI no transmite seales de audio, sino datos de eventos y
mensajes controladores que se pueden interpretar de manera arbitraria, de acuerdo con
la programacin del dispositivo que los recibe. Es decir, MIDI es una especie de
partitura que contiene las instrucciones en valores numricos, o ms especficamente
en binario, sobre cundo generar cada nota de sonido y las caractersticas que debe
tener; posteriormente el sistema MIDI transformar en msica las secuencia de
instrucciones.
Los aparatos MIDI se pueden clasificar en tres grandes categoras:
C A P T U L O 4 Introduccin a MIDI
4.1.3 Electrnica MIDI
4.1.3.1 Interconexin de sistemas
MIDI no ha sido indiferente a los nuevos avances en sistemas de comunicacin
electrnica de datos. As, las nuevas tecnologas en comunicaciones han abierto un gran
abanico de posibilidades al estndar, del cual se ha dejado influenciar.
El sistema MIDI utiliza un total de 16 canales que se pueden comunicar entre aparatos o
instrumentos a travs de cada cable. Los tipos de conexin actuales son los siguientes:
Conectores y cables MIDI:
El MIDI comunica de manera digital los datos de una interpretacin musical a
travs de un cable estndar MIDI como una serie de mensajes que se transmiten a una
velocidad de 31,25 kbaudios (bits/segundo).
84
C A P T U L O 4 Introduccin a MIDI
Una forma tpica de conectar dispositivos MIDI es un una red margarita o daisy
chain. Este mtodo transmite MIDI de un aparato al siguiente puenteando los datos
recibidos por MIDI in de un aparato, directamente a otro aparato por MIDI thru, donde
la cadena contina en el siguiente aparato. En la figura 4.8 se muestra un ejemplo de
esta disposicin.
85
C A P T U L O 4 Introduccin a MIDI
Conexiones USB y FireWire:
Actualmente los sistemas MIDI pueden conectarse tambin a travs de
conectores USB del tipo 1 y 2 y el protocolo IEEE (FireWare). Gracias a estos
dispositivos de alta velocidad es posible conectar, respetando el protocolo MIDI 1.0,
aparatos de diferentes compaas. La ventaja de estos conectores es la facilidad de
auto-deteccin del dispositivo, la rpida y cmoda conexin.
Conexiones de red mLAN:
Este innovador sistema fue creado por Yamaha y resolva el problema de la
innecesaria parafernalia de cables para la conexin MIDI. Este sistema permite que el
audio multicanal y los datos sean transferidos a travs del cable estndar IEEE FireWare
1394.
mLAN, soporta un total de 100 canales de datos de audio digital y hasta 256 puertos
MIDI, es decir, un total de 16 x 256 conexiones o canales en tiempo real. Adems tiene
la posibilidad de comunicacin fullduplex a velocidades de 100, 200 400 Mbps.
Las ventajes principales de este sistema son la velocidad de conexin, el ancho de banda
para audio y canales MIDI, y la fcil conexin automtica entre sistemas MIDI sin
necesidad de configuracin.
86
C A P T U L O 4 Introduccin a MIDI
4.1.3.2 Esquemticos
En esta seccin se ilustra los esquemticos electrnicos para configurar las
conexiones IN, OUT y THRU a la circuitera MIDI basada en un integrado UART para
comunicacin serie.
87
C A P T U L O 4 Introduccin a MIDI
Byte de estado.
Byte de datos.
El byte de estado se utiliza para indicar el tipo de mensaje y el canal dentro del
sistema al que va dirigido. En los bytes de datos se codifican en binario los valores
numricos que indican los parmetros para ese canal. Por ejemplo: la nota pulsada y la
velocidad de pulsacin. Figura 4.11.
Para identificarlo, el MSB (bit ms significativo) del byte de estado es siempre 1, en
contrapartida, el MSB del byte de datos siempre empieza en 0.
Byte de estado
N de estado/canal
(1001 0100)
(note on/canal 5)
Byte de datos 1
N de nota
(0100 0000)
(64)
Byte de datos 2
Velocidad de pulsacin
(0101 1001)
(89)
88
C A P T U L O 4 Introduccin a MIDI
89
C A P T U L O 4 Introduccin a MIDI
Note on: indica que una nota particular debera ser reproducida. Esencialmente,
significa que la nota comienza a sonar, aunque algunos patches podran tener un
periodo de ataque VCA largo que necesite aumentar lentamente el sonido. En
cualquier caso, este mensaje indica que una nota particular comienza a sonar (al
menos que la velocidad de pulsacin de la nota sea 0). Si el dipositivo el
multitmbrico, cada nota se reproduce en un canal diferente.
El rango del byte de estado abarca los valores hexadecimales 0x90 a 0x9F. El
primer byte de datos contiene el nmero de la nota. Hay 128 posibles notas en
un sistema MIDI, numeradas del 0 al 127. El valor 60 corresponde a la nota DO
central del teclado. El segundo byte de datos es la velocidad, tambin en el rango
[0,127]. Indica con qu fuerza se ha pulsado la tecla. Con frecuencia la
velocidad se usa para adaptar el tiempo de ataque del VCA.
Un mensaje MIDI con la velocidad 0 es considerado como un mensaje de Note
off.
Note off: indica que una nota en concreto ha sido finalizada. Esto significa que
la nota debe de parar la reproduccin, aunque algunos patches podran tener un
tiempo de liberacin (release time) que necesite disminuir lentamente el sonido.
Algunas veces, el pedal de sostenimiento puede estar presionado, en ese caso la
liberacin de la nota es pospuesta hasta que se levante el pedal. En cualquier
evento, este mensaje puede causar que el VCA se posicione dentro de la etapa de
liberacin, o si el pedal est presionado, indica que una nota debera ser liberada
cuando el pedal de sostenimiento est desactivado. En un dispositivo
multitmbrico cada note off debera activarse por cada canal.
El mensaje contiene un byte de estado con el rango de valores: 0x80 a 0x8F,
mientras que el primer byte de datos contiene la tecla a liberar y el segundo byte
la velocidad en la que se ha dejado levantar la tecla.
90
C A P T U L O 4 Introduccin a MIDI
durante el proceso. Una vez recibido el mensaje, muchos dispositivos lo usan
para variar el VCA de la nota y/o el nivel de sostenido de la envolvente VCF, o
la cantidad a ser aplicada al control LFO.
El byte de estado est comprendido en el rango de valores: 0xA0 a 0xAF.
El primer byte de datos es el nmero de nota a aplicar la presin. El segundo
byte de datos es la cantidad de presin, en un rango discreto de [0,127] valores.
91
C A P T U L O 4 Introduccin a MIDI
92
C A P T U L O 4 Introduccin a MIDI
4.3.2 Mensajes de sistema
Estos mensajes son transmitidos globalmente a cada dispositivo dentro de la red
MIDI, puesto que no se utiliza en ellos el nmero de canal. Cualquier dispositivo
responder a los mensajes del sistema independientemente del canal. A continuacin se
enumeran los diferentes mensajes de sistema MIDI:
Song select: los dispositivos maestros MIDI envan este mensaje para comenzar
el playback de una cancin.
El byte de estado es 0xF3, y el byte de datos es una valor comprendido entre 0 y
127 que indica el nmero de secuencia o cancin.
Tune request: mensaje que tambin se traduce como peticin de tono. Este
mensaje se utiliza para solicitar al dispositivo un cambio de calibracin tonal.
Con frecuencia se implementa en mdulos de sonido con circuitos osciladores
analgicos.
El byte de estado es el valor 0xF6 y no contiene byte de datos.
93
C A P T U L O 4 Introduccin a MIDI
4.3.3 Mensajes de sistema exclusivo
Estos mensajes permiten a los fabricantes y programadores de sistemas MIDI
comunicar informacin especfica para la configuracin del dispositivo.
El principal uso del mensaje es para enviar una gran cantidad de datos en formato no
estructurado MIDI, como volcados de la memoria de patches, datos del secuenciador o
datos de formas de onda. Por ejemplo, un mensaje SysEx podra se utilizado para
establecer el nivel de retroalimentacin para un operador en un sintetizador de
modelado fsico de Roland .
El formato de transmisin de un mensaje de sistema exclusivo (figura 4.13),
como se define en el estndar MIDI, incluye un byte de estado (arranque) de sistema
exclusivo (0xF0) y un byte de parada EOX (0xF7).
0xF0 0x43 0x25 ... ... ... ... ... ... 0xF7
94
C A P T U L O 4 Introduccin a MIDI
95
C A P T U L O 4 Introduccin a MIDI
4.3.5 Mensajes de tiempo real
Los mensajes de tiempo real, que consisten en un solo byte de estado, estn
comprendidos en el rango [0xF8,0xFF]. Estos mensajes estn principalmente
relacionados con la temporizacin y sincronizacin. MIDI permite que los mensajes de
tiempo real sean enviados en cualquier momento, incluso intercalados con otros
mensajes MIDI. Por ejemplo, un mensaje en tiempo real podra ser enviado entre los
dos bytes de datos de un mensaje note on. Un dispositivo debera siempre estar
preparado para manejar cada situacin; procesando el byte de tiempo real, y
subsiguientemente continuar procesando el mensaje anteriormente interrumpido.
A continuacin se enumeran los mensajes de tiempo real utilizados en MIDI:
MIDI Tick: como en el caso anterior, algunos dispositivos maestros envan este
mensaje para mantener las sincrona con el receptor. Este mensaje es enviado a
intervalos regulares de uno cada 10 ms.
El byte de estado contiene el valor 0xF9 y no tiene datos.
96
C A P T U L O 4 Introduccin a MIDI
In t e r r u p c i n
d e l t im e r
Interru pci n
d e recepci n
M ID I
F la g = 0
R ecib e
d atos
F la g = 1
In c r e m e n t a
t im e o u t
Inicia la
variable d e
tim eou t
S A L ID A
t im e o u t < = 3 0 0 m s
no 0xF E
?
t im e o u t > 3 0 0 m s
0xFE
Establece
el flag
S AL ID A
a algu na o tra
o peracin
D e s a c t iv a
t o d a s la s
n o ta s
S A L ID A
In ic ia e l
f la g
S A L ID A
97
C A P T U L O 4 Introduccin a MIDI
C A P T U L O 4 Introduccin a MIDI
Bibliografa y referencias
Libros
Tcnicas de Grabacin modernas David Miles Huber, Robert E. Runstein, 6 edicin.
Editorial Omega, 2007.
Diseo y desarrollo Multimedia, Sistemas, Imagen, Sonido y Vdeo Manuel-Alonso
Castro Gil, Antonio Colmenar Santos, Pablo Losada de Dios, Juan Peire Arroba.
Editorial Ra-ma, 2002.
La Web
MIDI Manufacturers Association:
http://www.midi.org/
MIDI specification:
http://home.roadrunner.com/~jgglatt/
Wikipedia:
http://es.wikipedia.org/wiki/MIDI
99
C A P T U L O 5 Programacin MIDI
Programacin MIDI
5.1 Introduccin
Una vez examinados los conceptos bsicos sobre la tecnologa MIDI es momento de
programar el sistema para modificar en tiempo real eventos y mensajes. De esta forma,
es posible realizar aplicaciones que se ajusten a las demandas actuales de edicin de
msica, as como programas de control de dispositivos a travs de mensajes MIDI.
La programacin MIDI se ha vuelto fundamental en la programacin de sistemas, pues
se utiliza en un amplio rango de aplicaciones, desde investigacin hasta videojuegos.
Actualmente se hace necesaria alguna herramienta que permita a los ingenieros y
programadores desarrollar software musical y de acceso a las funciones bsicas de los
dispositivos MIDI. De esta manera, se consigue una abstraccin del software de bajo
nivel, proveyendo una arquitectura orientada a objetos y estratificada que permita el
diseo de software robusto y complejo compuesto por una gran cantidad de
componentes.
En los principios de los aos 90, desarrollar una aplicacin de acceso a MIDI sobre
una plataforma de 16 bits como era Atari (muy utilizado en la industria en aquella
poca), supona desarrollar una aplicacin basada en una ingeniera de software no
orientada a objetos, pero estructurada y modular, implementada en un lenguaje como C
donde el acceso al hardware MIDI del computador se haca a travs de funciones de
envi de bytes a puertos, y en su extremo, programando directamente en ensamblador.
Posteriormente, con la aparicin de los sistemas operativos modernos de 16 y 32 bits
como Windows, Linux y Mac/OS, han provisto una API (Interfaz de Programacin de
Aplicaciones) al servicio de los programadores que, adems de abstraer la complejidad
del acceso al hardware (manejado por las capas de E/S y la mquina virtual del sistema
operativo) proporciona un conjunto de servicios para acceder a todas las funciones que
MIDI posee. La ventaja de este enfoque moderno permite desarrollar software MIDI
que funcionar con cualquier fabricante de hardware sin la necesidad de modificar el
cdigo fuente del programa.
Actualmente en Windows existe la posibilidad de desarrollar aplicaciones MIDI
utilizando dos APIs diferentes: la Windows Multmedia API y la API DirectMusic de
DirectX. En este estudio nos centraremos en esta ltima.
Otras libreras MIDI de alto nivel profesionales para C++ existentes en Internet son:
101
C A P T U L O 5 Programacin MIDI
102
C A P T U L O 5 Programacin MIDI
103
C A P T U L O 5 Programacin MIDI
104
C A P T U L O 5 Programacin MIDI
105
C A P T U L O 5 Programacin MIDI
5.3.2 Esquema de la arquitectura DirectMIDI
El ncleo principal de la librera est basado en sus diez clases relacionadas que
definen los diferentes objetos involucrados en una aplicacin basada en MIDI y que
encapsulan el cdigo para llevarlo a cabo.
El siguiente diagrama de colaboracin muestra los objetos creados por una aplicacin
que usa DirectMIDI:
Exceptions
CMasterClock
CInputPort
CReceiver
CDirectMusic
CDLSLoader
CCollection1..i
COutputPort
CInstrument1..j
Initialize
DownLoad / UnLoad
DirectMusic
main
objects
MIDI ports
CDMusicException
CSampleInstrument
1..n
Exception
handling
106
C A P T U L O 5 Programacin MIDI
proporciona funciones de ayuda para ajustar envolventes, LFOs (Osciladores de baja
frecuencia) y regiones (zonas activas del teclado) antes de descargarlos al puerto de
salida.
Finalmente, el objeto CDMusicException maneja todas las excepciones producidas en la
aplicacin y muestra informacin detallada sobre el problema que gener el error.
5.3.3 Comenzando la aplicacin
5.3.3.1 Primer paso: Configurar el entorno de desarrollo
Es posible comenzar la aplicacin en muchos tipos diferentes de proyectos con
Visual Studio y la librera DirectMIDI, tales como una aplicacin MFC, Win32 bsica o
Win32 en modo consola1.
Para poder compilar una aplicacin DirectMIDI necesitamos aadir al proyecto los
siguientes ficheros cabecera: CDirectMidi.h, CDirectBase.h y CMidiPart.h. Por ltimo
es necesario aadir tambin al proyecto todos los ficheros .cpp que aparecen dentro del
directorio directmidi.
Tambin se requiere tener instalada una versin actualizada del SDK de DirectX, en
este caso se ha utilizado la versin 9.0c. Finalmente necesitamos aadir al IDE de
Visual C++ las rutas de las dependencias (.lib) y ficheros cabecera (.h) del SDK de
DirectX, que normalmente se encuentran localizados en los directorios lib que incluye
el paquete de instalacin.
5.3.3.2 Segundo paso: Las primeras lneas de cdigo
El compilador debera saber cual es el cdigo externo que se est utilizando en el
fichero .cpp actual de trabajo. Por ello se debe utilizar la directiva #include para indicar
al compilador qu otros recursos fuente son necesarios para la compilacin. Las
cabeceras (includes) requeridas se muestran en el siguiente cdigo:
// Cabeceras ANSI I/0
#include <conio.h>
#include <iostream>
#include <math.h>
// La librera DirectMIDI
#include ".\\DirectMidi\\CDirectMidi.h"
// Inclusin de
#pragma comment
#pragma comment
#pragma comment
#pragma comment
107
C A P T U L O 5 Programacin MIDI
const int SYSTEM_EXCLUSIVE_MEM = 48000;
// Define PI
const double PI = 3.1415926;
La directiva #pragma comment indica al linkador que cree un fichero obj con las
libreras necesarias. Las ltimas lneas de cdigo indicadas anteriormente contienen
constantes simblicas necesarias para el ejemplo.
5.3.3.3 Tercer paso: preparando la captura de msica
La clase CInputPort es la responsable de manejar eventos de entrada MIDI. Estos
eventos MIDI son capturados por un thread que invoca a dos mtodos virtuales puros
sobrecargados de la clase CReceiver; dependiendo del tipo de dato MIDI llegado al
puerto. Estos dos diferentes tipos de datos pueden ser: datos MIDI no estructurados (en
forma de Sistema Exclusivo) y datos MIDI estructurados (mensajes MIDI Standard
1.0).
Para sobrecargar estas funciones virtuales puras, es necesario derivar una clase de
CReceiver como se muestra en el siguiente fragmento de cdigo:
// Clase heredada de CReceiver
class CDMReceiver:public CReceiver
{
public:
// Funciones sobrecargadas
void RecvMidiMsg(REFERENCE_TIME rt,DWORD dwChannel,DWORD
dwBytesRead,BYTE *lpBuffer);
void RecvMidiMsg(REFERENCE_TIME rt,DWORD dwChannel,DWORD dwMsg);
};
Una vez realizada esta operacin, podemos implementar parte del cdigo de
procesamiento de eventos:
// Funcin sobrecargada para la captura de datos en Sistema Exclusivo
void CDMReceiver::RecvMidiMsg(REFERENCE_TIME lprt,DWORD
dwChannel,DWORD dwBytesRead,BYTE *lpBuffer)
{
DWORD dwBytecount;
// Imprime el buffer recibido
for (dwBytecount = 0;dwBytecount < dwBytesRead;dwBytecount++)
{
cout.width(2);
cout.precision(2);
cout.fill('0');
cout << hex <<static_cast<int>(lpBuffer[dwBytecount])<< "
";
if ((dwBytecount % 20) == 0) cout << endl;
if (lpBuffer[dwBytecount] == END_SYS_EX)
cout << "\nMemoria del sistema volcada" << endl;
108
C A P T U L O 5 Programacin MIDI
}
}
La primera funcin lee los datos del buffer en formato Sistema Exclusivo, imprime
los valores en base numrica hexadecimal y detecta cundo el sintetizador alcanza el
final del volcado de datos (el byte 0xF7 de fin de datos exclusivos). Es importante saber
que no todos los datos SysEx son recibidos en una nica llamada RecvMidiMsg, se
pueden producir mltiples llamadas consecutivas a esta funcin miembro.
La segunda funcin sobregcargada gestiona mensajes estndar MIDI, tales como
note on o cambio de programa, en formato de doble palabra. Si se necesita parsear el
mensaje en partes se debe usar el mtodo esttico CInputPort::DecodeMidiMsg para
extraer cada byte componente MIDI.
5.3.3.4 Cuarto paso: inicilizando objetos
En este paso se declaran los principales objetos que sern usados a lo largo de la
aplicacin. Son lo siguientes:
int main(int argc, char* argv[])
{
CDirectMusic CDMusic;
CInputPort
CInPort;
CDMReceiver Receiver;
COutputPort COutPort;
CDLSLoader
CLoader;
CCollection CCollectionA,CCollectionB;
CInstrument CInstrument1,CInstrument2;
CSampleInstrument CSample1,CSample2;
109
C A P T U L O 5 Programacin MIDI
CDMReceiver que es una clase derivada de CReciever y que implementa las funciones
sobrecargadas vistas en el aparatado anterior. El objeto COutputPort es el responsable
de enviar datos al dispositivo y de descargar datos en el puerto. Los ltimos objetos
gestionan los sonidos descargables que sern comentados en el siguiente paso.
Ahora es posible comenzar a llamar a los mtodos y activar todo el sistema MIDI. A
continuacin se explica como conseguir este propsito:
try
{
// Inicializa DirectMusic
CDMusic.Initialize();
// Inicializa los puertos dado un objeto gestor de DirectMusic
COutPort.Initialize(CDMusic);
CInPort.Initialize(CDMusic);
El siguiente fragmento de cdigo muestra cmo activar los puertos de entrada y salida:
// Etructura de informacin para el puerto
INFOPORT PortInfo;
DWORD dwPortCount = 0;
//Seleccin del sintetizador software
do
COutPort.GetPortInfo(++dwPortCount,&PortInfo);
while (!(PortInfo.dwFlags & DMUS_PC_SOFTWARESYNTH));
COutPort.SetPortParams(0,0,1,SET_REVERB | SET_CHORUS,44100);
COutPort.ActivatePort(&PortInfo,32);
// Activacin del puerto de salida a partir de la estructura de
informacin
cout << "\nPuerto de salida seleccionado: " <<
PortInfo.szPortDescription << endl;
// Activacin del puerto de entrada, selecciona el primero (por
defecto)
CInPort.GetPortInfo(1,&PortInfo);
CInPort.ActivatePort(&PortInfo,SYSTEM_EXCLUSIVE_MEM);
// Activa el objeto receptor
CInPort.SetReceiver(Receiver);
Las primeras lneas enumeran todos los puertos de salida y seleccionan el primer
sintetizador software existente en el sistema, dado un nmero desde 1 hasta el valor de
COutputPort::GetNumPorts en el primer parmetro de COutputPort::GetPortInfo.
110
C A P T U L O 5 Programacin MIDI
Antes de llamar a COutputPort::ActivatePort necesitamos llamar al mtodo
COutputPort::SetPortParams para indicar el tipo de caractersticas que se necesitan en
el puerto de salida (si se pasa el valor cero como parmetro, se asumir la configuracin
por defecto para ese parmetro). Posteriormente se llamar a la funcin
COutputPort::ActivatePort pasando un puntero a una estructura INFOPORT para
activar el puerto de salida, usando los parmetros del nmero de grupo de canales y una
frecuencia de muestreo pasada en la llamada a COutputPort::SetPortParams. El
parmetro de canal de grupo es el nmero de grupos de canales MIDI para ser utilizados
en el puerto software, cada grupo de canal es un conjunto de 16 canales MIDI.
Uno de los parmetros configurables ms importantes en el mtodo
COutputPort::SetPortParams es el parmetro de la frecuencia de muestreo, que es la
frecuencia en Hertzios que se necesita para establecer la calidad del sonido en el puerto
de salida. En este caso se asumen 44100 Hz como frecuencia de muestreo.
En las ltimas tres lneas se selecciona el puerto de entrada MIDI para la captura de
mensajes, realizando operaciones similares. En este caso no se lleva a cabo ninguna
enumeracin, se limita a seleccionar el primer puerto de entrada por defecto. Es
importante advertir que hay un segundo parmetro en el mtodo
CInputPort::ActivatePort que indica el tamao de memoria mximo reservado para
albergar datos en formato de sistema exclusivo. En este caso slo se reservan 46.8
Kilobytes. Si se deja este parmetro opcional, el valor por defecto ser 32 bytes,
suficiente espacio para recibir datos MIDI estructurados estndar.
Finalmente, se establece un objeto receiver por medio de una llamada al mtodo
CInputPort::SetReceiver. Si cerramos la llave de sentencia principal y se ejecuta la
aplicacin se obtendr la siguiente salida:
Figura 5.4
5.3.3.5 Quinto paso: comenzar la captura de msica
Capturar datos musicales desde un teclado externo es muy simple tan pronto como
se haya inicializado el puerto de entrada. Si reservamos espacio para recibir datos en
sistema exclusivo en la llamada a CInputPort::ActivatePort, ahora la aplicacin estar
preparada para manejar todos los eventos de entrada generados por un teclado
controlador o un sintetizador. El siguiente cdigo explica como realizar la captura:
//Activa la recepcin de mensajes de entrada
CInPort.ActivateNotification();
cout << "Notificacion activada" << endl;
// Redirige mensajes del canal global 0 al canal de destino
global 0
CInPort.SetThru(0,0,0,COutPort);
111
C A P T U L O 5 Programacin MIDI
Otra caracterstica de DirectMIDI es la redireccin. Usando la redireccin (MIDI thru)
se pueden pasar mensajes MIDI desde un puerto de entrada activado a otro puerto de
salida especificando un canal de grupo y el canal global de origen y de destino donde
los mensajes sern redireccionados.
La siguiente salida muestra un volcado de datos en sistema exclusivo y una captura de
datos MIDI estndar estructurados:
Figura 5.5
5.3.3.6 Sexto paso: aumentando el lmite de instrumentos
DirectMIDI soporta la carga de mltiples sonidos almacenados en ficheros DLS
(Downloadable sound files). Esta tecnologa es el estndar de los fabricantes MIDI para
un formato de fuentes de sonido en el estado del arte de la tecnologa multimedia. El
actual formato DLS2 especifica todas las definiciones de los instrumentos: muestras,
LFOs, filtros paso bajo, bucles y generadores de evolvente que sern descargados y
renderizados en un puerto que soporte estos requisitos.
DirectMIDI soporta dos tipos de operaciones DLS: DLS de alto nivel y DLS de bajo
nivel. Ambas prestaciones se comentan a continuacin.
El DLS de alto nivel es la forma de manejar instrumentos de formas de onda que
pueden ser almacenados en formatos DLS 1.0 y DLS 2.0. Estos ficheros pueden ser
creados por una aplicacin como DirectMusic Producer que permite configurar
visualmente un amplio rango de parmetros antes mencionados. El DLS de bajo nivel
permite descarga directa de bytes de datos en formato DLS 1.0 a un puerto sintetizador,
proporcionando parmetros de articulacin y regiones para el instrumento antes de la
decarga.
DLS de alto nivel:
Utilizar ficheros DLS (.dls) en una aplicacin DirectMIDI resulta flexible y sencillo.
Para este propsito debemos declarar un objeto del tipo CDLSLoader con el fin de
realizar la carga y la descarga de ficheros a la librera. Adems de este objeto, es
necesario declarar otro objeto del tipo CCollection que es un contenedor que permite
albergar objetos del tipo Cinstrument, que son la instancia ltima de mantener una
referencia al instrumento DLS. El cdigo mostrado a continuacin explica como llevar a
cabo esta tarea:
// Inicializa el objeto loader
CLoader.Initialize();
// Carga el primer fichero DLS
CLoader.LoadDLS(_T(".\\media\\sample.dls"),CCollectionA);
// Carga la coleccin GM/GS por defecto del sintetizador software
112
C A P T U L O 5 Programacin MIDI
CLoader.LoadDLS(NULL,CCollectionB);
113
C A P T U L O 5 Programacin MIDI
cout << "Tocando el instrumento 1:" << CInstrument1.m_strInstName <<
endl;
cout << "Presione una tecla para reproducir el segundo instrumento..."
<< endl;
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(PATCH_CHANGE,0,0,0),0)
;
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(NOTE_ON,0,40,127),0);
getch();
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(NOTE_OFF,0,40,0),0);
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(PATCH_CHANGE,0,1,0),0)
;
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(NOTE_ON,0,60,127),0);
cout << "Tocando el instrumento 2:" << CInstrument2.m_strInstName <<
endl;
getch();
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(NOTE_OFF,0,60,0),0);
114
C A P T U L O 5 Programacin MIDI
La siguiente imagen muestra la salida del programa que se ha comentado previamente:
Figura 5.6
DLS de bajo nivel:
DirectMIDI 2.3 permite a una aplicacin comunicarse directamente con un puerto
que soporta descarga DLS. Hay dos alternativas para descargar datos al puerto: la
primera es cargar un fichero de forma de onda PCM en formato WAV que contenga los
datos de la muestra, y la segunda es generar la forma de onda en memoria usando
funciones matemticas. En el primer caso, es necesario cargar el fichero WAV mediante
el mtodo esttico CDLSLoader::LoadWaveFile y proporcionar los siguientes tres
parmetros: un puntero a una cadena terminada en null con la ruta del fichero en disco,
una referencia a un objeto CSampleInstrument y un flag indicando el acceso deseado al
fichero. Si el flag es la constante DM_LOAD_FROM_FILE, el fichero es siempre ledo
de disco cuando sea necesario; esto es til para ficheros muy grandes. Si el flag es
DM_USE_MEMORY, el fichero permanece almacenado en memoria dinmica
aumentando la velocidad de acceso.
Respecto a la segunda alternativa antes comentada, puede ser utilizada mediante
el mtodo CSampleInstrument::SetWaveForm, pasando un puntero a un buffer de bytes
y proporcionando una estructura WAVEFORMATEX conteniendo el formato de la
forma de onda. La forma de onda, tanto si se ha ledo de un fichero WAV como si se ha
generado matemticamente, debemos almacenarla en un objeto CSampleInstrument.
El cdigo a continuacin explica estas caractersticas:
// Carga el fichero WAV
CDLSLoader::LoadWaveFile(_T(".\\media\\starbreeze.wav"),CSample1,DM_US
E_MEMORY);
// Lo asigna a un patch
CSample1.SetPatch(2);
// Establece un loop contnuo
CSample1.SetLoop(TRUE);
// Establece parmetros WAV adicionales
CSample1.SetWaveParams(0,0,68,F_WSMP_NO_TRUNCATION);
REGION region;
ARTICPARAMS articparams;
115
C A P T U L O 5 Programacin MIDI
// Inicializa estructuras
ZeroMemory(®ion,sizeof(REGION));
ZeroMemory(&articparams,sizeof(ARTICPARAMS));
=
=
=
=
TimeCents(0.0);
TimeCents(0.0);
PercentUnits(0.0);
TimeCents(0.0);
=
=
=
=
TimeCents(1.275);
TimeCents(0.0);
PercentUnits(100.0);
TimeCents(10.157);
116
C A P T U L O 5 Programacin MIDI
// Establece los parmetros de los instrumentos
CSample2.SetLoop(TRUE);
CSample2.SetRegion(®ion);
CSample2.SetArticulationParams(&articparams);
// Genera los datos de la forma de onda
// Muestras por segundo
DWORD nSamplesPerSec = 44100;
// La duracin de la muestra
double nTimeSec = 1.5;
// Numero de muestras
DWORD nSamples = static_cast<DWORD>(nTimeSec * nSamplesPerSec);
// Frecuencia digital de la forma de onda
double Frequency = 1000.0/nSamplesPerSec;
// Reserva memoria para la forma de onda
WORD *pRawData = new WORD[nSamples];
// Genera la forma de onda
for(DWORD ni = 0;ni < nSamples;ni++)
pRawData[ni]
=
static_cast<WORD>(30000*sin(2.0*PI*Frequency*ni) +
5000*sin(6.0*PI*Frequency*ni) +
1000*sin(10.0*PI*Frequency*ni));
// Formato de la forma de onda
WAVEFORMATEX pwfex = {WAVE_FORMAT_PCM,1,44100,44100,2,16,0};
// Establece el formato de la forma de onda
CSample2.SetWaveForm((BYTE*)pRawData,&pwfex,nSamples*2);
// Reserva memoria para la interfaz
COutPort.AllocateMemory(CSample2);
//Descarga instruemento al puerto
COutPort.DownloadInstrument(CSample2);
COutPort.SendMidiMsg(COutputPort::EncodeMidiMsg(PATCH_CHANGE,0,3,0),0)
;
117
C A P T U L O 5 Programacin MIDI
Figura 5.7
5.3.3.7 Sptimo paso: terminar la aplicacin
El ltimo paso de esta secuencia es cerrar la aplicacin de una forma apropiada y
limpia. Un ejemplo de esta funcin de limpieza y terminacin de notificaciones puede
verse en el cdigo siguiente:
// Finaliza la aplicaicn
// Rompe la redireccin
CInPort.BreakThru(0,0,0);
// Finaliza la notificacin
CInPort.TerminateNotification();
cout << "\n\nNotificacion terminada" << endl;
cout << "Descargando instrumentos" << endl;
// Descarga las colecciones del objeto Loader
CLoader.UnloadCollection(CCollectionA);
CLoader.UnloadCollection(CCollectionB);
// Descarga los instrumentos del puerto
cout << "Unloading instruments" << endl;
COutPort.UnloadInstrument(CInstrument1);
COutPort.UnloadInstrument(CInstrument2);
// Descarga las muestras de los puertos
COutPort.UnloadInstrument(CSample1);
COutPort.UnloadInstrument(CSample2);
// Libera la memoria reservada
COutPort.DeallocateMemory(CSample1);
COutPort.DeallocateMemory(CSample2);
delete [] pRawData;
cout << "Aplicacin terminada...OK" << endl;
118
C A P T U L O 5 Programacin MIDI
getch();
}
catch (CDMusicException& DMExcp)
{
cout << "\n" << DMExcp.GetErrorDescription() << "\n" << endl;
getch();
}
return 0;
}
119
C A P T U L O 5 Programacin MIDI
Bibliografa y referencias
La Web
DirectMIDI wrapper class library
http://directmidi.sourceforge.net/
MSDN
http://msdn2.microsoft.com/es-es/default.aspx
120
Parte IV
Reproduccin de
formatos de sonido
Reproduccin de formatos
de sonido
6.1 Introduccin
Para desarrollar aplicaciones profesionales y complejas se hace necesario el uso
de abstraccin y modularidad de las funciones de bajo nivel ya vistas en los captulos 2
y 3 de la parte 2. Evidentemente, si requerimos implementar funcionalidades como
mezclar gran cantidad de sonidos o reproducir ficheros de audio conocidos como el
formato mp3, ogg, MIDI, WAV, etc. se nos presenta el problema de necesitar
encapsular y abstraer la complejidad de las funciones COM de DirectX o de la cantidad
de funciones de OpenAL, puesto que si se implementa en la misma capa que la lgica
de negocio de nuestra aplicacin, el resultado ser desastroso. En el caso de desarrollar
una aplicacin de reproduccin de ficheros mp3, sera muy confuso tener que mezclar el
cdigo de procesamiento y decodificacin MPEG con las funciones de DirectSound.
Esto tambin sera aplicable a un videojuego, donde el cdigo y los objetos que
gestionan el motor del juego no podran entremezclarse con cdigo de bajo nivel para
reproducir un efecto o poner una msica de fondo.
La solucin en este caso tendra dos alternativas:
1. Desarrollar por nuestra cuenta una capa software donde se implementara el
cdigo de acceso a los dispositivos de audio(DirectSound, OpenAL), y,
adicionalmente otra capa superior a sta donde se implementara la lgica ms
cercana al usuario como: reproduccin de formatos de sonido conocidos y
objetos de alto nivel para gestionar streams, sonidos cortos, mezclas, efectos,
etc. o
2. Utilizar una librera de software de terceros donde ya se nos provea de estas
funcionalidades antes descritas. La ventaja de este enfoque es la eficiencia de la
reutilizacin y el ahorro del tiempo de desarrollo, puesto que esta parte puede
ser subcontratada a terceras personas. La desventaja, sin embargo, de este
enfoque es el coste de la adquisicin de la licencia para la distribucin al
pblico.
Afortunadamente, en el entorno del software libre existen soluciones muy
aceptables y eficientes que resuelven este problema.
En este captulo se explicar la utilizacin de una librera GNU de software
libre para resolver todos los problemas de una aplicacin de audio profesional.
Esta librera se llama Audiere que se explicar a continuacin.
123
DirectSound
WinMM (Windows Multimedia API)
OSS en Linux y Cygwin
SGI AL en IRIX
Audiere es cdigo fuente abierto y publicado bajo la licencia LGPL. Esto significa
que es posible usar esta librera en productos comerciales siempre y cuando no se
modifique el cdigo fuente. En el caso de modificar el cdigo fuente y liberar una nueva
librera, sta debe ser publicada bajo los trminos de LGPL tambin.
Audiere es una librera portable que ha sido testeada en sistemas como Windows,
Linux i386, Cygwin e IRIX con al menos tres grandes compiladores. La arquitectura de
Audiere es independiente de la codificacin big-endian y little-endian.
124
125
<windows.h>
<conio.h>
<iostream>
"audiere.h"
Figura 6.2
Esta clase base (RefCounted) permite contar referencias de instancias de la clase,
as cuando el contador de referencias llega a cero se libera completamente la memoria
que ocupaba el objeto AudioDevice.
El objeto AudioDevice representa un dispositivo en el sistema que es capaz de abrir y
mezclar varias fuentes de sonido. En Windows, DirectSound sera un ejemplo de un
dispositivo.
126
Figura 6.3
Como en el caso anterior, esta clase tambin hereda de la clase RefCounted para la
gestin de memoria.
Sus mtodos pblicos disponibles al desarrollador son los que a continuacin se
muestran:
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
void
void
bool
void
void
bool
void
float
void
float
void
float
bool
int
void
int
play ()=0
stop ()=0
isPlaying ()=0
reset ()=0
setRepeat (bool repeat)=0
getRepeat ()=0
setVolume (float volume)=0
getVolume ()=0
setPan (float pan)=0
getPan ()=0
setPitchShift (float shift)=0
getPitchShift ()=0
isSeekable ()=0
getLength ()=0
setPosition (int position)=0
getPosition ()=0
Como podemos apreciar, este objeto contiene los mtodos principales para
manejar las funcionalidades bsicas de un sonido: cambiar el volumen, pan, reproducir,
pausar, obtener la posicin de la secuencia, cambiar la frecuencia de reproduccin, etc.
Si a continuacin requerimos cargar un fichero en un objeto OutputStream para
su reproduccin tendremos que recurrir a la funcin global OpenSound que detectar
automticamente el tipo de formato y lo cargar en el objeto como stream o buffer
segn se le indique en el ltimo parmetro mediante los flags true o false.
En el cdigo siguiente se muestra esta situacin:
127
// Carga la msica
OutputStreamPtr stream(OpenSound(device, "..\\media\\OMD Electricity.mp3", true));
if (!stream) {
cout << "Error al cargar musica" << endl;
return 1;
}
128
Es fcil realizar estas operaciones. Como puede intuirse, todos los sonidos que
se reproducen con el mtodo play se mezclan sobre el mismo dispositivo, permitiendo
utilizar un nmero indeterminado de fuentes de sonido. Esto puede ser til para un
videojuego donde varios efectos de sonido se deben mezclar con una banda sonora de
fondo. El mtodo setPan toma valores desde -1.0 (balance a canal izquierdo) a 1.0
(balance a canal derecho), estando en el 0.0 el balance central. Por ltimo, el mtodo
setPitchShift cosigue cambiar la velocidad de reproduccin con valores de 2.0
(reproduce a doble velocidad), 0.5 (reproduce a la mitad de la velocidad) y 1.0
(reproduce normal).
Es de destacar que esta librera tiene una plitica de gestin de memoria muy
avanzada y automtica por lo que puede terminarse la apliacacin sin necesidad de
liberar los recursos manualmente.
6.2.5 Acceso a los datos PCM de un buffer
Uno de los aspectos ms importantes de una librera de audio es poder acceder a
los datos de audio PCM contenidos en un buffer de sonido. Para poder realizar esta
operacin con Audiere es necesario cargar el sonido en un objeto SampleSurce que
adems de ser la fuente para datos PCM permite posicionar el sonido. En la siguiente
imagen se muestra la estructura de esta clase:
129
Figura 6.4
Previo a la obtencin de los datos PCM necesitamos utilizar la clase
SampleBuffer que es un contenedor de muestras de sonido de slo lectura que permite
abrir streams de muestras e iterar sobre ellos. Este objeto es usado en la situacin donde
un sonido muy largo se carga una sola vez en memoria y se redirige en stream varias
veces hacia el dispositivo. Para obtener el objeto que hemos mencionado anteriormente
llamaremos a la funcin global CreateSampleBuffer.
En la siguiente imagen se muestra la estructura de esta clase estndar:
Figura 6.5
Por lo tanto el cdigo para llevar esto a cabo es el siguiente:
#include
#include
#include
#include
<windows.h>
<conio.h>
<iostream>
"audiere.h"
130
131
10 11 12 13 14 15 16 17 18 19 20
10
Figura 6.6
As, por lo tanto, el algoritmo que lleva a cabo esta inversin es el siguiente:
// Array auxiliar para la inversin
WORD *pRawAux = new WORD[sampleSize / 2];
// Indice al penltimo byte de datos
int t = sampleSize / 2 - 1;
// Proceso de inversin
for(int i = 0;i < sampleSize / 2;i++)
{
pRawAux[i] = pRawData[t];
t--;
}
Ya slo falta crear un nuevo objeto SampleBuffer a partir del nuevo array con los
datos invertidos y de ah obtener un objeto SampleSource mediante el mtodo
SampleBuffer::openStream. Por ltimo se pasa este objeto a la funcin global ya
comentada, OpenSound, y se provee un puntero al objeto SampleBuffer que contiene la
muestra invertida. Esta funcin nos devolver definitivamente un puntero a un objeto
OutputStream cuyo destino final es poder ser reproducido.
El cdigo que se muestra a continuacin ilustra estas operaciones:
// Crear un nuevo objeto SampleBuffer para albergar datos
SampleBufferPtr sampleBuffer2 =
CreateSampleBuffer(pRawAux,frame_count,channel_count,sample_rate,sampl
e_format);
if (!sampleBuffer2)
{
cout << "Error al crear objeto SampleBuffer" << endl;
return 1;
}
// Se obtiene un puntero al objeto SampleSource
SampleSourcePtr sampleSource2 = sampleBuffer2->openStream();
// Se libera la memoria de los arrays de datos
delete [] pRawData;
delete [] pRawAux;
// Se crea un objeto de salido de sonido stream
OutputStreamPtr sound2(OpenSound(device,sampleSource2,false));
if (!sound2)
{
cout << "Error al crear el objeto OutputStream" << endl;
return 1;
132
133
134
Normal
Transicin de ventana larga a corta (Start)
3 ventanas cortas (Short)
Transicin de ventana corta a larga (Stop)
Capa
1
2
3
Compresin
4:1
6:1 a 8:1
10:1 a 12:1
Transferencia
384 kbits/s
256 a 192 kbits/s
128 a 112 kbits/s
135
Muestreo
8 Khz
11,025 Khz
22,050 Khz
44,1 Khz
48 Khz
Resolucin
8
8
16
16
16
Modo
Mono
Mono
Estreo
Estreo
Estreo
Tasa transferencia
64 kbps
88 kbps
705,6 kbps
1441,2 kbps
1536 kbps
Ciclo externo: este ciclo se encarga de verificar si el factor de escala para cada
subbanda tiene ms distorsin de la permitida (ruido en la seal codificada),
comparando cada banda del factor de escala con los datos previamente
calculados en el anlisis psicoacstico.
Por ltimo falta empaquetar los datos. Para ello se toman muestras cuantificadas del
banco de filtros, junto a los datos de asignacin de bits/ruido y almacena el audio
codificado y datos adicionales en tramas. Cada trama contiene hasta 1152 muestras de
audio y est formada por un encabezado, junto con un chequeo de deteccin de errores
CRC y datos auxiliares.
136
Cabecera:
id
tamano
formato
deltatime
137
Segmentos de pista:
Cada segmento de pista est compuesto por una cabecera, seguida de una
serie de eventos MIDI. Entre estos eventos se encuentran los comandos, que son
los datos enviados y recibidos por los puertos MIDI.
Cadena de cuatro caracteres que identifica la cabecera del
track. Es MTrk.
Indica el tamao de la pista sin indicar la cabecera, es
decir, el nmero de comandos que contiene.
id
tamano
id[4];
tamano;
setid(const char *id);
*getid();
};
Notas musicales:
Do
0
12
24
36
48
60
72
84
96
108
120
Do#
1
13
25
37
49
61
73
85
97
109
121
Re
2
14
26
38
50
62
74
86
98
110
122
Re#
3
15
27
39
51
63
75
87
99
111
123
Mi
4
16
28
40
52
64
76
88
100
112
124
Fa
5
17
29
41
53
65
77
89
101
113
125
Fa#
6
18
30
42
54
66
78
90
102
114
126
Sol
7
19
31
43
55
67
79
91
103
115
127
Sol#
8
20
32
44
56
68
80
92
104
116
La
9
21
33
45
57
69
81
93
105
117
La#
10
22
34
46
58
70
82
94
106
118
Si
11
23
35
47
59
71
83
95
107
119
138
Eventos:
Estn formados por los comandos de voz y los comandos de modo. Los
primeros constan de un byte de estado seguido de datos dependientes del byte de
estado. Para los 16 posibles canales de GM-1 se utilizan los 4 bits ms bajos del
byte de estado. As, por ejemplo, para indicar que una nota ha sido pulsada o
liberada se utilizara los siguientes bytes de estado:
Byte de estado
0x8....
Significado
Liberacin de nota
0x9....
Pulsacin de nota
Datos
1 byte de nota + 1 byte de
velocidad pulsacin
1 byte de nota + 1 byte de
velocidad pulsacin
Los comandos de modo constan slo de un byte que indica el estado pero no
requieren ningn canal determinado. El comando ms utilizado tiene como
funcin silenciar las notas en todos los canales.
Eventos META:
139
// Dispositivo MIDI
MIDIDevicePtr midi(OpenMIDIDevice(NULL));
if (!midi) {
cout << "Error al crear dispositivo MIDI" << endl;
return 1;
}
MIDIStreamPtr midStream(midi->openStream("../media/SONG_001.mid"));
if (!midStream) {
cout << "Error al cargar fichero MIDI" << endl;
return 1;
}
140
141
142
Bibliografa y referencias
Libros
Diseo y desarrollo Multimedia, Sistemas, Imagen, Sonido y Vdeo Manuel-Alonso
Castro Gil, Antonio Colmenar Santos, Pablo Losada de Dios, Juan Peire Arroba.
Editorial Ra-ma, 2002.
La Web
Wikipedia:
WAV
http://es.wikipedia.org/wiki/Waveform_Audio_Format
AIFF
http://es.wikipedia.org/wiki/AIFF
MP3
http://es.wikipedia.org/wiki/MP3
GM
http://es.wikipedia.org/wiki/General_MIDI
MOD
http://en.wikipedia.org/wiki/MOD_(file_format)
XM
http://en.wikipedia.org/wiki/XM_(file_format)
GM
http://www.lpi.tel.uva.es/~nacho/docencia/ing_ond_1/trabajos_01_02/formatos_audio_
digital/html/midiformat.htm Juan Ignacio Arribas
Audiere documentation:
http://audiere.sourceforge.net/documentation.php
MSDN
http://msdn2.microsoft.com/es-es/default.aspx
143
Parte V
Tratamiento Digital de
Seal
147
No lineales: el audio resultante depende del audio inicial con una relacin que
no es una constante, sino una funcin del mismo. En esta categora se encuadran
la compresin o expansin del rango dinmico, la distorsin y el recorte
(clipping).
Como veremos a continuacin, muchos de los efectos que simulan procesos del
mundo real estn modificados en alguno de sus parmetros por funciones que varan
con el tiempo.
7.2.1 Filtros
Un filtro es un procesado de sonido que tiene como resultado la reduccin o
amplificacin de la seal en alguna banda de frecuencia. El filtrado se consigue
mediante la suma de la seal original con diversas muestras retardadas y multiplicadas
por ciertos coeficientes.
Existen dos categora bsicas para la realizacin de filtros digitales:
IIR (Infinite Impulse Response), o filtro recursivo: en este tipo de filtro la
seal de salida depende de la seal de entrada con diversos retardos y de la seal
de salida retardada, todas ellas multiplicadas por ciertos coeficientes. Al
depender la seal de salida de las muestras retardadas de la misma, se produce
un bucle de realimentacin que mantiene la seal activa de manera infinita. En la
prctica, los coeficientes y la cuantizacin de los datos hacen que la seal
realimentada acabe extinguindose. Tambin es posible que la seal de salida
oscile o se amplifique, pero estos no son efectos deseables en un filtro. Un filtro
IIR responde a la frmula general:
y[n] = b0x[n] + b1x[n-1] + b2x[n-2] + ... a1y[n-1] a2y[n-2] ...
148
Figura 7.1
Figura 7.2
En el caso de un filtro FIR, la seccin de coeficientes ai no existira. Dicha seccin
representa la parte recursiva del filtro, y es responsable de los polos de la funcin de
149
Fundido (fade): el fundido se suele utilizar al inicio de una pieza musical (fadein) o al final (fade-out) para lograr una transicin suave de la msica al silencio
y viceversa. En estos casos se aplica una envolvente exponencial para que,
combinada con la respuesta del odo al volumen, el oyente tenga una impresin
lineal.
Trmolo: el trmolo se utiliza para simular instrumentos musicales en la sntesis
de sonido, y suele ser una envolvente sinusoidal de frecuencia inferior a la
audible.
Envolvente de nota musical: modula la amplitud de la nota en 4 fases: ataque,
decaimiento, sostenido y liberacin. Simula los distintos estados de vibracin
por los que pasa un instrumento musical durante la generacin de una nota. En el
caso de un instrumento de cuerda hay 4 fases, pero en otros puede haber menos.
7.2.3 Retardo
El retardo consiste en generar una copia retrasada del sonido original con el objeto
de mezclarla con ste. La seal retardada se manipula y se mezcla con el sonido original
para generar el efecto deseado.
El retardo es importante en muchos efectos musicales, entre ellos los filtros, pero
tambin otros ms exticos como el flanger y phaser.
150
T=
V
c Sa
Figura 7.3. Nivel sonoro para un recinto con paredes desnudas (rojo) y el mismo
recinto con moqueta (negro).
Phaser: consiste en mezclar el sonido original con una versin del mismo con
desfase constante, es decir, una copia exacta donde todas las frecuencias han
sufrido el mismo desfase. No se trata de un simple retardo temporal, sino de un
filtrado de fase lineal. El resultado es un sonido de aspecto sinttico,
especialmente cuando se usa sobre voces.
Flanger: consiste en mezclar la seal original con una versin que tiene un
retardo variable controlado por otra seal. El resultado de mezclar una seal con
otra versin retardada es que se produce un filtrado en peine debido a la
151
152
n =
x[n]e
jn
n =
Donde x[n] es una seal discreta infinita en el tiempo y X() es una funcin
continua que se repite peridicamente con un intervalo 2. Comnmente se utiliza el
intervalo [-, ] para referirse al rango de frecuencia de la seal discreta. Obsrvese que
el rango de frecuencia es adimensional, es decir, no est referido a ninguna unidad de
medida de frecuencia ya que la seal muestreada en el tiempo tambin es adimensional,
pues al muestrearla se convierte en una sucesin de valores sin escala temporal. Por
tanto, se habla de como la frecuencia normalizada en radianes, aunque tambin se
puede sustituir por 2f, en cuyo caso la frecuencia normalizada representa la relacin
f/fs (fs = frecuencia de muestreo) y su intervalo es de [-0.5, 0.5].
Esta periodicidad es la principal diferencia con la transformada continua de Fourier,
que existe de - a . En este punto es donde debemos enlazar con el captulo 1 de
muestreo de seal. La frecuencia representa la frecuencia de Nyquist de la seal
discreta. Recurdese que el espectro de una seal muestreada se repite peridicamente y
que toda componente frecuencial que se encuentre por encima de la frecuencia de
Nyquist aparece alienada como una frecuencia dentro del rango permitido (figura 7.5).
La explicacin de este efecto de aliasing la tenemos en la propia definicin de la
transformada.
En Tratamiento Digital de Seal la notacin, e-jn tambin se puede representar
como cos(n) + jsen(n), donde j es la unidad imaginaria, tambin representada como
i.
153
X[k ] = x[n]e
2 kn
N
n =0
154
155
Figura 7.8. FFT bsica de 2 puntos, tambin conocida como operacin mariposa.
La esencia del algoritmo Cooley-Tukey es separar la FFT en muestras pares e
impares, de manera que el sumatorio inicial
N 1
X[k ] = x[n]e
2 kn
N
n =0
se transforma en
X[k ] =
N / 2 1
x[2n]e
2 k ( 2 n )
N
N / 2 1
n =0
x[2n + 1]e
2 k ( 2 n +1)
N
n =0
N / 2 1
x[2n]e
2 k
N
2 k ( 2 n )
N
+e
2 k N / 2 1
N
x[2n + 1]e
n =0
2 k ( 2 n )
N
n =0
2 k
N
X[k ] = DFT(pares) + e
DFT(impares)
Dicho coeficiente se denomina factor de alternancia y habitualmente se representa
como WNk . Si la transformada tuviera slo dos muestras (N=2), dicho trmino valdra 1
156
2 kn
N
n =0
157
158
159
160
161
BOOL CAudioPlayerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,
IDM_ABOUTBOX,
strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Establece icono grande
SetIcon(m_hIcon, FALSE); //Establece icono pequeo
// Lectura del fichero WAV
ALWavePlayer.FileName = "C:\\Program Files\\LabPacks\\Visual
C++\\Demos\\AVIFiles\\Demo.wav";
// Redireccin al canal de salida de audio
ALWavePlayer.OutputPin.Connect( ALAudioOut.InputPin );
VCL_Loaded(); // Inicio de los controles Mitov
return TRUE;
}
En este tratado nicamente se utilizar el formato WAV por su calidad; aunque es posible utilizar otros
formatos en Mitov como WMA.
162
in
out
Reproductor
ON / OFF
in
Filtro paso
bajo
out
ON / OFF
in
Filtro paso
banda
out
ON / OFF
in
out
in
Onda
in
Espectro
(FFT)
in
Altavoz del
sistema
out
in
Ecualizador
ON / OFF
163
<CSLScope.h>
<CALWavePlayer.h>
<CALAudioOut.h>
<CALSpectrum.h>
<CSLWaterfall.h>
<CALLowPass.h>
<CALBandPass.h>
<CALHighPass.h>
<CALGraphicEqualizer.h>
<CSLFourier.h>
"afxwin.h"
"afxcmn.h"
// CtdsDlg dialog
class CtdsDlg : public CDialog
{
// Construccin
public:
CtdsDlg(CWnd* pParent = NULL);
// Constructor estndar
// DDX/DDV
// Implementacin
protected:
CTSLWaterfall SLScope; // Scope Waterfall
CTSLScope SLScope2;
// Scope en tiempo
CTSLScope SLScope3;
// Scope para Fourier
// Objetos de SignalLab y AudioLab
CTSLFourier SLFourier;
// Objeto
CTALLowPass SLLowPass;
// Objeto
CTALBandPass SLBandPass; // Objeto
CTALHighPass SLHighPass; // Objeto
CTALGraphicEqualizer SLEqualizer;
CTALWavePlayer ALWavePlayer;
CTALAudioOut ALAudioOut; // Objeto
CTALSpectrum ALSpectrum; // Objeto
164
165
=
=
=
=
false;
false;
false;
false;
SLScope3.Channels.Clear();
SLScope3.Channels.Add();
// Conecta filtro paso bajo con filtro paso banda
SLLowPass.OutputPin.Connect(SLBandPass.InputPin);
// Conecta filtro paso banda con filtro paso alto
SLBandPass.OutputPin.Connect(SLHighPass.InputPin);
// Conecta filtro paso alto con ecualizador
SLHighPass.OutputPin.Connect(SLEqualizer.InputPin);
166
// return TRUE
En las primeras lneas se detalla cmo interconectar los controles Label con los
objetos CTSLScopes a travs de sus handlers de ventana. A continuacin se conecta el
reproductor de audio con el objeto filtro paso bajo.
Para comenzar la aplicacin de una manera clara y comprensible se ha preferido
desactivar por defecto los objetos de los filtros y el ecualizador, de esta manera se
puede observar en el cdigo cmo se establece a false las propiedades Enable de dichos
objetos. A continuacin se inician las frecuencias de corte de los filtros, as como los
coeficientes y frecuencias del ecualizador. Como ltima accin, se procede a
inerconectar los objetos de procesado de seal tal como se ilustr en el digrama de
bloques de la figura 7.12
7.5.4 Comportamiento de los filtros y el ecualizador
La ltima parte de la aplicacin es implementar el comportamiento de los filtros y el
ecualizador. Para implementar los filtros, se ha capturado el mensaje Win32 de
desplazamiento de sliders horizontales con el fin de calcular sus propiedades bsicas, de
esta manera tenemos el siguiente cdigo del mtodo sobrecargado:
// Manejador de mensajes de los sliders horizontales
afx_msg void CtdsDlg::OnHScroll(UINT SBCode,UINT nPos,CScrollBar *SB)
{
// Mensaje del slider paso bajo
if (SB==(CScrollBar *)&m_SliderBajo)
SLLowPass.Frequency = m_SliderBajo.GetPos();
// Mensaje del slider paso banda
else if ((SB==(CScrollBar *)&m_SliderFreqBanda) ||
(SB==(CScrollBar *)&m_SliderAnchoBanda))
{
167
Como se aprecia en el cdigo, tanto para el objeto filtro paso bajo como el filtro
paso alto, nos hemos limitado a aplicar la frecuencia de corte a partir de los valores del
slider. De esta manera el filtro paso bajo obtiene unos valores comprendidos entre los
30Hz y los 10 KHz, y el el filtro paso alto unos valores comprendidos entre 30 Hz y los
15 Khz para sus sliders. Sin embargo, para el filtro paso banda se le ha aplicado la
siguiente ecuacin que expresa las frecuencias de corte:
Frecuenciaalta = frecuenciacentral +
anchobanda
2
Frecuenciabaja = frecuenciacentral
anchobanda
2
if (SB==(CScrollBar *)&m_Slider1)
SLEqualizer.Channels[0].Coefficient
m_Slider1.GetPos()) / 100.0;
else if (SB==(CScrollBar *)&m_Slider2)
SLEqualizer.Channels[1].Coefficient
m_Slider2.GetPos()) / 100.0;
else if (SB==(CScrollBar *)&m_Slider3)
SLEqualizer.Channels[2].Coefficient
m_Slider3.GetPos()) / 100.0;
else if (SB==(CScrollBar *)&m_Slider4)
SLEqualizer.Channels[3].Coefficient
m_Slider4.GetPos()) / 100.0;
168
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
= (200.0 -
De esta forma se calculan los coeficientes para cada canal del ecualizador con la
siguiente ecuacin:
Coeficientecanal =
200 decibeliosbanda
100
169
170
Bibliografa y referencias
referencias
Libros
Programacin con MFC 6.0 Herbert Schildt. Editorial Osborne McGraw-Hill, 1999.
La Web
Mitov documentation
http://www.mitov.com
MSDN
http://msdn2.microsoft.com/es-es/default.aspx
Wikipedia:
Efectos de audio:
http://en.wikipedia.org/wiki/Digital_audio_editor
http://en.wikipedia.org/wiki/Sound_effect
http://paws.kettering.edu/~drussell/demos.html
FFT:
http://en.wikipedia.org/wiki/CooleyTukey_FFT_algorithm
http://en.wikipedia.org/wiki/Butterfly_diagram
171
APNDICE
Apndice
Byte(s) datos
D7----D0
Descripcin
Mensajes de canal
1000cccc
0nnnnnnn
0vvvvvvv
1001cccc
0nnnnnnn
0vvvvvvv
1010cccc
0nnnnnnn
0vvvvvvv
1011cccc
0nnnnnnn
0vvvvvvv
1100cccc
0ppppppp
1101nnnn
0ccccccc
1110nnnn
0lllllll
0mmmmmmm
Evento note-off.
Este evento es enviado cuando finaliza la nota.
(nnnnnnn) es el nmero de la nota.
(vvvvvvv) es la velocidad.
Evento note-on.
Este mensaje se enva cuando comienza una nota
(nnnnnnn) es el nmero de la nota.
Presin sobre la tecla (Aftertouch).
Este mensaje se enva para informar de la velocidad
de presin sobre la tecla.
(nnnnnnn) nmero de la nota.
(vvvvvvv) velocidad.
Cambio de control.
Este mensaje es enviado cuando se cambia un valor
de controlador.
Vase apndice A2.
(ccccccc) nmero de controlador.
(vvvvvvv) nuevo valor.
Cambio de programa
Indica un cambio de programa
(ppppppp) es el nuevo nmero de programa.
Presin del canal (After-touch).
Este mensaje es enviado cuando la presin del canal
cambia. Algunos teclados no soportan esta
caracterstica.
(ccccccc) es el nmero de canal.
Cambio de la rueda de modulacin.
Este mensaje es enviado para indicar un cambio en
la rueda de modulacin. La rueda de modulacin es
medido por el dcimo cuarto bit. El valor central es
2000H.
(llllll) son los 7 bits menos significativos.
(mmmmmm) son los 7 bits ms significativos.
173
APNDICE
1011nnnn
11110000
11110001
11110010
11110011
11110100
11110101
11110110
11110111
174
APNDICE
11111000
11111001
11111010
11111011
11111100
11111101
11111110
11111111
Mensajes de tiempo-real
Reloj de tiempo.
Oscila 24 veces por cuarto de nota cuando la
sincronizacin es requerida.
No definido
Comienzo
Comienza la reproduccin de la secuencia. (Este
mensaje vendr seguido de mensajes de tiempo del
reloj).
Continua.
Continua en el punto donde la secuencia par.
Stop
Para la secuencia actual
No definido
Activa Sensing. El uso de este mensaje es opcional.
Cuando es inicialmente enviado, el receptor
esperar recibir otro mensaje Active Sensing cada
300ms (mximo), o ser asumido que la conexin
ha sido terminada. En la terminacin, el receptor
desactivar todas las voces y volver al modo
normal de operacin (Sensing no activo)
Reset.
Reinicia todos los receptores en el sistema al estado
activado. Este mensaje debera ser usado con
cuidado y preferiblemente bajo control manual.
Particularmente, no debera ser enviado con el
sistema encendido.
175
APNDICE
A2. Lista de mensajes de controladores MIDI 1.0
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
176
Bank select
Modulation wheel
Breath control
Indefinido
Foot controller
Portamento time
Data Entry
Channel Volume
Balance
Indefinido
Pan
Expression Controller
Effect control 1
Effect control 2
Indefinido
Indefinido
General Purpose Controller
General Purpose Controller
General Purpose Controller
General Purpose Controller
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Bank Select
Modulation wheel
Breath control
Indefinido
Foot controller
Portamento time
Data entry
Channel Volume
Balance
Indefinido
Pan
Expression Controller
Effect control 1
Effect control 2
Indefinido
Indefinido
General Purpose Controller
General Purpose Controller
General Purpose Controller
General Purpose Controller
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
#1
#2
#3
#4
#1
#2
#3
#4
APNDICE
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Damper pedal on/off (Sustain)
Portamento on/off
Sustenuto on/off
Soft pedal on/off
Legato Footswitch
Hold 2
Sound Controller 1 (Sound Variation)
Sound Controller 2 (Timbre)
Sound Controller 3 (Release Time)
Sound Controller 4 (Attack Time)
Sound Controller 5 (Brightness)
Sound Controller 6
Sound Controller 7
Sound Controller 8
Sound Controller 9
Sound Controller 10
General Purpose Controller #5
General Purpose Controller #6
General Purpose Controller #7
General Purpose Controller #8
Portamento Control
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Effects 1 Depth
Effects 2 Depth
Effects 3 Depth
Effects 4 Depth
Effects 5 Depth
Data entry +1
Data entry -1
Non-Registered Parameter Number LSB
Non-Registered Parameter Number MSB
Registered Parameter Number LSB
Registered Parameter Number MSB
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
Indefinido
177
APNDICE
116
117
118
119
120
121
122
123
124
125
126
127
178
Indefinido
Indefinido
Indefinido
Indefinido
All Sound Off
Reset All Controllers
Local control on/off
All notes off
Omni mode off (+ all notes off)
Omni mode on (+ all notes off)
Poly mode on/off (+ all notes off)
Poly mode on (incl mono=off +all notes off)
APNDICE
A3. Lista de instrumentos GM (General MIDI)
00 - Piano de cola
acstico
01 - Piano
acstico
brillante
02 - Piano de cola
elctrico
03 - Piano de
cantina
04 - Piano Rhodes
05 - Piano con
"chorus"
06 - Clavicordio
07 - Clavinet
08 - Celesta
09 - Carilln
10 - Caja de
msica
11 - Vibrfono
12 - Marimba
13 - Xilfono
14 - Campanas
tubulares
15 - Salterio
16 - rgano
Hammond
17 - rgano
percusivo
18 - rgano de
rock
19 - rgano de
iglesia
20 - Armonio
21 - Acorden
22 - Armnica
23 - Bandonen
24 - Guitarra
espaola
25 - Guitarra
acstica
26 - Guitarra
elctrica
(jazz)
27 - Guitarra
elctrica
(limpia)
28 - Guitarra
elctrica
32 - Bajo acstico
33 - Bajo elctrico
pulsado
34 - Bajo elctrico
punteado
35 - Bajo sin
trastes
36 - Bajo
golpeado 1
37 - Bajo
golpeado 2
38 - Bajo
sintetizado 1
39 - Bajo
sintetizado 2
40 - Violn
41 - Viola
42 - Violoncello
43 - Contrabajo
44 - Cuerdas con
trmolo
45 - Cuerdas con
pizzicato
46 - Arpa
47 - Timbales
48 - Conjunto de
cuerda 1
49 - Conjunto de
cuerda 2
50 - Cuerdas
sintetizadas
1
51 - Cuerdas
sintetizadas
2
52 - Coro Aahs
53 - Voz Oohs
54 - Voz
sintetizada
55 - xito de
orquesta
56 - Trompeta
57 - Trombn
58 - Tuba
59 - Trompeta con
sordina
60 - Corno
francs
64 - Saxo soprano
65 - Saxo alto
66 - Saxo tenor
67 - Saxo bartono
68 - Oboe
69 - Corno ingls
70 - Fagot
71 - Clarinete
72 - Flautn
73 - Flauta
74 - Flauta dulce
75 - Flauta de pan
76 - Cuello de
botella
77 - Shakuhachi
(flauta
japonesa)
78 - Silbato
79 - Ocarina
80 - Meloda 1
(onda
cuadrada)
81 - Meloda 2
(diente de
sierra)
82 - Meloda 3
(rgano de
vapor)
83 - Meloda 4
(siseo
rgano)
84 - Meloda 5
(charanga)
85 - Meloda 6
(voz)
86 - Meloda 7
(quintas)
87 - Meloda 8
(bajo y
melodas)
88 - Fondo 1
(nueva era)
89 - Fondo 2
(clido)
90 - Fondo 3
(polisintetiz
ador)
91 - Fondo 4
96 - Efecto 1
(lluvia)
97 - Efecto 2
(banda
sonora)
98 - Efecto 3
(cristales)
99 - Efecto 4
(atmsfera)
100 Efecto 5
(brillo)
101 Efecto 6
(duendes)
102 Efecto 7
(ecos)
103 Efecto 8
(ciencia
ficcin)
104 Sitar
105 Banjo
106 Shamisen
107 Koto
108 Kalimba
109 Gaita
110 Violn celta
111 Shanai
112 Campanillas
113 Agog
114 Cajas
metlicas
115 Caja de
madera
116 Caja Taiko
117 Timbal
meldico
118 Caja
sintetizada
119 Platillo
invertido
120 Trasteo de
guitarra
121 Sonido de
respiracin
122 Playa
123 Piada de
pjaro
124 Timbre de
telfono
179
APNDICE
(apagada)
29 - Guitarra
saturada
(overdrive)
30 - Guitarra
distorsionad
a
31 - Armnicos
de guitarra
180
(trompa)
61 - Seccin de
metal
62 - Metales
sintetizados
1
63 - Metales
sintetizados
2
(coro)
92 - Fondo 5 (de
arco)
93 - Fondo 6
(metlico)
94 - Fondo 7
(celestial)
95 - Fondo 8
(escobillas)
125 Helicptero
126 Aplauso
127 Disparo de
fusil
APNDICE
A4. Tabla de frecuencias de notas musicales en Hertzios
Do 1: 65,406
Do# 1: 69,296
Re 1: 73,416
Re# 1: 77,782
Mi 1: 82,407
Fa 1: 87,307
Fa# 1: 92,499
Sol 1: 97,999
Sol#1: 103,826
La 1: 110
La# 1: 116,541
Si 1: 123,471
Do 2: 130,813
Do# 2: 138,591
Re 2: 146,832
Re# 2: 155,563
Mi 2: 164,814
Fa 2: 174,614
Fa# 2: 184,997
Sol 2: 195,998
Sol#2: 207,652
La 2: 220
La# 2: 233,082
Si 2: 246,942
Do 3: 261,626
Do# 3: 277,183
Re 3: 293,665
Re# 3: 311,127
Mi 3: 329,628
Fa 3: 349,228
Fa# 3: 369,994
Sol 3: 391,995
Sol#3: 415,305
La 3: 440
La# 3: 466,164
Si 3: 493,883
Do 4: 523,251
Do# 4: 554,365
Re 4: 587,33
Re# 4: 622,254
Mi 4: 659,255
Fa 4: 698,456
Fa# 4: 739,989
Sol 4: 783,991
Sol#4: 830,609
La 4: 880
La# 4: 932,328
Si 4: 987,767
Do 5: 1046,502
Do# 5: 1108,731
Re 5: 1174,659
Re# 5: 1244,508
Mi 5: 1318,51
Fa 5: 1396,913
Fa# 5: 1479,978
Sol 5: 1567,982
Sol#5: 1661,219
La 5: 1760
La# 5: 1864,655
Si 5: 1975,533
Do 6: 2093,005
Do# 6: 2217,461
Re 6: 2349,318
Re# 6: 2489,016
Mi 6: 2637,02
Fa 6: 2793,826
Fa# 6: 2959,955
Sol 6: 3135,963
Sol#6: 3322,438
La 6: 3520
La# 6: 3729,31
Si 6: 3951,066
Do 7: 4186,009
Do# 7: 4434,922
Re 7: 4698,636
Re# 7: 4978,032
Mi 7: 5274,041
Fa 7: 5587,652
Fa# 7: 5919,911
Sol 7: 6271,927
Sol#7: 6644,875
La 7: 7040
La# 7: 7458,62
Si 7: 7902,133
Do 8: 8372,018
Do# 8: 8869,844
Re 8: 9397,273
Re# 8: 9956,063
Mi 8: 10548,082
Fa 8: 11175,303
Fa# 8: 11839,822
Sol 8: 12543,854
Sol#8: 13289,75
La 8: 14080
La# 8: 14917,24
Si 8: 15804,266
181