Una incursión en el mundo de los sonidos

Es "incursión" es un teclado que interpreta sonidos básicos obtenidos a partir de frecuencias simples y que afectuosamente llamo Sinte-mor (Sinte para los colegas). Este ejemplo tiene una componente visual que es un efecto para mostrar que la tecla ha sido pulsada. Pero, fundamentalmente, lo que muestra esta aplicación es cómo generar sonidos.

La primera aproximación a este instrumento se hará en base a la disposición que muestra la Figura 8-5. En ella se puede ver una docena de teclas que hemos decorado con colores blanco y negro. Los bordes de las teclas blancas se han puesto a color negro para mostrar la separación entre ellas. Una barra vertica, a la izquierda, nos servirá para controlar el volumen del sonido generado. En la parte inferior se puede ver un campo de texto en el que se muestran las teclas (letras) en la secuencia en que se harán corresponder con las teclas del teclado musical. Vamos a suponer que no se exige que sea polifónico ya que es nuestro primer itento: sólo sonará una tecla en cada instante de tiempo, aunque se pueda pulsar más de una tecla a la vez.

Figura 8-5. Aplicación teclado instrumental: primera aproximación.

Entienda el atrevido título de esta sección: estamos realizando una simulación de lo que hace un sintetizador, generar una secuencia a partir de las teclas pulsadas en cada momento. Además en esos instrumentos se pueden añadir efectos e incluso cambiar el bando de sonidos que se asocian a las teclas. En nuestro caso la síntesis de sonido es la más básica: a partir de generación de frecuencias (ni siquiera haremos modulación, no es polifónico vamos)

Cada tecla tiene el mismo código, hemos así aprovechado que se puede clonar un objeto para replicar las tres primeras teclas de la izquierda. Vemos sólo una de ellas como ejemplo de propiedades y del código asociado:

Figura 8-6. Un ejemplo de tecla para el teclado instrumental propuesto.

on mouseUp
  set the beepPitch to the effective label of me
  beep 1
end mouseUp
                   

Con este código se asigna el sonido a generar por la orden beep y se lleva a cabo con una duración de una vez lo que indica la propiedad beepDuration. Puede ya empezar a hacer sonar este "instrumento" con el ratón.

Para controlar la intensidad del sonido se ha dispuesto un mando para modificar el volumen del sonido que se genera. No es la rueda de un sintentizador real pero servirá. Este controla otra propiedad asociada a la orden beep:

on scrollbarDrag nouValor
  set the beepLoudness to nouValor
end scrollbarDrag
                   

Figura 8-7. Propiedades del mando de volumen del teclado instrumental propuesto.

Hemos cubierto una etapa: tenemos una representación gráfica del teclado, que suena y cuyas propiedades de cómo (frecuencia) y cuánto (intensidad) tenemos ya controlado. Pero queremos que se pueda utilizar el teclado para realizar "interpretaciones" con este engendro. Para ello, dejaremos que sea la tarjeta quien reciba todas las pulsaciones y se encargue de hacer sonar la nota correspondiente.

Finalmente, la tarjeta es el gran "intérprete" de las acciones, mira qué tecla es. No se deje asustar por las líneas de código, son sólo tres eventos:

La única complejidad es el manejo de las estructuras (los vectores) que hacen corresponder la tecla (letra) con el nombre de la nota y la frecuencia asociada. El interés de esta aproximación es que permite pensar en una segunda etapa donde estos valores se obtengan por una configuración de fichero o una opción del programa para alterar o cambiar las asignaciones inciales. El mecanismo sigue siendo válido.

on openCard
  set the beepLoudness to "5"
  set the thumbPosition of scrollbar "mandoVolumen" to "5"
end openCard

local  kbd = "a e s d t f h y j k i l"
local teclat = "DO DO# RE MI MI# FA SOL SOL# LA SI SI# DO-A"
local  vFrecuencies = "200 300 250 350 450 400 500 600 550 700 800 750"

on keyDown quinaTecla
  if (quinaTecla is among the words of kbd) then
    put "Activant tecla" && quinaTecla && wordOffset(quinaTecla, kbd) &&\
        the word wordOffset(quinaTecla, kbd) of teclat
    set the backgroundColor of\
        graphic ( the word wordOffset(quinaTecla, kbd) of teclat ) to gray
    set the beepPitch to the word wordOffset(quinaTecla, kbd) of vFrecuencies
    beep 1
  end if
end keyDown

on keyUp quinaTecla
  if  (quinaTecla is among the words of kbd) then \
      set the backgroundColor of \
      graphic ( the word wordOffset(quinaTecla, kbd) of teclat )  to\
      the borderColor of graphic ( the word wordOffset(quinaTecla, kbd) of teclat )
end keyUp
                   

Un último apunte de este ejemplo: hemos situado un campo de texo en la parte inferior (que llamamos "partitura") donde se puede introducir una secuencia de pulsaciones y hacer que el "instrumento" las intrerprete de forma autónoma. Así se puede ver que se permiten otros usos para este ejemplo de "teclado musical" virtual. El código permite almacenar las pulsaciones que se hagan sobre él (y sólo cuando él está activo) y para que cuando se pulse la tecla Return se generen los eventos correspondientes a pulsar y soltar estas teclas, como si lo hubiese hecho el usuario: el evento KeyDown consume (recuerde que de no hacerlo el mensaje discurre por la jerarquía de objetos y acabaría activando el manejador de la tarjeta) la pulsación de una tecla, así no llega hasta la tarjeta y no suena nada; hasta que se utiliza la tecla de retorno de carro y entonces se envían con una secuencia de tiempo fija, simulando el tiempo que podría tardar el usuario en pulsarlas.

on keyDown quinaTecla
  #Nota: fa falta per tal que no aplege a la tarjeta
  put quinaTecla after me
end keyDown


on returnInField
  focus on scrollBar "mandoVolumen"
  repeat for each character c in the text of me
    put "Llansant" && c
    send "keyDown" && c to this card in  (100 * the offset(c, the text of me)) milliseconds
    send "keyUp" && c to this card in  (110 *  the offset(c, the text of me)) milliseconds
  end repeat
  wait 2 seconds
  focus me  
end returnInField
                   

Quedan algunas cosas que se pueden hacer y que dejo a consideración del lector: