1.4 Construcción del software

Esta sección describe algunas de las decisiones de programación que hicimos cuando diseñamos el programa LilyPond.


Representación musical

Idealmente, el formato de entrada de cualquier sistema de formateado de alto nivel es una descripción abstracta del contenido. En este caso, eso sería la propia música. Ello presenta un enorme problema: ¿cómo podemos definir qué es la música realmente? En lugar de buscar una respuesta, le hemos dado la vuelta a la pregunta. Escribimos un programa capaz de producir música impresa, y luego ajustamos el formato de forma que sea lo más escueto posible. Cuando el formato ya no se puede recortar más, por definición nos estamos quedando con el propio contenido. Nuestro programa sirve como una definición formal de un documento musical.

La sintaxis es también el interfaz de usuario de LilyPond, de aquí que sea tan fácil teclear:

{
  c'4 d'8
}

para crear un Do central negra (Do 4) y un Re por encima del Do central, corchea (Re 4).

[image of music]

A una escala microscópica, esta sintaxis es fácil de usar. A una escala mayor, la sintaxis necesita también una estructura. ¿De qué otra forma podríamos introducir piezas complejas como sinfonías u óperas? La estructura se forma por medio del concepto de expresiones musicales: combinando pequeños fragmentos de música dentro de otros más grandes, se puede expresar una música más compleja. Por ejemplo:

f'4

[image of music]

Las notas simultáneas se pueden construir encerrándolas dentro de << y >>:

<<c4 d4 e4>>

[image of music]

La expresión se pone en secuencia encerrándola dentro de llaves { … }:

{ f4 <<c4 d4 e4>> }

[image of music]

Esto es también una expresión, y así se puede combinar de nuevo con otra expresión simultánea (una blanca) utilizando <<, \\ y >>:

<< g2 \\ { f4 <<c4 d4 e4>> } >>

[image of music]

Tales estructuras recursivas se pueden especificar limpia y formalmente dentro de una gramática independiente del contexto. El código del analizador sintáctico también se genera a partir de esta gramática. Dicho de otra forma, la sintaxis de LilyPond está definida claramente y sin ambigüedades.

Los interfaces de usuario y la sintaxis son aquello que la gente ve y con lo que trata más frecuentemente. Son, en parte, cuestión de gusto, y también objeto de mucha discusión. Aunque las discusiones sobre el gusto tienen su mérito, no son muy productivas. Bajo el punto de vista más amplio de LilyPond, la importancia de la sintaxis de la entrada es pequeña: inventarse una sintaxis limpia es fácil, pero escribir un código de formatead que sea decente es mucho más difícil. Esto queda ilustrado por la cantidad de líneas que están dedicadas a los componentes respectivos: el análisis sintáctico y la representación se llevan menos del 10% del código fuente.

Cuando estábamos diseñando las estructuras utilizadas dentro de LilyPond, tomamos algunas decisiones de forma diferente a como es aparente en otros programas. Consideremos la naturaleza jerárquica de la notación musical:

[image of music]

En este caso, hay notas agrupadas en acordes que están dentro de compases, que pertenecen a pentagramas. Esto se parece a una estructura ordenada de cajas anidadas unas dentro de otras:

nestedboxes

Desgraciadamente la estructura resulta ordenada porque está basada en algunas suposiciones excesivamente restrictivas. Este extremo se hace aparente si tenemos en cuenta un ejemplo musical más complejo:

[image of music]

En este ejemplo, los pentagramas parecen iniciarse y terminar a capricho, las voces saltan de un pentagrama a otro, y las pautas tienen tipos de compás diferentes. Muchos programas se las ven y se las desean para reproducir este ejemplo porque están construidos sobre la estructura de las cajas anidadas. Con LilyPond, por el contrario, hemos tratado de conservar el formato del código de entrada y la estructura lo más flexibles posible.


¿Qué símbolos grabar?

El proceso de formateo decide dónde colocar los símbolos. Sin embargo, esto sólo puede hacerse una vez que se ha decidido qué símbolos se deben imprimir: en otras palabras, qué notación utilizar.

La notación musical común es un sistema de registro de la música que ha evolucionado durante los últimos mil años. La forma que es hoy día de uso común data del Renacimiento temprano. Aunque la forma básica (es decir, puntos sobre una pauta de cinco líneas) no ha cambiado, los detalles aún evolucionan para expresar las innovaciones de la notación contemporánea. De aquí que la notación musical común abarque unos quinientos años de música. El ámbito de sus aplicaciones comprende desde melodías monofónicas hasta monstruosos contrapuntos para gran orquesta.

¿Cómo podemos ensillar a tal bestia de siete cabezas, y forzarla dentro de los confines de un programa de ordenador? Nuestra solución es escindir el problema de la notación (en oposición al grabado, es decir, a la tipografía) en fragmentos fácilmente digeribles y programables: cada tipo de símbolo se maneja por parte de un módulo separado conocido como plug-in. Cada plug-in es completamente modular e independiente, de manera que cada uno se puede desarrollar y mejorar por separado Estos plugines reciben el nombre de engravers o “grabadores”, por analogía con los artesanos que traducían las ideas musicales en símbolos gráficos.

En el ejemplo siguiente, comenzamos con un plug-in para la cabeza de las notas, el grabador Note_heads_engraver.

[image of music]

A continuación, un grabador del pentagrama, el Staff_symbol_engraver, añade la pauta:

[image of music]

el grabador de la clave o Clef_engraver define un punto de referencia para el pentagrama:

[image of music]

y el grabador de las plicas Stem_engraver añade las plicas.

[image of music]

El grabador Stem_engraver que traza las plicas recibe una notificación por cada nota que le llega. Cada vez que se ve la cabeza de una nota (o más, en el caso de un acorde), se crea un objeto plica y se conecta a la cabeza. Añadiendo grabadores para las barras, ligaduras, acentos, alteraciones, líneas divisorias, la indicación de compás y la armadura, obtenemos un fragmento de notación musical completo.

[image of music]

Este sistema funciona bien para la música a una voz, pero ¿qué tal para la polifonía? En la notación polifónica, muchas voces pueden llegar a compartir el mismo pentagrama.

[image of music]

En esta situación, las alteraciones accidentales y la pauta se comparten, pero las plicas, ligaduras, barras, etc., son privadas para cada voz. De aquí que los grabadores deban estar agrupados. Los grabadores de la cabeza de las notas, plicas, ligaduras, etc., van a un grupo llamado ‘contexto de voz’, mientras que los grabadores de la armadura, las alteraciones, los compases, etc., van a un grupo llamado ‘contexto de pauta’. En el caso de la polifonía, un solo contexto de pauta contiene más de un contexto de voz. De forma similar, varios contextos de pentagrama se pueden reunir dentro de un único contexto de partitura. El contexto de partitura es el contexto de notación del nivel más alto que hay.

[image of music]

Véase también

Referencia de funcionamiento interno: Contexts.


Arquitectura flexible

Al principio escribimos el programa LilyPond completamente en el lenguaje de programación C++; la funcionalidad del programa estaba grabada en piedra por parte de los desarrolladores. Se comprobó que esto no era satisfactorio por unas cuantas razones:

Estos programas se han solucionado integrando un intérprete para el lenguaje de programación Scheme y reescribiendo partes de LilyPond en Scheme. La arquitectura de formateo actual está construida alrededor de la noción de objetos gráficos, descritos por medio de variables y funciones de Scheme. Esta arquitectura coordina las reglas de formateo, el estilo tipográfico y las decisiones de formateo individuales. El usuario tiene acceso directo a la mayoría de esos controles.

Las variables de Scheme controlan las decisiones de disposición en la página. Por ejemplo, muchos objetos gráficos tienen una variable de dirección que codifica la elección entre arriba y abajo (o izquierda y derecha). A continuación vemos dos acordes, con acentos y símbolos de arpegio. En el primer acorde, los objetos gráficos tienen todas las direcciones hacia abajo (o hacia la izquierda). El segundo acorde tiene todas las direcciones hacia arriba (o hacia la derecha).

[image of music]

El proceso de dar formato a una partitura comprende la lectura y escritura de las variables de los objetos gráficos. Algunas variables tienen un valor preestablecido. Por ejemplo, el grosor de muchas líneas (una característica del estilo tipográfico) es una variable con un valor preestablecido. Somos libres de alterar este valor, dando a nuestra partitura una impresión tipográfica distinta.

[image of music]

Las reglas de formateado también son variables preestablecidas: cada objeto tiene variables que contienen procedimientos. Estos procedimientos realizan el formateo propiamente dicho, y mediante la sustitución de unos u otros, podemos modificar el aspecto de los objetos. En el ejemplo siguiente, la regla que gobierna qué objetos de cabeza se utilizan para producir el símbolo de la cabeza, se cambia a lo largo del fragmento musical.

[image of music]


LilyPond — Ensayo sobre grabado musical automatizado v2.24.4 (rama estable).