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:
El código fuente de las funciones desarrolladas.
Un pequeño
main()
que pruebe las distintas funciones desarrolladas.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: