instituto polit´ecnico nacional - Página Dr. Maximino Peña Guerrero

Transcripción

instituto polit´ecnico nacional - Página Dr. Maximino Peña Guerrero
INSTITUTO POLITÉCNICO NACIONAL
ESCUELA SUPERIOR DE INGENIERÍA MECANICA Y ELÉCTRICA
DEPARTAMENTO DE INGENIERÍA EN COMUNICACIONES Y ELECTRÓNICA
ACADEMIA DE ACÚSTICA
Diseño Elemental de un Sintetizador de Notas Musicales
TESIS
Que para obtener el Tı́tulo de
Ingeniero en Comunicaciones y Electrónica
Presentan:
Victor Hugo Correa Cid
Iván Guadalupe Contreras Méndez
Asesores:
Dr. Maximino Peña Guerrero
Ing. José de Jesús Negrete Redondo
México D.F.
Octubre 2005
Trabajo de tesis que forma parte de los resultados
obtenidos con nuestro proyecto de investigación, MAN:
Red Internet II de Audio Multimedia con Servidores y
Clientes Incrustados, número de registro 20040733 asignado por la Coordinación General de Posgrado e Investigación del Instituto Politécnico Nacional durante febrero
2004 a marzo 2005, desarrollado en el laboratorio de la
academia de acústica de la ESIME Zacatenco, y dirigido
por el Dr. Maximino Peña Guerrero.
ii
iii
RESUMEN
Actualmente los sintetizadores son instrumentos musicales que generan sonidos
controlando osciladores electrónicos con un teclado de piano, o bien con dispositivos
electrónicos digitales o analógicos. De esta forma es posible crear nuevos sonidos, o
bien sintetizar por ejemplo el sonido de una trompeta, flauta, o un saxofón. Para
lograr un sonido particular, la forma de onda que producen estos osciladores se puede
modificar cambiando los parámetros que definen una nota musical (frecuencia), su
volúmen (amplitud), y el timbre que permite identificar un instrumento de otro (fase
y cantidad de armónicos).
Esta tesis presenta el diseño básico de un sintetizador electrónico digital de notas
musicales. Las caracterı́sticas que lo definen se describen dentro de un programa
que corre en una PC (Personal Computer). Nuestro sintetizador trabaja con base
en las series matemáticas de Fourier. Sus “osciladores” son generadores de formas
de onda simples (funciones seno), los cuales se pueden modificar (timbre de una
nota) con barras y controles gráficos en la pantalla de la computadora. La frecuencia
fundamental (nota) del conjunto de osciladores del sintetizador es controlada con
un teclado virtual de 12 notas, las cuales simulan las teclas fı́sicas de un piano de
concierto.
Los resultados que se obtienen son: nuestro sintetizador funcionando en un ambiente gráfico que genera un programa en Visual C++.NET y que también muestra
una serie de ventanas, las cuales contienen las formas de onda de los osciladores;
ası́mismo, un teclado gráfico y barras que controlan la amplitud y frecuencia de los
osciladores. Por otra parte, el sonido que se produce cuando se activan las teclas
del sintetizador es reproducido con el sistema de audio estándar de la computadora.
Cabe mencionar que sólo utilizamos seis osciladores, pero que esta restricción, no ha
impedido la investigación del funcionamiento básico de dicho dispositivo.
iv
OBJETIVO
Diseñar un sintetizador básico de notas musicales para PC (Personal Computer),
utilizando algoritmos de programación (en Visual C++.NET) y métodos numéricos.
JUSTIFICACIÓN
En la actualidad existen varios tipos de modelos de sintetizadores por hardware,
con los cuales es posible obtener sonidos de diversos instrumentos musicales, sin embargo, para esto se necesita de multiples elementos electrónicos, por lo que pueden
llegar hacer enormes, ocupar grandes espacios, ser estorbosos y poco prácticos para
los usuarios. Al darnos cuenta de lo anterior observamos que un modelo por software
puede igualar o incluso superar a un modelo por hardware, ya que si se cuenta con una
PC, un músico o cualquier persona, puede tener acceso a un sintetizador en lugares
que normalmente no seria posible (avión, tren, autobús, etc.).
v
Agradecimientos
A mis padres:
Marı́a Magdalena Cid Flores y Salomón Correa Medina, quienes con su apoyo
constante me han dado fuerzas para seguir adelante y nunca detenerme. Sé que no
necesito escribir todo lo que significan para mı́, pero quiero que sepan que siempre
estaré para ustedes, ası́ como ustedes siempre han estado para mı́. Nunca olviden que
los amo.
A mis hermanas:
Angélica Correa Cid y Alejandra Correa Cid, les agradezco por mostrarme el
camino para llegar hasta donde estoy, ya que sin su ejemplo y apoyo nunca lo hubiera
logrado. No encuentro palabras para expresar la bendición que significa tener unas
hermanas como ustedes.
A mis profesores:
Agradezco a todos mis profesores, pero en especial al Dr. Maximino Peña Guerrero
y al Ing. José de Jesús Negrete Redondo, quienes me confiaron este trabajo de tesis
y me impulsaron a cumplir con el objetivo. Espero no haberlos defraudado!!!.
A la Virgen de Guadalupe:
Por que siempre estás cuando te necesito y sé que ahı́ seguirás!!!.
Victor Hugo Correa Cid
vi
”El hombre es el único ser de la naturaleza
que tiene conciencia de que va a morir,
por eso —y sólo por eso— tengo un profundo respeto por la raza humana, y creo
que en un futuro será mucho mejor que
en el presente. Aun sabiendo que sus dı́as
estan contados y que todo acabará cuando
menos se lo espera, hace de la vida una
lucha digna de un ser eterno. Lo que las
personas llaman vanidad —dejar obras,
hijos, hacer que su nombre no se olvide—
yo lo considero la máxima expresión de la
dignidad humana.
Paulo Coelho
El Peregrino (Diario de un mago).
vii
Agradezco infinitamente a Dios por darme la oportunidad de; vivir en este tiempo
y conocer a las personas que han marcado mi vida para siempre. A todas esas personas
gracias, por compartir conmigo momentos de alegrı́as y tristezas.
A mis padres, Julia Méndez y Silvestre Contreras les agradezco el apoyo y paciencia que me han brindando durante todos estos años. Ası́ como también agradezco a
mi hermana Verónica que me brindó su apoyo en lo que necesitaba. Y muy especialmente le agradezco a mi abuela Delfina Hernández (q.p.d), que en vida siempre se
preocupó por mis estudios y mi bienestar. No podı́a faltar toda mi gratitud a, mi tı́a
Marı́a de la Cruz Méndez, a mi tı́o Benito Cureño Méndez y familia.
A mis amigos: Arturo Iñigo, Arturo Nava, Raúl Hernández, Leonel Rios y Denys
Basurto, humildemente les agradezco su confianza, su amistad y su compañı́a durante
todos estos años. De la misma manera agradezco a: Lalo, Ulises, Oscar, Chucho,
Moreno, Hugo, Karla y Cristina, porque con todos ellos compartı́ momentos muy
agradables y siempre conté con ellos en los momentos difı́ciles.
Quiero brindarles toda mi gratitud y respeto a mis profesores, que saben valorar
su profesión y dı́a con dı́a dan lo mejor de sı́ mismos. Muy en especialmente al Dr.
Maximino Peña Guerrero y al Ing. José de Jesús Negrete Redondo, por la confianza
y el apoyo para la realización de esta tesis, igualmente a mis amigos Victor Hugo
Correa y Juan Simúta.
Al Instituto Politécnico Nacional y a la E.S.I.M.E.-Zacatenco... ¡simplemente mil
gracias! porque en ellos no solamente aprendı́; matemáticas y fı́sica, también aprendı́;
que un buen ser humano es; humilde, sencillo y respeta al prójimo.
Iván Guadalupe Contreras Méndez.
viii
Quien
ama
la
ciencia,
la
corrección ama; mas aquel que es
como
bruto,
odia
el
reproche.
(Proverbios 12, 1)
Para el necio es recto su camino; mas
el hombre prudente oye el consejo.
(Proverbios 12, 15)
Hay quienes pretenden ser ricos,
sin tener nada; hay quienes pretenden ser pobres, siendo muy ricos.
(Proverbios 13, 7)
ix
Índice general
1. Introducción
1.1. Antecedentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2. Nuestro trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3. Organización del documento . . . . . . . . . . . . . . . . . . . . . . .
2. Instrumentos Musicales Electrónicos y Digitales
2.1. Principios de funcionamiento . . . . . . . . . . . .
2.2. El sintetizador como instrumento musical . . . . .
2.3. Métodos de programación de nuestro sistema . . .
2.4. Resumen . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
3. Aspectos del Diseño de Sintetizadores de Música
3.1. Generadores electrónicos de formas de onda . . . .
3.2. Tipos de osciladores . . . . . . . . . . . . . . . . .
3.3. Anatomı́a de un sintetizador . . . . . . . . . . . . .
3.4. Resumen . . . . . . . . . . . . . . . . . . . . . . . .
4. Diseño de Nuestro Sintetizador de Notas
4.1. Computadoras digitales . . . . . . . . . . . . .
4.2. Estructuras del controlador (driver) de sonido
4.3. Programación de las funciones de onda . . . .
4.4. Visualización de las formas de onda . . . . . .
4.5. Anatomı́a de una tarjeta de sonido . . . . . .
4.6. Resumen . . . . . . . . . . . . . . . . . . . . .
5. Diseño de la Interfaz Gráfica
5.1. Pixeles y mapas de bits . . . . . . . . . . . . .
5.2. Ventanas, barras, y otros controles gráficos . .
5.3. Programando la interfase gráfica . . . . . . . .
5.4. Programando el controlador driver de sonido .
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
6
7
.
.
.
.
9
9
11
12
16
.
.
.
.
17
17
18
20
23
.
.
.
.
.
.
25
25
27
31
33
35
36
.
.
.
.
37
37
38
38
48
5.5. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6. Pruebas y Resultados
6.1. Ambiente de compilación y generación de
6.2. Aspecto visual del sintetizador . . . . . .
6.3. Control de parámetros del sintetizador .
6.4. Controlando los armónicos . . . . . . . .
6.5. Control del teclado . . . . . . . . . . . .
6.6. Resumen . . . . . . . . . . . . . . . . . .
50
.
.
.
.
.
.
51
51
53
54
55
57
58
7. Conclusiones y Trabajos Futuros
7.1. Trabajos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
61
2
código
. . . .
. . . .
. . . .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Índice de figuras
3.1. Sintetizador elemental . . . . . . . . . . . . . . . . . . . . . . . . . .
21
4.1. Número de muestras por cada ciclo. . . . . . . . . . . .
4.2. Representación gráfica de la Serie de Fourier, mediante
diseñado en C++. . . . . . . . . . . . . . . . . . . . . .
4.3. Diagrama a bloques de una tarjeta de sonido. . . . . .
. . . . . .
programa
. . . . . .
. . . . . .
32
5.1. Jerarquı́a de ventanas. . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2. Interfaz gráfica de la aplicación. . . . . . . . . . . . . . . . . . . . . .
39
40
6.1.
6.2.
6.3.
6.4.
6.5.
6.6.
6.7.
6.8.
52
53
54
55
56
56
57
58
. .
un
. .
. .
Vista principal del sintetizador. . . . . . . . . . . . . . . . . . . . .
Valores mı́nimo, central y máximo de la barra horizontal. . . . . . .
Barras de desplazamiento verticales, con una amplitud modificada. .
Tercer armónico con amplitud modificada. . . . . . . . . . . . . . .
Quinto armónico con amplitud modificada. . . . . . . . . . . . . . .
Todos los armónicos modificados . . . . . . . . . . . . . . . . . . . .
Vista del Teclado. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
a)Tecla en reposo. b)Tecla pulsada. . . . . . . . . . . . . . . . . . .
3
.
.
.
.
.
.
.
.
34
36
Índice de tablas
6.1. Valores de las barras de desplazamiento . . . . . . . . . . . . . . . . .
4
58
Capı́tulo 1
Introducción
1.1.
Antecedentes
Un dispositivo que genera los sonidos a partir de la combinación de elementos
simples (normalmente señales periódicas y funciones matemáticas) es conocido como
sintetizador. Con este artefacto se pueden crear nuevos sonidos ası́ como reproducir
los de los instrumentos musicales conocidos, la forma de la onda generada, es alterada en su duración, altura y timbre, mediante el uso de dispositivos tales como
amplificadores, mezcladores, filtros, reverberadores, secuenciadores y moduladores de
frecuencia. Para encontrar los primeros sintetizadores de sonido debemos remontarnos
a 1906, año de invención del Telharmonium, mientras que en los años veinte surge el
Theremin. Estos primeros aparatos eran analógicos y utilizaban osciladores eléctricos
como fuente sonora.
Sin embargo fue en la década de 1960 que apareció uno de los sintetizadores más
famosos, el Moog, llamado ası́ por su inventor, el ingeniero estadounidense Robert
Moog. Este se controla con uno o más teclados y con él es posible crear un número
casi infinito de sonidos y pueden imitarse muchos instrumentos. El sintetizador Moog
no tiene memoria, lo que significa mover cerca de 60 botones para lograr el sonido
de algún instrumento, como un violı́n o una trompeta. Las posiciones de los botones
se apuntan en un cuaderno, ya que para hacer el sonido de un instrumento deben
desorganizarse las posiciones del instrumento anterior.
5
Una de las controversias que se han tenido en los últimos años, es si los sintetizadores por software podı́an desplazar a los modelos por hardware. Viendo que el
sonido de algunos modelos software, los han ido igualando, se decı́a que la falta de
control sobre sus parámetros, el hecho de tener fastuosos interfaces de pantalla pero
ningún potenciómetro a mano, los ponı́an en clara desventaja. Sin embargo hay que
decir que la mayorı́a de los modelos digitales y estaciones de trabajo que se usan
actualmente, tienen complejas arquitecturas y grandes cantidades de parámetros que
imposibilitan construir paneles de potenciómetros que cubran todas las opciones (a
no ser que midiesen un par de metros cuadrados). De esta manera hay que tener
en cuenta, que en general las arquitecturas de los modelos por software actuales son
mucho más amplias y ambiciosas.
1.2.
Nuestro trabajo
Lo anterior expuesto nos llevó a crear el diseño básico de un sintetizador elemental para PC (Personal Computer), el cual se basa en la manipulación de señales
analógicas, llamadas formas de onda, que en nuestro caso serán de tipo sinusoidal.
Estas señales serán manipuladas mediante un proceso para obtener sonido por medio
de una sı́ntesis, llamado series de fourier. De esta manera sumando las salidas de
varios osciladores de forma de onda sinusoidal, se obtendrán diversos timbres, según
la amplitud que se le da a la frecuencia fundamental (la nota) y sus armónicos (notas
múltiplos de la fundamental), los cuales permiten diferenciar un timbre de otro, por
ejemplo un violı́n de una flauta.
En la actualidad existen diferentes software que se enfocan en el desarrollo de
aplicaciones para Windows, tales como: C, C++, Borland, entre otros. Sin embargo,
las aplicaciones utilizadas en Windows, eran sencillas de usar para el usuario pero
difı́ciles de desarrollar para el programador. Por este motivo en febrero de 1993,
fue introducido uno de los mas conocidos y eficientes lenguajes de programación
orientada a objetos, Visual C++, el cual ha ido evolucionando hasta llegar a su más
6
reciente versión, Visual C++ .Net o versión 7 del mismo. Desarrollar aplicaciones en
un entorno de este tipo se vuelve una tarea un poco más sencilla, el programador puede
crear la interfaz gráfica (ventanas, barras de desplazamiento, botones, entre otras
cosas), sin necesidad de escribir nada de código. Tomando en cuenta lo anterior hemos
decidido usar para el desarrollo de este sintetizador, el software antes mencionado,
Visual C++ .Net.
1.3.
Organización del documento
Esta tesis se encuentra estructurada de la siguiente manera. El capı́tulo 2 presenta
los conceptos básicos que deben ser tomados en cuenta, para el desarrollo de nuestro
sintetizador, tales como: sonido, tipos de sı́ntesis, generación de sonido en PC’s, entre
otros. El capı́tulo 3 presenta los aspectos de diseño para el desarrollo de nuestro
sintetizador, de esta forma tomamos en cuenta el funcionamiento de los dispositivos
que pueden ser empleados para generar formas de onda (osciladores), tales como: los
tipo Hartley, Colpitts, LC, RC, VCO, 555, entre otros. Cabe mencionar que los diseños
anteriores son de caracter explicativo, ya que no serán implementados en nuestro
diseño. El capı́tulo 4 presenta el proceso de diseño de las sı́ntesis de ondas, en el que
veremos las estructuras de audio más importantes utilizadas para la comunicación
entre el software y la tarjeta de sonido de la PC. Al mismo tiempo desarrollaremos
y explicaremos la función encargada de realizar la sı́ntesis de ondas, almacenándolas
en un buffer de audio. El capı́tulo 5 presenta el diseño de la interfaz gráfica, donde se
explicará paso a paso los diferentes puntos a seguir para el desarrollo del software y
definiremos algunos conceptos básicos tales como pı́xel, mapa de bits, recurso gráfico,
entre otros, necesarios para su mejor comprensión. El capı́tulo 6 presenta algunas
pruebas y resultados de nuestro proyecto final, describiremos su operación y la forma
de obtener un archivo ejecutable del proyecto, para que este sea universal. Por último
el capı́tulo 7 presenta las conclusiones a las que llegamos al termino de este proyecto,
ası́ como algunas propuestas para la mejora del mismo.
7
Φ
8
Capı́tulo 2
Instrumentos Musicales
Electrónicos y Digitales
En este capı́tulo trataremos algunos conceptos que son básicos para la comprensión
de los demás capı́tulos, como son ondas sonoras, caracterı́sticas del sonido, armónicos,
análisis de Fourier, sintetizadores, técnicas de sı́ntesis, muestreo, modulación, generación de sonido en PC (Personal Computer), captura de sonido y lenguajes de
programación.
2.1.
Principios de funcionamiento
Cuando un cuerpo es excitado de alguna manera, las moléculas de aire que se
encuentran en contacto con la fuente se ponen en movimiento al mismo tiempo y
con la misma amplitud y fase que las superficies de dicha fuente, a esto se le conoce
como Sonido. A partir de este movimiento se desarrolla una onda sonora, cuando al
moverse las moléculas que están en contacto con la fuente, ponen en movimiento a las
que se encuentran a continuación y éstas a su vez a las siguientes, produciendo una
reacción en cadena y que continúa de acuerdo al movimiento de la fuente en ambas
direcciones, generando aumento y disminución de presión, haciendo que su efecto se
propague en todas direcciones.
Las principales caracterı́sticas del sonido son: frecuencia, amplitud, tono y timbre.
La frecuencia, es el número de oscilaciones que se cumplen en un segundo dentro de
9
un movimiento vibratorio y es expresada en Hertz (Hz.), las frecuencias que percibe
el oı́do humano se encuentran entre los 20 Hz y 20,000 Hz. La amplitud esta definida,
como el grado de movimiento de las moléculas de aire en una onda. El tono nos permite
diferenciar un sonido grave de un sonido agudo, mientras más ciclos completos ocurren
más alto será el tono. El timbre, es el atributo de la sensación auditiva por el cual,
un escucha puede juzgar dos sonidos similares como diferentes entre sı́ [1].
Existen diferentes formas de onda, como la onda sinusoidal, cuadrada, diente
de sierra, etc, estas ondas nos permiten distinguir una nota musical de la misma
frecuencia e intensidad, producida por instrumentos diferentes. La forma de onda
viene determinada por una serie de vibraciones subsidiarias, que acompañan a una
vibración primaria o fundamental del movimiento ondulatorio (especialmente en los
instrumentos musicales) llamados armónicos. Normalmente al hacer vibrar un cuerpo,
no obtenemos un sonido puro, sino un sonido compuesto de sonidos de diferentes
frecuencias. La frecuencia de los armónicos, siempre es un múltiplo de la frecuencia
más baja, llamada frecuencia fundamental o primer armónico.
En 1807, el matemático francés Joseph Fourier (1768-1830), envió un artı́culo a
la Academia de Ciencias en Parı́s. En él, presentaba una descripción matemática de
problemas relacionados con la conducción de calor. Una de las sorprendentes ramificaciones del trabajo de Fourier, fue que muchas de las funciones más conocidas podı́an
expandirse en series infinitas e integrales que involucraban funciones trigonométricas,
llamadas series de Fourier. La idea es importante hoy en dı́a, en el modelamiento de
muchos de los fenómenos en Fı́sica e Ingenierı́a.
Un método matemático para obtener el espectro de potencia, como función de la
frecuencia para una forma de onda de la señal dada, es la transformada de Fourier,
que es utilizada para transformar una señal representada en el dominio del tiempo, al
dominio de la frecuencia, sin alterar su contenido de información, solamente es una
forma diferente de representarla.
Astrónomo y matemático alemán nacido en Minden, Friedrich Bessel (1784-1846),
10
introdujo en matemáticas las funciones de Bessel como solución a ciertas ecuaciones
diferenciales. Las funciones son de gran importancia para determinar la distribución
y el flujo del calor o la electricidad, y para la solución de problemas relacionados con
el movimiento ondulatorio, la elasticidad y la hidrodinámica.
Llamadas funciones Splines, su gran popularidad se debe a que sus propiedades las
hacen ideales, para atacar problemas muy variados en diversas áreas de la matemática,
también son muy útiles en el diseño gráfico y en la solución numérica de ecuaciones
diferenciales.
Constituye un proceso importante en diferentes áreas de la ingenierı́a, la convolución representa una operación y un concepto matemático, que constituyen una
aplicación que permite la obtención, de una solución real que plantea la transmisión de
información, la interacción de dos cantidades en el tiempo y espacio, es la convolución
de esas dos cantidades.
2.2.
El sintetizador como instrumento musical
Aparecido en la década de los sesentas, el sintetizador, es un dispositivo electrónico
digital similar a un piano, que puede generar una gran variedad de sonidos musicales.
Se denominan sintetizadores porque obtienen el sonido por medio de una sı́ntesis
(proceso artificial), la cual se puede realizar por diferentes medios. Por ejemplo, los
primeros sintetizadores se basaban en la teorı́a del análisis de Fourier y sumando
las salidas de varios osciladores de forma de onda senoidal, obtenı́an diversos timbres
según la amplitud que se le daba a la frecuencia fundamental (la nota) y sus armónicos.
También utilizaban formas de onda del tipo diente de sierra, triangular y cuadrada,
cada una de las cuales tiene un rico y particular contenido armónico [7].
Robert Moog, construyó el primer sintetizador analógico que aún lleva su nombre,
el clásico Moog, el cual es un generador electrónico de formas de onda, que puede
producir casi cualquier clase de señal periódica de audiofrecuencia.
Actualmente podemos encontrar diversas formas de generar señales de audio, a
11
continuación mencionaremos las más conocidas técnicas de sı́ntesis: 1) Sı́ntesis Aditiva, parte de la idea contenida en el teorema de Fourier, según la cual todo sonido
periódico, por complejo que sea, es el resultante de la suma de ondas sinusoidales
sencillas de frecuencias múltiplo, de una frecuencia base. El proceso de esta sı́ntesis,
fabrica sonidos mediante el modelo matemático, buscando la composición armónica;
partiendo de pequeñas series armónicas y precisando la frecuencia y la amplitud de
cada componente en cada instante. 2) Sı́ntesis Análoga o Substractiva, es la opción
más antigua y duradera, se fundamenta en lo contrario de la aditiva, en lugar de
ensamblar un sonido a partir de sus componentes, se sintetiza el resultado eliminando
los componentes no deseados de un sonido parcial muy rico.
La idea esencial es poder representar las variaciones de presión del sonido, en
forma de variaciones de tensión. Los timbres se obtienen a partir de formas de onda
complejas (ricas en armónicos) a las que se les sustraen, mediante filtros, ciertas partes
de su estructura armónica. 3) Sı́ntesis Virtual, nace como la fusión de tres desarrollos
técnicos de dinámica relación, primero la formal constitución del sintetizador como
instrumento expresivo y la búsqueda de nuevas posibilidades para generar sonido,
segundo, el constante desarrollo de microchips, unidades complejas de circuitos digitales, computación multimedia y finalmente el desarrollo de sofisticadas piezas de
software, encontrándose ası́, que una computadora posee las caracterı́sticas necesarias
para generar audio, modularlo y que es posible usar sonido previamente digitalizado
(samples).
2.3.
Métodos de programación de nuestro sistema
Para la generación de sonido en la PC (Personal Computer) existen técnicas utilizadas en la Multimedia, multi (variedad) y media (medios). Se ha definido como
la herramienta que emplea la PC para integrar y controlar diferentes sistemas electrónicos tales como: videodiscos, videocámaras, videocasetes, sintetizadores de video
y audio, etc. Podemos mencionar que en un entorno multimedia, los elementos básicos
12
de hardware son: 1) La unidad de CD-ROM (Compact Disc Read Only Memory) y
2) La tarjeta de sonido.
Se pueden utilizar diferentes técnicas de programación, para controlar los dispositivos multimedia sin ningún tipo de limitación. Por ejemplo, para tener acceso a
la unidad de CD-ROM o a la tarjeta de sonido, el hardware, y los controladores de
los dispositivos a utilizar, deberán estar instalados y configurados para la PC. La
siguiente lista menciona el hardware que es necesario para los tipos de dispositivos
MCI (Media Control Interfase) mas utilizados en el ambiente de programación Visual
C++: 1) El CD de audio es controlado por la unidad de CD-ROM, 2) El secuenciador
es controlado por la tarjeta de sonido, 3) El audio por forma de onda es controlado
por la tarjeta de sonido.
Para la administración de recursos multimedia de una forma apropiada, deben
cerrarse los dispositivos MCI que se encuentren abiertos antes de salir de la aplicación
o cerrar la ventana que contiene dichos dispositivos, podemos utilizar para ello la
función OnDestroy con el mensaje SetCommand (close). Estas son las principales
instrucciones, que se utilizan para cancelar la reproducción de audio y video [2].
En algoritmos computacionales a la representación eléctrica del sonido, se le conoce
como Audio. En el proceso de conversión de la forma análoga a la forma digital de una
señal y viceversa aparecen tres términos matemáticos: 1)el muestreo, 2)la cuantización
y 3)la codificación. El muestreo, es el proceso de tomar medidas instantáneas de una
señal análoga cambiante en el tiempo, tal como la amplitud de una forma de onda
compleja, el Teorema de Muestreo o Teorema de Nyquist, establece que es posible
capturar toda la información de la forma de onda, si se utiliza una frecuencia de
muestreo del doble de la frecuencia más elevada contenida en la forma de onda. La
cuantización, es el siguiente proceso para la reducción de la señal análoga compleja;
éste permite aproximar la muestra a uno de los niveles de una escala designada. La
codificación, es la representación de información analógica en una señal digital.
El sistema PCM (Modulación por codificación de Pulsos) convierte la información
13
de dos canales de audio a forma digital. Una portadora puede modularse de diferentes
modos, dependiendo del parámetro de la misma sobre él que se actúe. Se modula en
amplitud (AM) una onda que llamaremos portadora, cuando la distancia existente
entre el punto de la misma en el que la onda vale cero y los puntos en que toma
el valor máximo o mı́nimo se altera. La modulación de frecuencia (FM) consiste en
variar la frecuencia de la onda portadora de acuerdo con la intensidad de la onda de
información. La amplitud de la onda modulada es constante e igual que la de la onda
portadora.
Para el procesamiento informático del sonido es necesario realizar su captura mediante una PC y almacenarlo en memoria o disco. El proceso básico para la captura de
sonido es el siguiente: 1) El sonido se transmite por el aire hasta el micrófono, el cual
transforma la señal acústica a niveles eléctricos, 2) La señal analógica pasa a través
de un convertidor analógico/digital. Sus caracterı́sticas establecen la frecuencia y el
número de bits por cada muestra, 3) Mediante un canal se copia cada muestra a la
memoria de la PC.
Cualquier lenguaje artificial que puede utilizarse para definir, una secuencia de
instrucciones para su procesamiento por una computadora, es llamado lenguaje de
programación. Vistos a muy bajo nivel, los microprocesadores procesan exclusivamente señales electrónicas binarias (0 y 1). Dar una instrucción a un microprocesador,
es en realidad enviar series de unos y ceros con un espacio en el tiempo de una forma
determinada. Esta secuencia de señales se denomina código de máquina. El código
representa datos, números e instrucciones para manipularlos. Una manera más fácil
de comprender el código de máquina es dando a cada instrucción un mnemónico, como
por ejemplo STORE, ADD o JUMP. Esta abstracción da como resultado el lenguaje
ensamblador, el cual es de muy bajo nivel y es especı́fico de cada microprocesador.
Hay un alto nivel de abstracción entre lo que se pide a la computadora y lo que
realmente comprende. Existe también una relación compleja entre los lenguajes de
alto nivel y el código de máquina. Los lenguajes de alto nivel son normalmente fáciles
14
de comprender, porque están formados por elementos de lenguajes naturales, como
el inglés. En BASIC, el lenguaje de alto nivel más conocido, los comandos como
por ejemplo: IF CONTADOR = 10 THEN STOP pueden utilizarse para pedir a la
computadora que pare si CONTADOR es igual a 10.
Por otra parte, el lenguaje de programación C, fue desarrollado en 1972 por el
estadounidense Dennis Ritchie en los laboratorios Bell, el cual es un lenguaje de
programación de propósito general que ofrece; economı́a de sı́ntesis, control de flujo,
estructuras sencillas y un buen conjunto de operadores, tiene un campo de aplicación
ilimitado por que no es un lenguaje de muy alto nivel, más bien es pequeño y sencillo
y no está especializado en ningún tipo de aplicación, esto lo hace un lenguaje potente,
y se aprende en poco tiempo. Ahora hablemos del lenguaje C++, que es una versión
orientada a objetos del lenguaje de programación llamado C, este fue desarrollado
por Bjarne Stroustrup a comienzos de la década de 1980 en los laboratorios Bell.
Ası́ mismo, en febrero de 1993, fue creado Microsoft Visual C++ 1.0, el cual
es un entorno de desarrollo diseñado especialmente para crear aplicaciones gráficas
orientadas a objetos, introduce la biblioteca MFC (Microsoft Foundation Class). Actualmente se cuenta con la versión Visual C++.Net, la cual cuenta con una mayor
integración; MFC, ATL (Active Template Library) y una nueva clase de servicios
web, convirtiéndose en el entorno de desarrollo, si se quiere combinar el control y
el rendimiento de C++ con la compatibilidad con windows y el entorno .Net, también permite numerosas caracterı́sticas de nivel profesional y con el podemos crear
aplicaciones para windows y la web muy eficaces.
Ahora hablaremos del sistema unix, el cual es un sistema operativo multitarea
y multiusuario. Esto quiere decir que el sistema puede ejecutar varios programas a
la vez, y que puede gestionar a varios usuarios simultáneamente. Fue desarrollado
originalmente por Ken Thompson y Dennis Ritchie en los laboratorios Bell en el
año de 1969. Unix tiene diversas variantes (p.e. Linux) y se considera potente, más
transportable e independiente de equipos concretos que otros sistemas operativos,
15
porque esta escrito en lenguaje C.
2.4.
Resumen
En el desarrollo de este capı́tulo tratamos conceptos básicos como: ondas sonoras,
caracterı́sticas del sonido, armónicos, análisis de Fourier, sintetizadores, técnicas de
sı́ntesis, muestreo, modulación, generación de sonido en PC, captura de sonido y
lenguajes de programación (C, C++, Visual C++, Unix).
16
Capı́tulo 3
Aspectos del Diseño de
Sintetizadores de Música
En este capı́tulo presentaremos los aspectos de diseño de sintetizadores de música,
ya que es necesario conocer su funcionamiento antes de ser implementado en algoritmos computacionales, por lo que mencionaremos varios tipos de osciladores básicos,
los cuales usan transistores y amplificadores operacionales, tales como: osciladores
RC, LC, VCO, Colpitts, Clapp, Hartley y el circuito integrado 555, describiendo cada
uno de ellos.
3.1.
Generadores electrónicos de formas de onda
Un oscilador, es un circuito que produce una forma de onda repetitiva en su salida,
con sólo el voltaje de alimentación de DC (Direct Current) como entrada, no requiere
de una señal de entrada repetitiva. Diferentes tipos de osciladores producen diversos
tipos de salidas, incluyendo ondas sinusoidales, cuadradas, triangulares y de diente
de sierra, estos se aplican ampliamente en casi todos los sistemas de comunicación,
sistemas digitales y computadoras para generar frecuencias y señales de sincronización
requeridas. Un oscilador básico consta de: 1) Un amplificador para obtener la ganancia
(transistor o amplificador operacional) y 2) Un circuito de realimentación positiva,
que produce desfasamiento y nos introduce atenuación [4].
Mencionaremos ahora los principios de los osciladores: 1) La realimentación po17
sitiva, se caracteriza por la condición en que una parte del voltaje de salida de un
amplificador, se realimenta a la entrada sin desfasamiento neto, con esto se reforza la
señal de salida, esto es, se crea un lazo en donde la señal se sostiene a sı́ misma y se
produce una salida en forma sinusoidal continua, por lo tanto se produce la oscilación.
2) Las condiciones para que ocurra la oscilación son dos: la primera, el desfasamiento
alrededor del lazo de realimentación debe ser 0◦ , la segunda, la ganancia de voltaje alrededor del lazo cerrado de realimentación debe ser igual a la unidad. Y 3) La
condición de arranque dice; que para que se inicie la oscilación, la ganancia de voltaje
alrededor del lazo de realimentación positiva debe ser mayor que 1, de tal manera
que para que la amplitud de salida pueda alcanzar un nivel deseado, la ganancia debe
decrecer enseguida hasta 1, con el fin de conservar ese nivel.
3.2.
Tipos de osciladores
Dentro de los osciladores realimentados con circuitos RC (Resistencia-Capacitor)
se mencionaremos tres tipos que proporcionan salidas sinusoidales: 1) El oscilador
puente de Wien, su parte fundamental es una red de adelanto-atraso formada por
resistencias y capacitores y que se usa en el lazo de realimentación positiva, esta
red tiene una frecuencia de resonancia, en donde el desfasamiento a través de la red
es 0◦ y la atenuación es 1/3. Por abajo de la frecuencia de resonancia predomina
la red de adelanto y la salida se adelanta a la entrada, por arriba de la frecuencia
de resonancia predomina la red de atraso y la salida se atrasa con respecto a la
entrada. 2) El oscilador de corrimiento de fase, consta de tres redes RC en el lazo
de realimentación, que puede proporcionar un desfasamiento máximo que tiende a
90◦ , la oscilación ocurre a la frecuencia en donde el desfasamiento total a través de
las tres redes RC es de 180◦ . Y 3) El oscilador de T gemela, se conoce ası́ debido a
los dos filtros RC de tipo T, que son usados en el lazo de realimentación negativa,
uno de los filtros T tiene una respuesta pasa-bajas y el otro una pasa-altas, estos
filtro son conectados en paralelo y producen una respuesta de un supresor de banda,
18
con frecuencia central igual a la frecuencia de oscilación deseada. Comúnmente estos
osciladores se usan para frecuencias hasta de 1MHz (Mega Hertz).
En osciladores que requieren frecuencias más altas de oscilación, normalmente se
usan elementos de realimentación tipo LC (Bobina-Capacitor), a menudo se emplean
transistores como elementos de ganancia en estos osciladores, a continuación nos
introduciremos en varios tipos de osciladores LC resonantes tales como: 1) El oscilador
Colpitts, denominado ası́ en honor de su inventor, en este tipo se usa un circuito LC
en el lazo de realimentación, para proporcionar el desfasamiento necesario y poder
operar como filtro resonante que va a pasar solamente la frecuencia de oscilación que
se requiere. 2) El oscilador Clapp es una variante del Colpitts, la diferencia básica es un
capacitor adicional en serie con el inductor, en el circuito resonante de realimentación.
3) El oscilador Hartley, es semejante al Colpitts, salvo que la red de realimentación
está formada por dos inductores en serie y un capacitor en paralelo. 4) El oscilador
Armstrong, usa un acoplamiento por transformador, con lo cual se realimenta una
parte del voltaje de señal, algunas veces se le denomina oscilador de reacción en
referencia al secundario del transformador, no es muy común en comparación con los
anteriormente mencionados, en principio por la desventaja que presenta el tamaño
y el costo del transformador. Y 5) Los osciladores controlados por cristal, son muy
estables y exactos, por que usan un cristal piezoeléctrico en el lazo de realimentación,
con el fin de poder controlar la frecuencia.
Hemos tratado osciladores que a su salida la forma de onda es sinusoidal, sin
embargo, existen osciladores que la forma de onda a su salida puede ser una onda triangular, diente de sierra, o cuadrada, algunos de estos tipos se refieren como
generadores de señal o multivibradores.
Continuando con los osciladores existe un tipo que es controlado por voltaje
(VCO), cuya frecuencia puede cambiarse mediante un voltaje de control variable de
DC, los VCO’s pueden ser sinusoidales o no sinusoidales. Por ejemplo, para construir
un oscilador de diente de sierra controlado por voltaje, se puede emplear un inte19
grador con un amplificador operacional, que use un dispositivo de conmutación PUT
(transistor de unı́ juntura programable) que se conecte en paralelo con el capacitor de
realimentación. El PUT contiene un ánodo, un cátodo y una terminal de compuerta.
La compuerta está siempre polarizada positivamente con respecto al cátodo, cuando
el voltaje del ánodo excede al de la compuerta en aproximadamente 0.7 V (Volts), el
PUT se enciende y opera como diodo polarizado directamente, si el voltaje del ánodo
cae por debajo de este nivel, el PUT se apaga, al cumplirse estas condiciones junto
con la carga y descarga del capacitor obtenemos un generador de diente de sierra.
Por otra parte, tenemos a un circuito integrado muy versátil y con muchas aplicaciones, el temporizador 555, el cual se verá como oscilador. Este oscilador consta
de dos comparadores, un circuito multivibrador biestable (flip-flop), un transistor de
descarga y un divisor de voltaje resistivo. El multivibrador biestable, es un dispositivo digital de dos estados, cuya salida puede estar en un nivel alto de voltaje (set) o
en un nivel bajo de voltaje (reset), estos estados pueden cambiarse mediante señales
de entrada apropiadas. El 555 se puede conectar, para que opere en el modo astable
como oscilador no sinusoidal de carrera libre.
3.3.
Anatomı́a de un sintetizador
Trataremos ahora los componentes elementales de un sintetizador. Conforme van
pasando los años la tecnologı́a va progresando en el campo de la electrónica, por
ejemplo, tenemos el caso del desarrollo y evolución del transistor, con esto es posible
la construcción de generadores de sonido más finos. Ası́ en 1964 Robert Moog, en
colaboración con un músico llamado Herbert Deutsch, desarrollaron los primeros VCO
y VCA (Amplificador Controlado por Tensión), un año mas tarde, desarrolla los
filtros controlados VCF (Filtro Controlado por Tensión), de pasa-bajas y pasa-altas,
de igual manera los ADSR (generador de envolvente), esto dio paso al nacimiento del
sintetizador analógico modular (llamado Moog en honor a su inventor). Más adelante
se explicaremos los términos anteriormente mencionados.
20
Figura 3.1: Sintetizador elemental
En la Figura 3.1 se muestra el diagrama a bloques de un sintetizador elemental, a
continuación se describen cada uno de sus bloques: El teclado controlador está compuesto por una fuente la cual va a suministrar tensiones que son proporcionales a la
tecla que se oprime, estas tensiones se utilizan para iniciar los generadores de envolvente. El VCO, es en este caso la fuente de sonido básica, la frecuencia de la señal
que genera se obtiene como suma algebráica de las tensiones de control aplicadas a
sus entradas, se usan con respuesta exponencial normalizada a 1V/Octava y disponen
de varias formas de onda, sinusoidal, diente de sierra, triangular y cuadrada, y cada
una de ellas dará un tipo de sonido peculiar y diferente, dado el distinto contenido
armónico que tienen.
El mezclador de audio, es un dispositivo que permite la combinación de una serie
de señales de entrada deseadas, de manera que se obtiene otra señal que es la combinación de aquellas. El ADSR (Attack Decay Sustain Release), se refiere a cuatro zonas
21
caracterı́sticas de la amplitud de una señal de control, la zonas ADR se refiere a tiempos, mientras que S se refiere a un nivel, estos generadores de envolvente controlarán
tanto la amplitud de la señal sonora como la respuesta del filtro. El VCA se combina
con un generador ADSR, para impartir a los sonidos que modifica unas determinadas
caracterı́sticas de ataque y decaimiento en su intensidad, de tal manera que permita
la simulación de la dinámica de diversos instrumentos musicales, también es posible
modular en amplitud la señal que se procesa para añadir trémolos y otros efectos que
dependerán mucho de la frecuencia de la señal moduladora.
Por otro lado, el VCF es un elemento que permite el paso de determinadas frecuencias de la señal de entrada y es el equivalente eléctrico de los resonadores acústicos de
los instrumentos tradicionales, como la caja del violı́n, que da el sonido caracterı́stico
del instrumento, este se puede configurar en varios modos, pasa bajo, pasa alto, pasa
banda y supresor de banda, según sea el efecto que deseamos resaltar o atenuar de la
onda básica generada por los VCO, se tiene que los parámetros caracterı́sticos de un
filtro son la frecuencia de corte y la pendiente del filtro, que determina la atenuación
de los sucesivos armónicos de la señal de entrada.
Ya por último, el LFO (Low Frecuency Ocilator) generalmente se compone de
varios osciladores independientes controlados por tensión, con varias formas de onda
cada uno y que se sitúan en la banda de bajas frecuencias, hasta unos 20Hz, su salida
puede usarse tanto para controlar la amplitud (trémolo), como la frecuencia (vibrato),
de los VCO, obteniendo sonoridades muy variadas. Por último mencionaremos que
existen técnicas para la generación de ruido, por ejemplo, la de un algoritmo computacional o un arreglo de dispositivos electrónicos, los cuales suelen proporcionar ruido
blanco o rosa, ası́ como una salida de tensión de control aleatoria, pero ajustable en
ciertos parámetros, estas tres señales sirven para producir sonidos no convencionales
similares a los naturales, como el mar, el trueno y el siseo del aire.
22
3.4.
Resumen
En este capı́tulo presentamos varios tipos de osciladores, tales como: osciladores
RC, LC, VCO, Colpitts, Clapp, Hartley, describiendo cada uno de ellos, también se
presentó un circuito integrado muy popular, llamado temporizador 555 en su forma
de oscilador, ası́ mismo describimos el diagrama de un sintetizador elemental, estos
conceptos son la antesala para el diseño básico de un sintetizador elemental, que más
adelante presentaremos.
23
Φ
24
Capı́tulo 4
Diseño de Nuestro Sintetizador de
Notas
En este capı́tulo presentaremos el diseño de nuestro sintetizador de notas musicales. Explicaremos con más detalle la programación de la sı́ntesis de onda y las
estructuras de sonido más importantes que se requieren para la programación del
driver que controla la tarjeta de sonido de una computadora digital PC.
4.1.
Computadoras digitales
Una computadora digital funciona con base al procesamiento de números digitales,
y son el tipo de computadoras en el que se ha centrado el progreso moderno. Éstas
se dividen en cuatro principales generaciones que son; 1) Primera generación (19511958), en la cual se usaron bulbos para almacenar la información y tarjetas perforadas
para cargar datos y programas. 2) Segunda generación (1959-1964), con el invento del
transistor llego esta nueva generación de computadoras, las cuales utilizaron cintas
y discos magnéticos para almacenar información y disponı́an de celdas fotoeléctricas
para la mejor lectura de las tarjetas perforadas. 3) Tercera generación (1964-1971),
aquı́ se da la llegada de los circuitos integrados a las computadoras, con lo cual se
incrementa el rendimiento de las máquinas, pudiendo ası́ trabajar a tal velocidad que
se podı́a correr más de un programa de manera simultanea. Las computadoras se
hicieron más pequeñas, más rápidas y desprendı́an menos calor. 4) Cuarta generación
25
(1971-a la fecha), la colocación de componentes más pequeños en un chip, permite
crear el microprocesador, el cual rige las funciones principales en una computadora. Se
crean memorias electrónicas, las cuales desechan a las memorias de núcleo magnético
que se usaban anteriormente, aumentando ası́ su rapidez. Con la llegada de estas
tecnologı́as, se hizo posible la creación de la PC (Personal Computer).
Las computadoras siguen avanzando hasta nuestros dı́as, creando mejores técnicas
y desarrollando nuevas tecnologı́as. Una parte importante de las computadoras hoy
en dı́a es la Internet, que puede ser definida como red de redes, es decir, una red que
interconecta redes de computadoras entre sı́. Una red de computadoras es un conjunto
de máquinas que se comunican a través de algún medio (cable coaxial, fibra óptica,
radiofrecuencia, lı́neas telefónicas, etc.) con el objeto de compartir recursos.
Aunque se pueda pensar que internet inició hace pocos años, no es ası́, sus inicios
nos remontan a la década de los 60’s. En plena guerra frı́a Estados Unidos creó una
red de uso exclusivamente militar, para que en caso de un ataque se pudiera tener
acceso a la información desde cualquier parte del paı́s. El envió de datos deberı́a
descansar en un mecanismo que pudiera manejar la destrucción parcial de la red, de
esta manera se decidió enviar la información en pequeños mensajes o paquetes, los
cuales contendrı́an la dirección de destino, pero no una ruta especı́fica para su arribo,
cada paquete buscarı́a una ruta y al final el destinatario reensambları́a el mensaje
original. Esta red se creo en 1969 y fue llamada ARPANET (Advanced Research
Projects Agency Network).
Esta red fue situada en diferentes universidades del paı́s y creció tanto que su
protocolo NCP (Network Control Protocol), quedó obsoleto. Entonces con el tiempo
se dio paso a un protocolo mas sofisticado, el TCP/IP (Transmission Control Protocol / Internet Protocol), que es el protocolo utilizado hasta nuestros dı́as. TCP se
encarga de convertir los mensajes a paquetes en la máquina emisora y los reensambla
en la máquina destino, mientras que IP se encarga de buscar la ruta destino. En 1983
el segmento militar decide separarse de ARPANET y formar su propia red conocida
26
como MILNET (Militar Network). En 1984 la National Science Foundation, crea una
nueva red llamada NSFNET (National Science Foundation Network) y con un incremento continuo de transmisión de datos de la misma, logró absorber a ARPANET.
Sin embargo, el continuo crecimiento de nuevas redes de libre acceso, terminaron en
la unión de éstas con NSFNET, formando ası́ el embrión de lo que ahora es Internet.
Con la creación de las páginas web y del primer explorador, Internet no ha dejado de
crecer y paso de ser una red de investigación militar, a un negocio y eso ha sido lo
que impulsa su desarrollo.
4.2.
Estructuras del controlador (driver) de sonido
Por otra parte, para el diseño de sı́ntesis de ondas, necesitamos conocer el funcionamiento y caracterı́sticas principales de algunas funciones y estructuras que se
utilizaran posteriormente. Empecemos con la estructura WAVEFORMATEX, la cual
contiene la información más común de la forma de onda y define su formato, cuando se requiere mayor información, ésta será incluida como primer miembro en otra
estructura con la información adicional. La siguiente es su estructura:
typedef struct {
WORD
wFormatTag;
WORD
nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD
nBlockAlign;
WORD
wBitsPerSample;
WORD
cbSize;
}WAVEFORMATEX;
Donde, wFormatTag especifica el tipo de formato de la forma de onda; nChannels
especifica el número de canales a utilizar, que puede ser monoaural para un canal
o estereo para dos canales; nSamplesPerSec es el número de muestras por segundo que en cada canal se reproducirán o grabarán, si wFormatTag tiene especificado WAVE FORMAT PCM, entonces los valores comunes de muestras por segundo
27
son: 8.0 KHz, 11.025 KHz, 22.05 KHz y 44.1 KHz; nAvgBytesPerSec requiere hacer un promedio de la transferencia de datos en bytes por segundo, si wFormatTag
tiene especificado WAVE FORMAT PCM, entonces nAvgBytesPerSec debe ser igual
al producto de nSamplesPerSec y nBlockAlign; nBlockAlign es el alineamiento de
bloques en bytes, éste es la unidad mı́nima de datos para el tipo de formato, si
wFormatTag tiene especificado WAVE FORMAT PCM, entonces nBlockAlign debe
ser igual al producto de nChannels y wBitsPerSample, dividido entre 8; wBitsPerSample son los bits por muestra para el tipo de formato, si wFormatTag tiene especificado
WAVE FORMAT PCM, entonces wBitsPerSample debe ser igual a 8 o 16; cbSize es
utilizada para agregar información extra de la estructura WAVEFORMATEX, cuando
el formato es diferente de PCM [9].
Quien se encarga de abrir el dispositivo de salida de la forma de onda es la función
waveOutOpen y su estructura es la siguiente:
MMRESULT waveOutOpen(
LPHWAVEOUT
{\it phwo},
UINT
uDeviceID,
LPWAVEFORMATEX
pwfx,
DWORD
dwCallback,
DWORD
dwCallbackInstance,
DWORD
fdwOpen
);
Donde, phwo es ocupado para identificar y relacionar las diferentes funciones de
salida de forma de onda; uDeviceID identifica el dispositivo a utilizar, el cual puede
ser de entrada o salida; pwfx es una dirección de la estructura WAVEFORMATEX,
la cual identifica los datos de la forma de onda que serán enviados al dispositivo,
esta estructura será vaciada inmediatamente después que se pase a la función waveOutOpen; dwCallback es una dirección que asegura que la función regrese, ya sea
de un manejador de eventos, de un manejador de ventana, etc., esto dependerá de
la bandera que se utilice (fdwOpen), si esta función no es usada, su valor puede
ser cero; dwCallbackInstance se usa para pasar datos al mecanismo de llamada de
regreso; fdwOpen es un parámetro que usa banderas para abrir el dispositivo, las
28
banderas son las siguientes: CALLBACK EVENT permite manejar eventos; CALLBACK FUNCTION regresa algún procedimiento a una dirección; CALLBACK NULL
no tiene mecanismo de regreso y solo cuenta con los parámetros iniciales; CALLBACK THREAD es un hilo identificado; CALLBACK WINDOW es un manejador de
ventana; WAVE ALLOWSYNC indica que un dispositivo de forma de onda sı́ncrono
puede estar abierto; WAVE FORMAT DIRECT especificada que el controlador ACM
(Audio Compression Manager) no llevará acabo las conversiones en los datos de audio;
WAVE FORMAT QUERY indica a waveOutOpen preguntar al dispositivo determinado si soporta el formato dado, pero el dispositivo no estará abierto; WAVE MAPPED
indica al parámetro uDeviceID especificar un dispositivo de forma de onda para ser
mapeado.
Para detener el dispositivo de salida y reiniciar la corriente de posición a cero, es
utilizada la función waveOutReset y su estructura es la siguiente:
MMRESULT waveOutReset(HWAVEOUT hwo);
donde hwo es el manejador del dispositivo de salida de forma de onda.
Una estructura importante es WAVEHDR, ya que define los parámetros usados
para identificar un buffer de audio de forma de onda y su estructura es la siguiente:
typedef struct {
LPSTR
lpData;
DWORD
dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD
dwLoops;
DWORD
dwFlags;
} WAVEHDR;
Donde, lpData es la dirección del buffer de la forma de onda; dwBufferLength es
la longitud en bytes del buffer; dwBytesRecorded es puesta cuando la estructura es
usada para entrada, este miembro especifica cuantos datos hay en el buffer; dwUser
son los datos de usuario; dwLoops es el número de veces que la función se repite,
dentro de una iteración; dwFlags son las banderas de abastecimiento de información
acerca del buffer: WHDR BEGINLOOP es el primer buffer en un lazo y solo puede
29
ser usado con buffer de salida; WHDR DONE es colocada en el controlador del dispositivo para indicar que ha finalizado el buffer y está regresando a la aplicación;
WHDR ENDLOOP es el último buffer en el lazo y solo es usada con buffer de salida;
WHDR INQUEUE es puesto por windows para indicar que el buffer está en cola para
tocar; WHDR PREPARED también es puesto por windows para preparar al buffer,
ya sea con una función de entrada o una de salida.
Para preparar un bloque de datos de la forma de onda y después tocarlos utilizamos
la función waveOutPrepareHeader. Su estructura es la siguiente:
MMRESULT waveOutPrepareHeader(
HWAVEOUT
hwo,
LPWAVEHDR pwh,
UINT
cbwh
);
Donde, hwo es el manejador del dispositivo de salida de forma de onda; pwh
es una dirección de la estructura WAVEHDR, que define los bloques de datos para
prepararlos; cbwh es el tamaño en bytes de la estructura WAVEHDR.
Una parte importante es la función waveOutWrite, ya que es la encargada de
mandar bloques de datos a la salida del dispositivo de forma de onda. Su estructura
es la siguiente:
MMRESULT waveOutWrite(
HWAVEOUT hwo,
LPWAVEHDR pwh,
UINT cbwh
);
Donde, hwo es el manejador del dispositivo de salida de forma de onda; pwh es
la dirección de una estructura WAVEHDR, la cual contiene información acerca del
bloque de datos; cbwh es el tamaño en bytes de la estructura WAVEHDR.
Para limpiar la preparación llevada a cabo por la función waveOutPrepareHeader
es utilizada la función waveOutUnprepareHeader, esta función debe ser llamada después de que el dispositivo haya finalizado con un bloque de datos y antes de liberar
el buffer. Su estructura es la siguiente:
30
MMRESULT waveOutUnprepareHeader(
HWAVEOUT hwo,
LPWAVEHDR pwh,
UINT cbwh
);
Donde, hwo es el manejador del dispositivo de salida de forma de onda; pwh
es la dirección de una estructura WAVEHDR, para identificar los datos que serán
limpiados; cbwh es el tamaño en bytes de la estructura WAVEHDR.
Por último tenemos a la función waveOutClose, que es la encargada de cerrar el
dispositivo de salida de forma de onda y su estructura es la siguiente:
MMRESULT waveOutClose( HWAVEOUT hwo
);
Donde, hwo es el manejador del dispositivo de salida de forma de onda.
4.3.
Programación de las funciones de onda
Para la generación de sonido en nuestro diseño, una de las funciones más importantes es la que llamaremos FillBuffer. Esta función es la encargada de manipular las
diferentes formas de onda con las que trabajaremos, y tiene la siguiente estructura:
VOID FillBuffer ( LPBYTE pBuffer, int iFreq )
{
static double fAngle;
int i;
for ( i = 0 ; i < BUFFER_SIZE ; i ++ )
{
pBuffer [i] = (BYTE) (127 + 127 * sin (fAngle));
fAngle += 2 * PI * iFreq / SAMPLE_RATE ;
if (fAngle > 2 * PI)
fAngle - = 2 * PI;
}
}
La función anterior genera datos digitales (bytes) que corresponden a una señal
analógica (en este caso un seno), que debe estar en el rango de frecuencias audibles
para el oı́do humano (de 20-20 KHz), esta será almacenada en memoria con una razón
de muestras digitales que llamaremos SAMPLE RATE. Para generar una onda de 20
KHz es necesario que en cada ciclo se tomen mı́nimo dos muestras, por esta razón
31
el SAMPLE RATE toma el valor de 44100 Hz. Por ejemplo para generar una forma
de onda con una frecuencia de 8820 Hz por cada ciclo se tomarán 5 muestras, como
se muestra en la Figura 4.1, esto significa que el número de muestras por segundo es
el SAMPLE RATE divido entre la frecuencia de la forma de onda. El seno de cada
muestra será almacenado en la localidad de un buffer previamente definido.
Figura 4.1: Número de muestras por cada ciclo.
Se puede aprovechar que la señal con la que se está trabajando es una señal
periódica, de esta manera se puede trabajar con un solo ciclo incrementando las
localidades de memoria y repitiendo los ángulos de fase. El primer ángulo será 0,
después la variable fAngle es incrementada 2π veces la frecuencia dividida entre el
SAMPLE RATE, este procedimiento continúa hasta que fAngle es mayor que 2π,
entonces será decrementado en 2π para volver a retomar los ángulos que ahora serán
almacenados en diferentes localidades de memoria de nuestro buffer. Cada localidad
de memoria es de 8 bits por esta razón la función seno está dada entre 0 y 254 (00 a
FF) [8].
Por otro lado tenemos que, un seno es una porción fundamental en la trigonometrı́a,
en un triángulo rectángulo el valor del seno de un ángulo agudo, es igual a la longitud del cateto opuesto al ángulo, dividida por la longitud de la hipotenusa. El valor
numérico del seno está comprendido entre -1 y 1, la curva de este es el prototipo o
modelo de todas las sinusoides. Se tiene que un ángulo representa la apertura de dos
lı́neas que tienen un origen común (vértice); un arco se define como la lı́nea circular
32
que rodea al ángulo por el extremo de dos segmentos, las medidas de un ángulo se
pueden expresar en radianes; el radian es el ángulo cuyo arco tiene una longitud igual
al radio. Por lo tanto tenemos que, 1◦ = 0.01745 radianes y 1 radian = 57.3 grados, el
grado está definido en trigonometrı́a como el arco igual a 1/360 de la circunferencia
de un cı́rculo.
4.4.
Visualización de las formas de onda
Mediante la sumatoria de señales simples, podemos obtener una señal compleja
que sea semejante a la forma de onda caracterı́stica de algún instrumento musical.
Tomando en cuenta el teorema de Fourier, que dice: que por medio de la suma de
funciones periódicas de distinta frecuencia es posible obtener una señal compleja,
hemos creado un programa en Visual C++ que muestra gráficamente el teorema de
Fourier [3].
En la Figura 4.2 se muestra el resultado de nuestro programa, que se encuentra
dividido en cuatro ventanas; en la primera se representa la frecuencia más baja llamada frecuencia fundamental; en las ventanas dos y tres se representan el tercer y
noveno armónico respectivamente, los cuales son múltiplos de la frecuencia fundamental; en la ventana cuatro podemos observar una forma de onda compleja, la cual
es el resultado de la sumatoria de las tres ventanas anteriores.
Tenemos que una serie de Fourier está representada por una sumatoria de senos
y cosenos, su representación matemática es la siguiente:
f (t) = a0
∞
X
cos(kw0 t) + bk
n=1
∞
X
sen(kw0 t)
(4.1)
n=1
Una señal por compleja que sea se puede representar mediante la función f(t),
las funciones pueden ser pares e impares, las funciones pares tienen una gráfica que
debe ser geométrica respecto al eje vertical, las funciones impares tienen su gráfica
simétrica con el origen, también existen funciones que no cumplen con la definición
de función par e impar.
33
En las ventanas de la Figura 4.2 tenemos dos barras de desplazamiento, la barra
horizontal representa la frecuencia (kw0 t), la barra vertical representa la amplitud de
la señal (a0 , ak ,bk ). Si la señal es par entonces, bk = 0, y la señal estará representada por cosenos. Si la señal es impar entonces, a0 y ak = 0, por lo tanto la señal
estará representada por senos. En la ventana superior izquierda tenemos representada
a la señal: a seno(w0 t); la ventana superior derecha representa: ak seno(3w0 t); la ventana inferior izquierda representa: ak seno(9w0 t); y por último en la ventana inferior
derecha, queda representada gráficamente la sumatoria de las ventanas anteriormente
Figura 4.2: Representación gráfica de la Serie de Fourier, mediante un programa
diseñado en C++.
34
mencionadas, dando la función: f(t) = a seno(w0 t)+ak seno(3w0 t)+ak seno(9w0 t), que
es la representación de la Ecuación 4.1.
Estas ventanas se implementan con un buffer y algunas estructuras de audio,
para obtener el sonido de las señales que representan dichas ventanas, por lo tanto,
vamos a obtener la respuesta gráfica y el audio, que pueden ser semejantes a cualquier
instrumento musical.
4.5.
Anatomı́a de una tarjeta de sonido
Una parte muy importante de este proyecto es la tarjeta de sonido, ya que permitirá implementar la parte de audio en nuestro proyecto. En un principio la PC
(Personal Computer) no fue diseñada para trabajar con sonido, sin embargo, con el
desarrollo de nuevas aplicaciones (video juegos, música electrónica, etc.), tuvo que ser
desarrollado un hardware diseñado para controlar el sonido y que fuese compatible
con la PC, de esta manera en la década de los 80’s aparece la tarjeta de sonido.
En la actualidad las tarjetas de sonido se encuentran divididas en dos partes: la
parte analógica y la parte MIDI (Musical Instrument Digital Interface) [6]. En la
Figura 4.3 se muestra el diagrama a bloques de una tarjeta de sonido.
Se puede observar que la parte analógica se encuentra subdividida en tres bloques;
el primero es un convertidor analógico-digital, que es el encargado de transformar los
datos analógicos de la entrada (micrófono, guitarra, etc.) a datos digitales, ya que la
PC solo trabaja con este tipo de datos; en el segundo bloque se encuentran los drivers
de audio, que usa windows para manipular los datos que le pasará el primer bloque;
y por último el tercer bloque es un convertidor digital-analógico, que realiza una
operación inversa al primer bloque, para que el escucha pueda interpretar el sonido.
La segunda parte se encuentra dividida en cuatro bloques; los bloques de entrada
y salida son un receptor universal, los cuales se encargan de mandar y recibir datos;
el bloque del sintetizador de sonido, consta de dos formas de sintetización de datos,
una es sintetización FM, la cual se encarga de imitar el sonido por medio de formulas
35
Figura 4.3: Diagrama a bloques de una tarjeta de sonido.
matemáticas y la otra es la sı́ntesis por tabla de onda, en la cual ya no se crea
música computarizada, sino que se busca en una tabla con muestras de ondas del
instrumento deseado [5]. Cabe mencionar que la parte de MIDI no será requerida
para este proyecto.
4.6.
Resumen
En este capı́tulo presentamos lo más relevante del diseño de nuestro sintetizador de
notas musicales, también presentamos la programación de las estructuras de audio,
ası́ como el método que utilizamos para realizar la sı́ntesis de onda y por último
describimos cómo se encuentra estructurada una tarjeta de sonido. En el siguiente
capı́tulo presentaremos el diseño de la interfaz la gráfica de nuestro sistema.
36
Capı́tulo 5
Diseño de la Interfaz Gráfica
En este capı́tulo presentaremos el diseño la interfaz gráfica, la cual es el medio
de comunicación entre el usuario y las estructuras utilizadas en el diseño de sı́ntesis
de ondas. Se plantearán conceptos necesarios para su comprensión, tales como: pı́xel,
mapa de bits, recurso gráfico, ventana madre, ventana hija, sistema de coordenadas,
entre otros.
5.1.
Pixeles y mapas de bits
Para dibujar sobre dispositivos gráficos se utiliza la GDI (Graphics Device Interface), la cual se encarga de llamar las rutinas de diversos dispositivos (drivers de
video, impresora, y trazadores gráficos). Las aplicaciones gráficas útilizan un sistema
de coordenadas (x, y) en el área de dibujo, para saber la ubicación de cada punto
que se encuentre en pantalla, el valor x da la ubicación del punto sobre el eje x,
con la ubicación predeterminada 0 en el extremo izquierdo, desplazándose de izquierda a derecha, el valor de y es la ubicación del punto en el eje y, con la ubicación
predeterminada 0 en el extremo superior, desplazándose de arriba hacia abajo.
Un punto que representa la menor unidad gráfica de medida de una pantalla es
llamado pı́xel. La imagen digital de algún dibujo es conocida como mapa de bits, la
imagen esta constituida por pı́xeles, donde cada uno corresponde a uno o más bits
del mapa, por ejemplo: un mapa de bits de un sólo color requiere un bit por pı́xel,
37
mientras que un mapa de bits de más de un color requiere varios bits por pı́xel.
5.2.
Ventanas, barras, y otros controles gráficos
Existen elementos que interactúan directamente con el usuario, tales como: cajas
de diálogo, ı́conos, cursores, mapas de bits, etc., estos elementos son conocidos como
recursos. La lista de todos los recursos que utilice alguna aplicación se encuentra en
un archivo con extensión .rc, los recursos se guardan en un directorio y pueden ser
editados directamente (colocar barras de desplazamiento, cajas de texto, botones de
pulsación, etc.), con los editores de recursos de Visual C++ [2].
Una ventana sirve de fondo para los controles y para los gráficos, se pueden utilizar
tantas ventanas como se necesiten y dependiendo de la utilidad que se les dé, éstas
pueden ser de diferentes tipos. Se pueden crear ventanas desde el editor de diálogos de
Visual C++ o escribir el código en un archivo .cpp, como se muestra a continuación:
CVentanaPpal::CVentanaPpal()
{
// Crear la ventana principal
Create( NULL, "Windows - C++", WS_OVERLAPPEDWINDOW,
CRect( 175, 100, 465, 300), NULL, NULL, 0, NULL );
}
Las ventanas están organizadas jerárquicamente; una ventana padre o marco principal, ventana cliente o área de cliente y ventana hija o ventana marco de documento,
la ventana padre es una ventana convencional; esto es, tiene una barra de tı́tulo, una
barra de herramientas, un menú de control, un borde que permite redimensionar la
ventana y botones para maximizar, minimizar y cerrar la ventana, el área de cliente
de la ventana padre es denominada ventana cliente, en ésta se contienen las ventanas
hijas, cada una de las cuales visualizan un documento(Figura 5.1).
5.3.
Programando la interfase gráfica
Una clase es una estructura de datos cuyos campos son métodos. Los métodos
también son conocidos como funciones, estos son la base de las aplicaciones y se
38
Figura 5.1: Jerarquı́a de ventanas.
encuentran declaradas en diversos archivos de cabecera incluidos en Visual C++. Para
indicarle a una aplicación en ejecución, que ha sucedido algún evento (clic sobre un
botón, mover el ratón, pulsar una tecla) es necesario enviar una notificación la cual es
conocida como mensaje. La aplicación responde con una acción, que está determinada
por la ejecución del código en una función, esto significa que enviar un mensaje
equivale a ejecutar una función dentro de una aplicación.
Para la implementación de la interfase de nuestra aplicación contaremos con una
ventana como la que se muestra en la Figura 5.2, la cual mezclará una señal fundamental con cinco de sus armónicos, estas señales se visualizarán en la ventana ası́ como
la señal resultante. Contará también con una serie de botones, los cuales simularán
las teclas del piano y al hacer clic en ellas se escuchará la señal antes mencionada.
A continuación explicamos el procedimiento para la realización del software antes
mencionado en el lenguaje de programación Visual.C++.
Inicialmente necesitamos crear un documento vacio (esqueleto de la aplicación),
para esto de clic en la orden new del menú file, esto invocará a Class Wizard, en la
pestaña projects se elige una aplicación MFC (Microsoft Foundation Class) AppWizard
[exe] y ponga el nombre del proyecto (en este caso lo llamaremos Sintetizador) y la
39
Figura 5.2: Interfaz gráfica de la aplicación.
localización, las otras opciones en esta ventana son las dadas por omisión. En ese
momento comienzan los pasos que genera Class Wizard; en el paso 1 se elige un
documento simple; en los pasos 2 y 3 se toman las opciones por omisión; en el paso 4
se desactivan las tres primeras casillas (Docking Toolbar, Inicial Status Bar y Printing
and Print Preview), dejando sólo los controles 3D; en el paso 5 se toman las opciones
por omisión; y en el paso 6 se elige la opción CFormView del menú Base Class,
para obtener un formulario como vista principal. Al dar clic en el botón finalizar, se
muestra la información del proyecto que se realizará cuando demos clic en el botón
OK de esta ventana.
El paso siguiente es dibujar sobre la vista cinco barras verticales, las cuales controlarán la amplitud de los armónicos de la frecuencia fundamental, una barra horizontal
que servirá como afinador y una caja de texto por cada barra, en donde se visualizará en valor de la misma al ser pulsada. Cada objeto cuenta con un identificador
40
que es llamado ID, para modificarlo es necesario: entrar al cuadro de propiedades del
objeto y asignarle un nombre que sea cómodo para ser manipulado. Cabe mencionar
que usted puede acomodar los botones como más le convenga.
Para facilitar la entrada y salida de datos a través de controles se utilizan variables
miembro que los representen, para que el código trabaje sobre esas variables y se olvide
de los controles. Ejecute Class Wizard (Ctrl.+ w), de clic en la pestaña Member
Variables y seleccione el ID de la barra que desee, ahora pulse el botón Add Variable..
y añada para la barra horizontal la variable m CtrlBarraH1, para las barras verticales
agregue las variables m CtrlBarraV1 hasta m CtrlBarraV5, todas de categorı́a Control
y tipo CScrollBar, para la caja de texto de la barra horizontal la variable aH1 y para
las cajas de texto de las barras verticales las variables aV1 hasta aV5, todas estas de
tipo int.
Para inicializar las barras de desplazamiento es necesario modificar la función
miembro OnInitialUpdate, ya que es la primera función de la vista en ejecutarse,
está se encuentra en el archivo fuente sintetizadorview.cpp. Edite la función como se
muestra a continuación:
void CSintetizadorView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit(false);
m_CtrlBarraH1.SetScrollRange(415, 466, false);
m_CtrlBarraH1.SetScrollPos(440, false);
m_CtrlBarraV1.SetScrollRange(0, 16, false);
m_CtrlBarraV1.SetScrollPos(0, false);
...
...
...
m_CtrlBarraV5.SetScrollRange(0, 16, false);
m_CtrlBarraV5.SetScrollPos(0, false);
}
UpdateData(false);
La función SetScrollRange asigna los valores mı́nimo y máximo para la barra de
41
desplazamiento especificada. La función SetScrollPos sitúa el cuadro de desplazamiento en la posición indicada.
Cuando el usuario actúe sobre una de las barras de desplazamiento se genera un
mensaje, si la barra es horizontal el mensaje será WM HSCROLL y si la barra es
vertical el mensaje será WM VSCROLL, esto hará que se ejecute la función asociada OnHScroll o OnVScroll. Para esto invoque Class Wizard y de clic en la ventana
Message Maps, enseguida seleccionando la clase CSintetizadorView, el objeto CSintetizadorView y el mensaje WM HSCROLL, de clic en el botón Add Fuction y después
en el botón Edit Code y edite la función OnHScroll de la siguiente forma:
void CSintetizadorView::OnHScroll(UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar)
{
int nNuevaPo = pScrollBar->GetScrollPos();
switch( nSBCode )
{
case SB_LEFT:
nNuevaPo = 415;
break;
case SB_RIGHT:
nNuevaPo = 466;
break;
case SB_PAGERIGHT:
nNuevaPo = min(466, nNuevaPo + 5);
break;
case SB_PAGELEFT:
nNuevaPo = max(415, nNuevaPo - 5);
break;
case SB_LINERIGHT:
nNuevaPo = min(466, nNuevaPo + 1);
break;
case SB_LINELEFT:
nNuevaPo = max(415, nNuevaPo - 1);
break;
}
case SB_THUMBTRACK:
nNuevaPo = nPos;
break;
default:;
pScrollBar->SetScrollPos( nNuevaPo );
42
aH1 = m_CtrlBarraH1.GetScrollPos();
Graficador();
}
CFormView::OnHScroll(nSBCode, nPos, pScrollBar);
Un procedimiento similar se hace para la función OnVScroll, esta función se ejecuta igual que la anterior pero ahora con el mensaje WM VSCROLL, y a continuación
edı́tela de la siguiente forma:
void CSintetizadorView::OnVScroll(UINT nSBCode, UINT nPos,
CScrollBar* pScrollBar)
{
int nNuevaPos = pScrollBar->GetScrollPos();l
switch( nSBCode )
{
case SB_LEFT:
nNuevaPos = 0;
break;
case SB_RIGHT:
nNuevaPos = 16;
break;
case SB_PAGERIGHT:
nNuevaPos = min(16, nNuevaPos + 2);
break;
case SB_PAGELEFT:
nNuevaPos = max(0, nNuevaPos - 2);
break;
case SB_LINERIGHT:
nNuevaPos = min(16, nNuevaPos + 1);
break;
case SB_LINELEFT:
nNuevaPos = max(0, nNuevaPos - 1);
break;
case SB_THUMBTRACK:
nNuevaPos = nPos;
break;
CFormView::OnVScroll(nSBCode, nPos, pScrollBar);
}
pScrollBar->SetScrollPos( nNuevaPos );
aV1 = m_CtrlBarraV1.GetScrollPos();
aV2 = m_CtrlBarraV2.GetScrollPos();
aV3 = m_CtrlBarraV3.GetScrollPos();
aV4 = m_CtrlBarraV4.GetScrollPos();
aV5 = m_CtrlBarraV5.GetScrollPos();
43
Graficador();
}
CFormView::OnVScroll(nSBCode, nPos, pScrollBar);
Las variables miembro aH1 y aV’s son igualadas con la posición en la que se
encuentre la barra de desplazamiento para ser mandadas a la caja de texto y a la
función Graficador que más tarde será declarada. Para una mejor manipulación de
estas variables, borre su declaración que se encuentra en el archivo sintetizadorview.h
y declárelas como variables globales en el archivo sintetizadorview.cpp.
Al final de cada código estamos llamando a una función Graficador, está función
es la encargada de dibujar la señal fundamental, los armónicos y la resultante en la
vista principal. Para darla de alta ocuparemos AppWizard, esto lo hacemos dando clic
en la pestaña ClassView de la ventana WorkSpace, desplegamos el menú sintetizador
classes y damos clic derecho sobre la clase CSintetizadorView, al hacerlo aparecerá un
menú y daremos clic sobre la opción Add Member Function, aparecerá una ventana
en donde preguntará el tipo de función, que será void y la declaración o nombre de
función, que será Graficador. Edite esta función de la manera siguiente:
void CSintetizadorView::Graficador()
{
CClientDC dc(this);
CClientDC dc2(this);
CClientDC dc3(this);
CClientDC dc4(this);
CClientDC dc5(this);
CClientDC dc6(this);
CClientDC dc7(this);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetViewportExt(630,20);
dc.SetViewportOrg(47,400);
dc2.SetMapMode(MM_ISOTROPIC);
dc2.SetViewportExt(630,20);
dc2.SetViewportOrg(47,560);
dc3.SetMapMode(MM_ISOTROPIC);
dc3.SetViewportExt(630,20);
dc3.SetViewportOrg(250,416);
44
dc4.SetMapMode(MM_ISOTROPIC);
dc4.SetViewportExt(630,20);
dc4.SetViewportOrg(250,560);
dc5.SetMapMode(MM_ISOTROPIC);
dc5.SetViewportExt(630,20);
dc5.SetViewportOrg(450,416);
dc6.SetMapMode(MM_ISOTROPIC);
dc6.SetViewportExt(630,20);
dc6.SetViewportOrg(450,560);
dc7.SetMapMode(MM_ISOTROPIC);
dc7.SetViewportExt(630,20);
dc7.SetViewportOrg(700,420);
RedrawWindow();
for(x=0;x<=2000; x ++)
{
w = (440*2*3.14);
w2 = (880*2*3.14);
w3 = (1320*2*3.14);
w4 = (1760*2*3.14);
w5 = (2200*2*3.14);
w6 = (2640*2*3.14);
ysen=(int)(87+87*sin(x*w/440));
ysen2=(int)(8+aV1*sin(x*w2/880));
ysen3=(int)(8+aV2*sin(x*w3/1320));
ysen4=(int)(8+aV3*sin(x*w4/1760));
ysen5=(int)(8+aV4*sin(x*w5/2200));
ysen6=(int)(8+aV5*sin(x*w6/2640));
resul=(int)((87+87*sin(x*w/440))+(8+aV1*sin(x*w2/440))+
(8+aV2*sin(x*w3/440))+(8+aV3*sin(x*w4/440))+
(8+aV4*sin(x*w5/440))+(8+aV5*sin(x*w6/440)));
}
}
dc.SetPixel(x*8,ysen*50,RGB(0,0,0));
dc2.SetPixel(x*8,ysen2*300,RGB(0,0,0));
dc3.SetPixel(x*8,ysen3*300,RGB(0,0,0));
dc4.SetPixel(x*8,ysen4*300,RGB(0,0,0));
dc5.SetPixel(x*8,ysen5*300,RGB(0,0,0));
dc6.SetPixel(x*8,ysen6*300,RGB(0,0,0));
dc7.SetPixel(x*12,resul*80,RGB(0,0,0));
UpdateData( false );
Declare las variables ysen a ysen6, x y resul, como tipo int y las variables w a w6
de tipo double, todas como variables globales. La función RedrawWindow se encarga
de limpiar la pantalla cada vez que movemos las barras y se dibuja la función seno.
45
El CClientDC nos sirve para obtener el contexto de dispositivo del área de cliente y
acceder a sus atributos a través de la función miembro de la clase del contexto de
dispositivo. La función SetMapMode se encarga de ajustar el sistema de coordenadas
a algún modo de proyección que en este caso es MM ISOTROPIC, el cual es un modo
que se puede personalizar, permitiéndonos manipular el tamaño de las figuras cuando
se redimensione la ventana. SetViewportExt establece la medida del ancho del dibujo.
SetViewportOrg sitúa el origen lógico 0,0 de coordenadas, en algún punto del área
de cliente (las funciones expuestas en la función Graficador son opcionales). SetPixel
dibuja un punto en la pantalla, las coordenadas que utiliza son referidas por un for y
por el resultado de las operaciones matemáticas, para que estas operaciones se lleven
a cabo se necesita declarar la librerı́a math.h al inicio de sintetizadorview.cpp.
Siguiendo con la aplicación se pretende visualizar la octava de un teclado en la
vista principal. El primer paso es dibujar trece botones en el formulario, acomódelos de
tal forma que aparenten el tamaño de una tecla blanca y una tecla negra como las del
teclado. Cuando creamos un botón de mapa de bits es necesario poner su propiedad
Owner Draw a valor true, esto hace que se visualice el mapa de bits dependiendo del
estado del botón, enseguida añadiremos dos mapas de bits por cada botón para que
aparenten una tecla, una para cuando la tecla este pulsada y otra para cuando este en
reposo, los mapas de bits deben ser creados por usted en cualquier programa de edición
de imágenes (Paint Brush, Corel Draw, etc.) en nuestro caso usamos Macromedia
Flash. Ahora abra el editor de recursos para importar estas imágenes como recursos
de tipo bitmap, asigne a cada una de las imágenes un ID compuesto por el titulo del
botón (en nuestro caso BOTON) más una letra U o D (Up, Down) correspondiente al
estado del botón, ponga los ID entre comillas para sean considerados como cadenas y
no como constantes (BOTONU, BOTOND). En el archivo sintetizadorview.h declare
un objeto miembro de CBitmapButton.
class CSintetizadorView : public CFormView
{
public:
46
CBitmapButton Boton1;
// Overrides
}
Por último, para cargar los recursos mapa de bits, el botón debe recibir el mensaje
AutoLoad, el cual tiene dos parámetros: el ID del botón y la dirección al objeto. Esta
operación se realiza desde la función miembro OnInitialUpdate.
void CSintetizadorView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit(false);
}
Boton1.AutoLoad(IDC_BOTON1, this);
UpdateData(false);
Repita los pasos anteriores para los demás botones.
Cada vez que se pulsa un botón es generado el mensaje WM COMMAND, este
mensaje es manipulado por la función OnCommand, la cual se encargará de llamar a
la función fillplaybuffer y asignarle un valor dependiendo del botón pulsado. Ahora ejecute Class Wizard, seleccione la clase CSintetizadorView, el objeto CSintetizadorView
y el mensaje OnCommand, oprima el botón Add Function.. y enseguida Edit Code y
edite esta función de la siguiente manera, siguiendo la secuencia:
BOOL CSintetizadorView::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case IDC_BOTON1:
raiz = pow(cua, -9);
fillplaybuffer();
break;
case IDC_BOTON2:
raiz = pow(cua, -8);
fillplaybuffer();
break;
...
...
...
case IDC_BOTON10:
raiz = 1;
fillplaybuffer();
47
break;
...
...
...
case IDC_BOTON13:
raiz = pow(cua, 3);
fillplaybuffer();
break;
}
return CFormView::OnCommand(wParam, lParam);
}
5.4.
Programando el controlador driver de sonido
El parámetro wParam, contiene el elemento del recurso que ha hecho que se envı́e
este mensaje, de esta manera mediante el uso de un switch, se puede identificar el
botón sobre el que se ha pulsado. El valor raiz es enviado a la función fillplaybuffer,
este valor determinará la nota que tocará cada botón, esto se explicará más adelante.
La función fillplaybuffer es la encargada de llenar un buffer con los datos de la
señal fundamental y sus armónicos, y de mandarlos de la tarjeta de sonido. Utilizando AppWizard declare la función fillplaybuffer de tipo void y edı́tela de la siguiente
manera:
void CSintetizadorView::fillplaybuffer()
{
HWAVEOUT fd;
WAVEFORMATEX wf;
WAVEHDR wh;
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = 1;
wf.nSamplesPerSec = SAMPLE_RATE;
wf.wBitsPerSample = 8;
wf.nBlockAlign = 1;
wf.nAvgBytesPerSec = SAMPLE_RATE;
wf.cbSize = 0;
waveOutOpen(&fd, WAVE_MAPPER, &wf, 0, 0, CALLBACK_NULL);
for(i=0;i<MAXBUF;i++)
{
son[i]=(BYTE)((47+47*sin(fAngle))+(16+aV1*sin(fAngle2))+
(16+aV2*sin(fAngle3))+(16+aV3*sin(fAngle4))+
(16+aV4*sin(fAngle5))+(16+aV5*sin(fAngle6)));
48
fAngle += 2 * pi * aH1*raiz/SAMPLE_RATE;
fAngle2 += 2 * pi * aH1*2*raiz/SAMPLE_RATE;
fAngle3 += 2 * pi * aH1*3*raiz/SAMPLE_RATE;
fAngle4 += 2 * pi * aH1*4*raiz/SAMPLE_RATE;
fAngle5 += 2 * pi * aH1*5*raiz/SAMPLE_RATE;
fAngle6 += 2 * pi * aH1*6*raiz/SAMPLE_RATE;
if(fAngle > 2*pi)
{
fAngle -= 2*pi;
}
if(fAngle2 > 2*pi)
{
fAngle2 -= 2*pi;
}
if(fAngle3 > 2*pi)
{
fAngle3 -= 2*pi;
}
if(fAngle4 > 2*pi)
{
fAngle4 -= 2*pi;
}
if(fAngle5 > 2*pi)
{
fAngle5 -= 2*pi;
}
}
}
if(fAngle6 > 2*pi)
{
fAngle6 -= 2*pi;
}
wh.lpData = son;
wh.dwBufferLength = MAXBUF;
wh.dwFlags = 0L;
wh.dwLoops = 0L;
waveOutPrepareHeader(fd, &wh, sizeof(WAVEHDR));
waveOutWrite(fd, &wh, sizeof(WAVEHDR));
Sleep(150);
waveOutReset(fd);
waveOutUnprepareHeader(fd, &wh, sizeof(WAVEHDR));
waveOutClose(fd);
Declare las variables; i como tipo entero, fAngle a fAngle6 como tipo double y
son[MAXBUF] como tipo CHAR. La estructura utilizada para el llenado de buffer es
49
parecida a la función fillbuffer explicada en el capitulo 4, sólo que en esta ocasión realiza una serie de Fourier con los parámetros antes mencionados. El parámetro fAngle
recibe el valor de la barra horizontal, el cual tiene por default 440 Hz, al mismo tiempo
es multiplicado por un valor que corresponde al armónico en el que se encuentra y por
un valor raiz que es enviado por el botón que se pulso. Defina un parámetro cua con
un valor de raı́z doceava de dos, este valor es el que determina el intervalo que hay de
una tecla a la siguiente, de esta manera en la función OnCommand, el parámetro cua
es elevado a cierta potencia dependiendo del botón en el que se encuentre (nuestra
tecla central es la nota LA4) y se iguala a raiz (Ecuacion 5.1), el cual es enviado a
fAngle para determinar la nota. La frecuencia 440 Hz, se encuentra en el botón 10 y
es a partir de ésta que se determinan las demás notas de la octava.
raiz = pow(cua, Boton);
(5.1)
Defina las variables SAMPLE RATE con un valor de 11025, pi con un valor de
3.14159 y MAXBUF con un valor de 3200. Las estructuras utilizadas en esta función ya han sido explicadas en el capı́tulo 4, no olvide incluir el archivo de cabecera
mmsystem.h e incluir en las opciones de link la librerı́a winmm.lib.
5.5.
Resumen
En este capı́tulo presentamos conceptos importantes para el diseño, tales como
sistema de coordenadas, pı́xel, mapas de bits, recursos, entre otros. Al mismo tiempo
desarrollamos y explicamos los pasos a seguir para la implementación del sintetizador,
mostrando cada uno de los principales programas para la manipulación de audio
analógico.
50
Capı́tulo 6
Pruebas y Resultados
En el capı́tulo anterior explicamos como asignarle ciertos comportamientos a cada
uno de los elementos utilizados en este proyecto, tales como el rango a las barras de
desplazamiento, el sonido que se produce al pulsar los diferentes botones, dibujar las
diferentes señales ocupadas, etc. En este capı́tulo presentamos algunos resultados de
nuestro sistema Sintetizador y describiremos su operación.
6.1.
Ambiente de compilación y generación de código
Usando el lenguaje de programación Visual C++, realizamos un tipo de compilación llamado release, con esto conseguimos generar un archivo ejecutable Sintetizador.exe que podrá ser ejecutado en cualquier sistema operativo Windows (95 o
superior). Para generar un archivo ejecutable .exe de tipo release, es necesario llevar
acabo los siguientes pasos; a) Seleccione la configuración Win32 Release de la caja de
herramientas Set Active Project Configuration, que se encuentra en el menú Build de
la barra de herramientas, b) Al cambiar de un tipo de compilación a otra, deberá especificar en las opciones de linker la librerı́a winmm.lib, para esto presione ALT+F7,
seleccione la pestaña Link, escriba la librerı́a en la caja de texto Object/library modules y presione el botón OK para hacerla valida, c) Y por último en el menú Build
de la barra de herramientas, de clic en la opción Build Sintetizador.exe. Cabe men-
51
Figura 6.1: Vista principal del sintetizador.
52
cionar que con el tipo de compilación Debug, el archivo ejecutable no operará en
PC’s (Personal Computer) que no cuenten con el software Visual C++ instalado.
Una vez creado el archivo ejecutable éste se encontrará en la carpeta release, la cual
está ubicada en la carpeta principal de nuestro proyecto.
6.2.
Aspecto visual del sintetizador
Al dar doble clic en el archivo Sintetizador.exe se visualizará nuestra aplicación ya
terminada, ésta tendrá un aspecto similar al mostrado en la Figura 6.1. En la esquina
superior izquierda de esta figura se encuentra un marco con el tı́tulo Afinador que
contiene; una barra horizontal y una caja de texto. La barra horizontal tiene un valor
inicial de 440 Hz, un valor máximo de 466 Hz y un valor mı́nimo de 415 Hz, como se
muestra en la Figura 6.2, cuando el usuario actúe sobre la barra está modificará su
valor, el cual se visualizará en la caja de texto y será enviado a la función que está realizando la sı́ntesis (fillplaybuffer). Ésta función es la encargada de llenar el buffer de
audio para ser enviado a la tarjeta de sonido, lo cual significa que de acuerdo con los
valores máximos y mı́nimos en la barra, las teclas pueden llegar a subir o a bajar un
tono, por lo tanto, la barra nos servirá como un afinador. Cuando el usuario actúe
sobre la barra podrá modificar el tono de las teclas para que éste sea de su agrado.
Figura 6.2: Valores mı́nimo, central y máximo de la barra horizontal.
Debajo del marco Afinador, se encuentra un marco con el tı́tulo Amplitud que
contiene cinco barras verticales y cinco cajas de texto. Las barras representan la
amplitud de los armónicos de la señal fundamental utilizados, los cuales se pueden
visualizar en la parte inferior izquierda de la vista. En la parte inferior derecha se
53
visualiza la señal resultante de la suma de los armónicos, la cual es enviada a la tarjeta
de sonido. Cuando el usuario actúa sobre alguna de las barras verticales cambiará su
valor, el cual se visualizará en su respectiva caja de texto situada debajo de cada barra
como se muestra en la Figura 6.3. Las barras pueden obtener un valor mı́nimo de cero
y un máximo de dieciséis, esto es por razones de normalización, ya que en nuestro
programa fuente, la amplitud máxima de cada armónico es de treinta y dos, este
valor representa el 12.6 % del 100 % que nuestro buffer puede tocar sin distorsionar el
sonido (8 bits, de 0 a 254), siendo la señal fundamental la de mayor amplitud con un
37 %. Cuando sumamos la señal fundamental con la amplitud máxima de los cinco
armónicos nos da el 100 % de nuestro buffer.
Figura 6.3: Barras de desplazamiento verticales, con una amplitud modificada.
6.3.
Control de parámetros del sintetizador
Cuando el usuario actúe sobre alguna de las barras su valor es enviado a la función
que se encarga de realizar la sı́ntesis para el llenado del buffer, al mismo tiempo es
enviado a una función encargada de graficar la señal fundamental, los armónicos
y la resultante (la función Graficador fue mostrada en el capı́tulo 4). Por ejemplo,
cuando el usuario actúa sobre la barra Arm 3 su valor es enviado a las funciones antes
mencionadas y se visualiza un cambio de amplitud en la señal ubicada en el marco
54
con el titulo Tercer Armónico, que encontramos en la parte inferior izquierda de la
vista principal del proyecto, al mismo tiempo visualizamos un cambio en la señal
resultante ubicada en el marco con tı́tulo Resultante, que encontramos en la esquina
inferior derecha de la vista de nuestro proyecto, como se muestra en la Figura 6.4.
Figura 6.4: Tercer armónico con amplitud modificada.
Cuando el usuario actúa sobre la barra Arm 5 el valor de éste es enviado a la
función Graficador y se visualiza un cambio de amplitud en la señal ubicada en el
marco con el tı́tulo Quinto Armónico, que se encuentra en la parte inferior izquierda
de la vista principal del proyecto, al mismo tiempo visualizamos un cambio en la señal
resultante ubicada en el marco con tı́tulo Resultante, que encontramos en la esquina
inferior derecha de la vista de nuestro proyecto como se muestra en la Figura 6.5.
6.4.
Controlando los armónicos
El usuario puede actuar sobre varias barras modificando diferentes armónicos,
cuando esto ocurra los valores de las barras serán enviados a las funciones antes
mencionadas y se visualizará un cambio en los marcos situados en la parte inferior de
la vista principal de nuestro proyecto como se muestra en la Figura 6.6.
55
Figura 6.5: Quinto armónico con amplitud modificada.
Figura 6.6: Todos los armónicos modificados
56
La razón por la que utilizamos solamente cinco armónicos es por fines prácticos,
ya que uno de los principales objetivos es demostrar que se puede lograr una sı́ntesis
de audio mediante la serie de Fourier (usted puede adicionar o quitar el número de
armónicos que desee, modificando el proyecto desde Visual C++).
6.5.
Control del teclado
En la parte superior derecha encontramos un marco con el tı́tulo Teclado como el
que se muestra en la Figura 6.7. El teclado está conformado por 13 botones, que con
la ayuda de un par de mapas de bits simulan las teclas de un sintetizador, ya sean
en estado de reposo o presionadas como se muestran en la Figura 6.8, y su principal
objetivo es que el usuario tenga una vista más amigable al interactuar con el proyecto.
Figura 6.7: Vista del Teclado.
El teclado cuenta con una frecuencia central de 440 Hz, que corresponde a la nota
LA4 y se encuentra ubicada en la tecla número 10, es a partir de ésta que se calcula
√
el valor de las demás teclas, multiplicando la frecuencia central por 12 2 para subir
medio tono y se ubica en la tecla número 11 y multiplicar la frecuencia central por
√
( 12 2)−1 para bajar medio tono y se ubicará en la tecla número 9, para las demás
√
teclas es necesario elevar el valor 12 2 a una potencia positiva o negativa dependiendo
57
de la tecla (para mayor información consulte el capı́tulo 4). Estos valores son enviados
a la función fillplaybuffer mencionada en capı́tulos anteriores, para realizar el llenado
del buffer y enviarlo a la salida de la tarjeta de sonido.
Figura 6.8: a)Tecla en reposo. b)Tecla pulsada.
A continuación se muestra una tabla, con los valores que deben tener las barras
para asemejarse a un Oboe ó a un Órgano de Jazz, el sonido fue comparado con un
sintetizador marca CASIO, modelo CT-680:
Tabla 6.1: Valores de las barras de desplazamiento
IN T RU M EN T O
OBOE
Organo de Jazz
6.6.
Af inador
450
450
Arm2 Arm3 Arm4 Arm5 Arm3
12
10
0
8
8
16
0
0
14
11
Resumen
En este capı́tulo presentamos la utilización de nuestro proyecto mostrando gráfica
y textualmente los principales pasos a seguir para su funcionamiento básico. Cabe
mencionar que en este proyecto no se utiliza MIDI (Music Interfaz Digital Instrument), se utiliza audio analógico digitalizado.
58
Capı́tulo 7
Conclusiones y Trabajos Futuros
Esta tesis presentó el diseño elemental de un sintetizador de notas musicales,
el cual describimos en un programa de computadora digital. Este dispositivo de
software produce sonidos mediante la generación de señales periódicas y funciones
matemáticas con la ayuda de elementos electrónicos programados, tales como osciladores, filtros, mezcladores de señales, etc. Fı́sicamente estos elementos son costosos
y ocupan grandes espacios, lo cual puede llegar a ser molesto para el usuario. Pensando en esto último, nos dimos cuenta que un modelo por software puede igualar
a un modelo por hardware y no ser estorboso, ya que lo único que se necesita para
usarlo es una computadora digital (p.e. PC), que prácticamente es necesaria en la
vida cotidiana de toda persona.
Para iniciar con la elaboración de nuestro proyecto, primero debimos elegir un
lenguaje de programación que permitiera diseñar la interfase de usuario. Este lenguaje deberı́a ser accesible para el programador a fin de que los resultados obtenidos
pudieran observarse en una computadora estándar. El resultado de esta elección,
como ya se ha mencionado, fue el lenguaje de programación Visual C++.NET, el
cual nos ofreció además de su fácil manejo, la oportunidad de crear objetos bastante
amigables para los usuarios. De esta manera, el diseño de nuestro sintetizador se ha
realizado con medios comunes en el mercado.
Desde un principio, las bases de nuestro proyecto estuvieron planteadas: crear
59
señales senoidales para representar una sumatoria, en otras palabras, programar una
Serie de Fourier. El resultado deberı́a ser visible en la ventana principal del proyecto
para ver la forma de onda que se estarı́a mandando a la tarjeta de sonido. Lo anterior
fue logrado programando funciones matemáticas en Visual C++.NET, algunas de estas funciones fueron la suma, la multiplicación y el seno. Con estas funciones, algunas
veces llamadas primitivas, programamos nuestra Serie de Fourier para comprobar
las sı́ntesis de onda, con esto obtuvimos un número bastante grande de valores, los
cuales tenı́amos que almacenar en memoria operativa (buf f er de audio) con el fin de
tener un mejor control de los datos.
Una vez generada la sı́ntesis, el siguiente paso fue enviar los datos almacenados en
nuestro buf f er, a otro buf f er que se encuantra asociado al driver de la tarjeta de
sonido (una Sound Blaster). Sin embargo, al iniciar este proceso nos dimos cuenta de
la poca información que existe sobre cómo programar drivers de sonido. Encontramos
varios libros y notas que hablaban acerca de cómo enviar un archivo WAVE, previamente grabado, a la tarjeta de sonido, pero lo anterior no era suficiente; fue hasta que
se consultó el artı́culo de una revista que hablaba acerca de la generación de audio
por medio de una onda senoidal, que pudimos avanzar en nuestro proyecto. Esto nos
ayudó enormemente en nuestra investigación, sin embargo, el artı́culo está escrito en
inglés, lo cual reafirmaba la poca información disponible en este paı́s al respecto.
Para enviar los datos almacenados en el buffer a la tarjeta de sonido, ocupamos
instrucciones de audio de bajo nivel que se encuentran en la biblioteca de funciones
multimedia mmlib.lib. Algunas de las instrucciones de audio más importantes son;
WavePrepareHeader() que se encarga de preparar al buffer para ser enviado a la
tarjeta de sonido, y WaveOutWrite() que se encarga de sacar los datos de la tarjeta
de sonido a los altavoces de la PC; estos procesos se explican más detalladamente en
el capı́tulo 4 de esta tesis.
Hecho lo anterior, los siguientes pasos fueron sencillos. Para la distribución de las
notas del teclado utilizamos el valor matemático raı́z doceava de dos, que representa
60
el intervalo existente entre una nota y la siguiente (un semitono). El resultado de esta
operación fue multiplicado por la frecuencia central utilizada (LA4 =440Hz) con el fin
de encontrar la frecuencia de la siguiente nota (LA#), y ası́ sucesivamente. Cada uno
de estos valores fueron asignados a un botón ubicado en la vista principal y ası́ darle
el sonido de la nota correspondiente.
Para cambiar el timbre de nuestro sintetizador, controlamos las formas de onda
senoidales en su amplitud y frecuencia, esto se consiguió por medio de barras de
desplazamiento, asignándole el valor de dichas barras a las amplitudes y frecuencias
que se encuentran en la formula de la sı́ntesis de onda. De esta manera es posible no
solo escuchar algún instrumento como una trompeta o un oboe, sino también ver su
forma de onda al mismo tiempo.
En resumen, las principales contribuciones de esta tesis son las siguientes:
La realización de una Serie de Fourier con algoritmos de programación y métodos numéricos.
La generación de audio analógico por medio de una suma de señales.
La programación de instrucciones de audio de bajo nivel con lo cual se facilitará la construcción software de drivers de sonido.
Técnicas de graficación en Visual C++.NET.
Y por último, un sintetizador virtual para PC capáz de ejecutarse en sistemas
windows 95 o superior.
7.1.
Trabajos Futuros
Continuando con los resultados de nuestra investigación, presentamos algunas
sugerencias en cuanto a trabajos futuros. Pensamos que es posible implementar una
serie de elementos, en cuanto a estética, funcionalidad, y aplicación cientı́fica.
61
Respecto a la estética, se puede mejorar la apariencia de las barras verticales y la
barra horizontal, mediante la implementación de perillas giratorias en tercera dimensión, ası́ mismo, perfeccionar la apariencia del teclado. Además es posible mejorar
la graficación de las señales mediante la implementación de color y aumento de la
resolución de la gráfica.
En cuanto a funcionalidad, se pueden efectuar varias acciones para el mejoramiento del proyecto. Por ejemplo, sólo se cuenta con la frecuencia fundamental y cinco
de sus armónicos, que son señales senoidales. Para resolver esta limitante se puede
implementar una mayor cantidad del contenido armónico a nuestro sistema, mediante la integración de formas de onda cuadrada, cosenoidal, diente de sierra, etc. Esto
permite obtener una mayor variedad de instrumentos musicales, ya que cada forma
de onda cuenta con diferente contenido armónico. Ası́ mismo, es posible crecer la
funcionalidad de nuestro sintetizador en cuanto a la amplitud, tono y timbre, integrando generadores de ruido (blanco o rosa) y envolventes de onda. Esto permite la
simulación dinámica de los instrumentos musicales, mediante el control del ataque,
decaimiento, sostenimiento y la relajación tal como se ha descrito en el capı́tulo tres.
Ya que en nuestro trabajo cuenta sólo con una octava en el teclado, en el futuro se
pueden implementar cuatro o más octavas para obtener un rango mayor de frecuencias. Además, se puede agregar una función para que el sintetizador pueda dividir el
teclado en dos partes. Es decir, si cuenta con cuatro octavas, las primeras dos tocarı́an
un instrumento, por ejemplo el piano y las dos octavas restantes tocarı́an un acordeón
como lo hacen los sintetizadores profesionales. Se puede perfeccionar el teclado, para
que puedan ejecutarse acordes, esto es, aumentar el número de teclas que se tocan al
mismo tiempo.
Como ya se sabe, la principal función de un sintetizador es generar una gran
variedad de sonidos, que simulen instrumentos musicales. Por ello, a este proyecto se
puede agregar un selector de instrumentos, esto es, tener configurado el sistema para
que con una perilla, pueda seleccionar el instrumento o los instrumentos que se deseen
62
tocar, por ejemplo un piano, un violı́n, una flauta, etc. Se tiene pensado realizar una
versión comercial que pueda competir con la industria de los sintetizadores realizados
por software, en cuanto al costo y a la transportabilidad.
Respecto a las aplicaciones en la ciencia y en la tecnologı́a los resultados obtenidos
pueden ser aprovechados en algunas áreas como: Procesamiento de Señales Digitales (DSPs), reconocimiento de patrones de imágenes, reconocimiento de patrones de
sonido, e instrumentos de medición como osciloscopios, generadores de funciones, medidores de ruido, e instrumentos de ultrasonido.
Por otra parte, para un músico puede ser de gran utilidad, ya que donde quiera
que él se encuentre haciendo su trabajo (tocando), si cuenta con una PC podrá tener
a su alcance un sintetizador de sonidos. Además, en la educación musical puede ser
de gran ayuda como material didáctico, por ejemplo, aprender el orden de las notas
en un teclado e iniciarse dentro de la música.
Por útlimo, cabe mencionar que esta tesis se ha desarrollado conjuntamente con
el Dr. Maximino Peña Guerrero y el Ing. José de Jesús Negrete, profesores de la
academia de acústica de la ESIME-Zacatenco. Actualmente se encuentran desarrollando más proyectos en ciencia y tecnologı́a acústica.
63
Bibliografı́a
[1] Beristáin, Sergio, AUDIO Ed. Particular, México D.F., Agosto de 1998, 201 pgs.
(p: 10)
[2] Ceballos, Fco. Javier, Visual C++ Aplicaciones para Win 32, Alfaomega Ra-Ma,
México 2004, 717 pgs. (p: 38)
[3] Ceballos, Fco. Javier, Visual C++ Programación Avanzada en Win 32, Alfaomega Ra-Ma, México 2000, 852 pgs. (p: 33)
[4] Floyd, Thomas, Dispositivos Electrónicos, LIMUSA Noriega Editores, 1996,
Colección Textos Politécnicos, 974 pgs. (p: 17)
[5] Moog Robert A., “Voltaje-Controlled Electronic Music Modules”, R. A. Moog
Co., Trumansburg, New York, Journal of the Audio Engeering Society, january,
1968, vol. 16 No. 1. pp. 200-206. (p: 36)
[6] Moog Bob., “MIDI: Musical Instrument Digital Interface”, Journal of the Audio
Engeering Society, may 1986, v. 34 No. 5. pp. 394-404. (p: 35)
[7] Peña G. M., Çaptura de Múltiples Eventos MIDI en Tiempo de Ejecución”.
Inédita. México. Tesis presentada para aspirar al grado de Doctor en Ciencias
en Ingenierı́a Eléctrica. Centro de Investigación y de Estudios Avanzados del
Instituto Politécnico Nacional, 2005. 160 pgs. (p: 11)
[8] Petzold, Charles, ”Exploring Wave Form Audio Generating Sine Waves in Software”, PC Magazine, November 26, 1991, pp 505-510. (p: 32)
[9] Petzold, Charles, Programing Windows, Microsoft Press, 1999, 1479 pgs. (p: 28)
64
Glosario
CAC: Computer Aided Composer, Composición Asistida con Computadora. Colección de programas de sof tware agrupados en un medio ambiente de computadora
digital que interactúa con el usuario para estudiar, desarrollar, simular e interpretar
música de cualquier tipo, incluyendo toda clase de sonidos.
Generador de tonos: Dispositivo electrónico digital que puede generar una gran
variedad de sonidos musicales de acuerdo con las notas que recibe. Es un sintetizador de sonidos similares a los producidos por instrumentos musicales. Se conecta,
a través de la interfaz MIDI, a computadoras digitales o cualquier otro controlador
MIDI, los cuales envı́an notas musicales en forma de comandos para reproducir la
música de acuerdo con la información que tiene un archivo MIDI, u otra forma de
almacenamiento digital.
KL: Kernel for a musical Language, núcleo para un lenguaje musical. Compilador
de estructuras musicales desarrollado por el autor para estudiar el procesamiento
electrónico de la música. La entrada es un programa fuente que tiene cadenas de texto
escritas en lenguaje natural (do re mi[ fa sol sil fa]...) de las notas musicales
(solfeo). La salida son gráficas, partituras, y/o el sonido de una canción escrita en el
programa fuente.
MIDI: Musical Instrument Digital Interface, interfaz digital para instrumentos musicales. Protocolo de comunicaciones de hardware y sof tware estándar diseñado por
los fabricantes de instrumentos musicales electrónicos.
Pentagrama: Grupo de cinco lı́neas horizontales para escribir sı́mbolos gráficos que
tiene el lenguaje musical y que determina una melodı́a.
Sintetizador: Dispositivo electrónico digital, similar a un piano, que puede generar
una gran variedad de sonidos musicales. Las notas son activadas por el sistema de
teclas, o también por aquellas que recibe a través de su interfaz MIDI interconstruida
y conectada con computadoras digitales u otros dispositivos similares.
Sistema de tiempo real: Dispositivo que controla una aplicación dedicada la cual
tiene restricciones temporales bien definidas.
65
Solfeo: Lenguaje natural musical, compuesto por las sı́labas do, re, mi, f a, sol, la
y si, para enseñar música cantando.
Tiempo real: Momento actual de respuesta al procesamiento inmediato de datos
que interactúan con procesos fı́sicos.
UART: Unasynchronous Asynchronous Reciver Transmitter, transmisor y receptor
sı́ncrono ası́ncrono. Dispositivo electrónico digital de comunicaciones serial que transforma datos con formato serie a paralelo para recibir o transmitir información. La
velocidad de transferencia, cuando se utiliza en instrumentos musicales electrónicos,
es de 32,250 Bauds lo que permite enviar y recibir, en promedio, hasta 142 notas
musicales en un segundo.
VLSI: Very Large Scale Integration (integración a escala muy elevada). Técnica de
fabricación de circuitos integrados electrónicos en espacios bastantes reducidos.
66
Φ
67

Documentos relacionados