Antecedentes
Los archivos MIDI son bastante diferentes de los archivos de audio WAV o MP3. Los archivos MP3 y WAV contienen bytes que representan una "grabación" del audio, mientras que los archivos MIDI tienen una serie de mensajes MIDI almacenados en eventos MIDI que informan a un sintetizador MIDI qué instrumento virtual tocar o un secuenciador MIDI el tempo de reproducción que se debe usar. Estos mensajes se almacenan en pistas, y una colección de pistas forma una secuencia MIDI, cuyos eventos pueden ser analizados por un secuenciador y transmitir sus mensajes desde el secuenciador al receptor de un sintetizador.
La mayoría de las veces los mensajes MIDI almacenados en eventos MIDI son mensajes Note On que le dicen al sintetizador que toque una nota en particular, o mensajes Note Off que le dicen al sintetizador que deje de tocar la nota. Estos mensajes contienen dos bytes de datos, el primero de los cuales informa al sintetizador de la velocidad de la nota (la mayor velocidad da como resultado una nota más alta), y el segundo le dice al sintetizador la nota que debe tocar (es decir, C central). Los eventos en sí también contienen marcas que tienen el propósito de decirle al secuenciador cuándo enviar los mensajes.
El reto
El desafío es escribir un programa completo o una función que analice una serie de mensajes MIDI Note On y Note Off en una secuencia MIDI de una sola pista y envíe a STDOUT un gráfico que muestre cuándo están activadas las notas particulares, cuándo están desactivadas y velocidad de estas notas. El eje vertical del gráfico representa el valor de la nota y debe etiquetarse como se describe a continuación, y el eje horizontal representa el tiempo en tics MIDI (aunque debe permanecer sin etiquetar para reducir la complejidad y los problemas de espacio).
Su entrada puede ser cuatro matrices o listas separadas, cada una con una serie de valores enteros; una matriz o lista bidimensional que contiene cuatro submatrices / sublistas con una serie de valores enteros; o cualquier otro medio conveniente; esto representa la colección de eventos MIDI con mensajes Note On y Note Off en la pista. Los valores en la primera de estas matrices especifican la nota, la segunda la velocidad, la tercera la nota en el tic del evento y la cuarta la nota en el tic del evento. Por ejemplo, dados cuatro arreglos como estos:
{60, 62, 64, 65, 67}
{20, 40, 60, 80, 100}
{ 0, 4, 8, 12, 16}
{ 2, 6, 10, 14, 18}
Al analizar el primer elemento de cada matriz se obtienen dos eventos: un evento en la marca 0 con un mensaje que tiene un comando Note On, nota 60 (C central) y velocidad de nota de 20; y un evento en la marca 2 con un mensaje que tiene un comando Note Off con la misma nota y velocidad.
Reglas
El gráfico debe presentar los números del 0 al 127 que se muestran en orden decreciente en el lado izquierdo (que representa el valor de la nota), cuando comienza la nota, la duración de cada nota (nota desactivada tick menos nota activada tick) y la velocidad de la nota. Los símbolos que representan las notas dependen de su velocidad:
- 0-15:
O
- 16-31:
=
- 32-47:
#
- 48-63:
-
- 64-79:
@
- 80-95:
+
- 96-111:
0
- 112-127:
*
Puede asumir lo siguiente:
- Los valores para nota y velocidad estarán dentro del rango [0, 127].
- Las longitudes de cada una de las cuatro matrices siempre serán iguales entre sí.
Aquí están algunos ejemplos:
{60, 62, 64, 65, 67}
{20, 40, 60, 80, 100}
{ 0, 4, 8, 12, 16}
{ 2, 6, 10, 14, 18}
127|
126|
125|
...
67 | 00
66 |
65 | ++
64 | --
63 |
62 | ##
61 |
60 |==
59 |
...
2 |
1 |
0 |
{60, 48, 62, 47, 64, 45, 65, 43, 67, 41, 65, 43, 64, 45, 62, 47, 60, 48}
{63, 31, 75, 90, 12, 23, 122, 104, 33, 19, 57, 42, 5, 82, 109, 86, 95, 71}
{0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16}
{2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18}
127|
126|
...
68 |
67 | ##
66 |
65 | ** --
64 | OO OO
63 |
62 | @@ 00
61 |
60 |-- ++
59 |
...
49 |
48 |== @@
47 | ++ ++
46 |
45 | == ++
44 |
43 | 00 ##
42 |
41 | ==
40 |
...
1 |
0 |
Aquí hay un ejemplo que muestra las primeras notas de Ode to Joy:
{48, 55, 64, 64, 65, 67, 55, 67, 65, 64, 62, 52, 55, 60, 60, 62, 64, 55, 64, 62, 62}
{45, 45, 63, 63, 63, 63, 89, 66, 66, 66, 66, 30, 30, 103, 103, 103, 103, 127, 55, 55, 55}
{ 0, 0, 0, 4, 8, 12, 16, 16, 20, 24, 28, 32, 32, 32, 36, 40, 44, 48, 48, 54, 56}
{16, 16, 2, 6, 10, 14, 32, 18, 22, 26, 30, 48, 48, 34, 38, 42, 46, 64, 50, 55, 64}
127|
...
67 | -- @@
66 |
65 | -- @@
64 |-- -- @@ 00 --
63 |
62 | @@ 00 - --------
61 |
60 | 00 00
59 |
58 |
57 |
56 |
55 |################++++++++++++++++================****************
54 |
53 |
52 | ================
51 |
50 |
49 |
48 |################
...
0 |
Puedes reducir tu puntaje en un 25% si su envío toma una secuencia MIDI real como entrada, analiza los mensajes Note On y Note Off de cualquier pista de su elección, siempre que contenga al menos cuatro eventos con mensajes Note On y Note Off, y salidas una tabla como se describe arriba.
Este es el código golf, por lo que gana el código más corto. ¡Buena suerte!
Ruby, 106 bytes
Esto fue divertido. No estoy seguro de por qué nadie lo intentó.
Esta función toma la entrada como cuatro argumentos de matriz y devuelve una matriz de cadenas, una para cada línea del gráfico.
Nota: Esto supone arbitrariamente que no habrá más de 10,000 ticks. Si lo ejecuta en su terminal, le sugiero que lo conecte para
less
que pueda desplazarse horizontalmente. Puede cambiar1e4
si desea más ticks, hasta el final9e9
, pero eso tomará un terabyte o dos de RAM.Véalo en repl.it: https://repl.it/Cx4I/1
fuente
Pitón 2,
163160156145 bytesEsta no es la forma más elegante de hacerlo, pero fue una de las más simples. Si pudiera descubrir cómo reemplazar partes de cadenas sin convertirlas en listas, reemplazarlas y volverlas a convertir en cadenas, sería muy útil aquí. Sugerencias de golf bienvenidas.
Editar: 18 bytes gracias a Leaky Nun. Pruébalo en Ideone !
fuente
str.sub(/(?<=.{20}).{3}/,"foo")
es equivalente astr[20,3] = "foo"
. Por supuesto, eso significa construir la expresión regular mediante interpolación / concatenación de cadenas con las variables de índice / longitud, lo cual es barato en bytes Ruby, pero tal vez no en Python.Japt , 65 bytes
Pruébalo en línea!
Toma la entrada como una lista de notas en el formato
[pitch, start_tick, end_tick, velocity]
. Si es obligatorio tomar la entrada como listas separadas (es decir, una lista que contiene todos los tonos, una que contiene todas las velocidades, etc.), eso se puede lograr a costa de 1 byte .Explicación:
fuente