Ejercicio obligatorio 4

Fecha de entrega: Domingo 28 de junio

Introducción

El formato MIDI

El formato de archivos Standard MIDI File Format (SMF) de archivos .mid es un formato diseñado para almacenar secuencias de eventos musicales.

Un archivo MIDI está compuesto por un encabezado, que define las particularidades de ese archivo, y luego por pistas que cada una corresponde a un instrumento particular. Cada pista consiste en una sucesión de eventos que codifican las cosas que suceden en la pista.

Encabezado

El encabezado del archivo consiste en una secuencia:

+-------------+-------------+-------------+-------------+-------------+
|  Header ID  |   Tamaño    |   Formato   | Núm. pistas | Pulso negra |
+-------------+-------------+-------------+-------------+-------------+

Donde el campo formato es un uint16_t que admite los siguientes valores:

Valor

Significado

0

Pista única

1

Multipistas sincrónicas

2

Multipistas asincrónicas

Eventos

El formato MIDI distingue 8 tipos de eventos diferentes, y cada uno de ellos trae distintos parámetros y por lo tanto ocupa diferente espacio.

La siguiente es la lista de todos los eventos:

Valor

Longitud

Significado

1000

2

Nota apagada

1001

2

Nota encendida

1010

2

Nota durante

1011

2

Cambio de control

1100

1

Cambio de programa

1101

1

Variar canal

1110

2

Cambio de pitch

1111

2

Metaevento

Notar, además que el valor siempre tiene en alto su bit más significativo. El valor del bit más significativo es lo que distingue a los eventos de los datos.

A su vez el evento se codifica en un byte de la siguiente manera:

MSB +----+----+----+----+----+----+----+----+ LSB
    | e3 | e2 | e1 | e0 | c3 | c2 | c1 | c0 |
    +----+----+----+----+----+----+----+----+

donde los valores e representan los 4 bits del valor de un evento mientras que los valores c representan los 4 bits del valor de un canal (que es un valor numérico entre 0 y 15).

Notas

La escala cromática es una sucesión de doce sonidos separados entre sí por un semitono. Cada uno de estos sonidos de la escala tiene un nombre, y sus nombres son Do, Do♯ (o Re♭), Re, Re♯ (o Mi♭), Mi, Fa, Fa♯ (o Sol♭), Sol, Sol♯ (o La♭), La, La♯ (o Si♭), Si. (También suele utilizarse el cifrado americano, donde se utiliza una A para la nota La, una B para el Sí, C para el Do y así con cada una de ellas hasta la G que es el Sol.)

Las escalas musicales son cíclicas, después del Sí de una escala continúa el Do y se dice que dicho Do está una octava más alta que el anterior.

En los archivos MIDI la nota y la octava se codifican en un número que está entre 0 y 127 donde el 0 corresponde al C (Do) de la octava -1 y se van numerando las notas hasta el 127 que corresponde al G (Sol) de la octava 9.

Trabajo

Enumerativos

Definir un tipo enumerativo formato_t que contenga claves para referirse a las modalidades "pista única", "multipistas sincrónicas" y "mutipistas asincrónicas".

Definir un tipo enumerativo evento_t que contenga claves para referirse a los eventos "nota apagada", "nota encendida", "nota durante", "cambio de control", "cambio de programa", "variar canal", "cambio de pitch" y "metaevento".

Definir un tipo enumerativo nota_t que contenga claves para referirse a todas las notas de una misma octava.

Decodificación

Se pide implementar una función bool decodificar_formato(uint16_t valor, formato_t *formato); que dado un valor devuelva a través de formato el formato que representa. Debe devolver true si el valor era correcto, false en caso contrario.

Se pide implementar una función bool decodificar_evento(uint8_t valor, evento_t *evento, char *canal, int *longitud); que dado un valor devuelva a través de evento el evento que representa, a través de canal el canal que representa y a través de longitud la longitud de dicho evento. En caso de que no se trate de un evento válido no se deben modificar los parámetros recibidos y se debe devolver false, en caso de éxito devolver true.

(Es obligatorio el uso de tablas de búsqueda (diccionarios) para resolver la función decodificar_evento().)

Se pide implementar una función bool decodificar_nota(uint8_t valor, nota_t *nota, signed char *octava); que dado un valor devuelva la nota y la octava que representa dicho valor. Debe devolver true si la nota es correcta y false en caso contrario.

Codificación

Se pide implementar una función const char *codificar_formato(formato_t formato); que dado un formato devuelva una cadena que lo represente.

Se pide implementar una función const char *codificar_evento(evento_t evento); que dado un evento devuelva una cadena que lo represente.

Se pide implementar una función const char *codificar_nota(nota_t nota); que dada una nota devuelva una cadena que la represente.

(Es obligatorio el uso de tablas de búsqueda (diccionarios) para resolver estas funciones.)

Entrega

Deberá entregarse:

  1. El código fuente de las funciones desarrolladas.

  2. Un pequeño main() que pruebe las distintas funciones desarrolladas.

  3. Opcionalmente puede armarse el ejercicio como un módulo con un .c que contenga las funciones y las tablas, un .h que contenga los enumerativos y prototipos, y un tercer archivo fuente que contenga el programa de prueba.

La entrega se realiza a través del sistema de entregas.

El ejercicio es de entrega individual.

Referencias

Formato MIDI: