¿Cómo encontrar algorítmicamente una progresión de acordes para una melodía arbitraria infinita?

Mi pregunta es principalmente sobre esta interpretación de piano:

El número Pi se toca con la mano derecha asignando cada dígito a una nota en la escala de La menor:

0 1 2 3 4 5 6 7 8 9
Sol# ABCDEFG# AB

Mientras tanto, la mano izquierda arpegia ciertos acordes. Un acorde generalmente dura dos notas de la melodía Pi. Aquí están las primeras notas y los acordes que las acompañan:

Dígitos: 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2 6 4 3 3 8 3 2 7 9 5 0 2 8 8 4 1 9 7 1 ...
Melodía: CADAEBBFECEABG#BCBCADFBFDCCACBG#BEG#BAADABG#A...
Acordes: Am Dm C G7 CCEE Am Am ​​Dm Dm C Am EE Am Am ​​Dm E ...

No he transcrito toda la canción (más de 100 dígitos), pero hasta ahora no pude detectar una progresión de acordes repetitiva. Tampoco pude encontrar ningún patrón por el cual los acordes pudieran deducirse de la melodía.

Es muy posible que el autor haya usado los acordes que le sonaron bien en el contexto de la canción.

Sin embargo, me preguntaba si uno podría determinar algorítmicamente los acordes que acompañarían a la melodía, ya que esta canción es potencialmente infinita.

¡Cualquier ayuda con esto sería genial! Y si alguien puede detectar un patrón en la forma en que se usan los acordes, sería increíble.

Esto es principalmente un experimento, pero también me gustaría usarlo como ejemplo en mi próxima charla sobre música por computadora.

Patrones más obvios: solo se usan los acordes Am, Dm, C, G7, E y F. (Por lo general) el acorde se elige para que contenga al menos una nota del par. En realidad, apuesto a que estas reglas por sí solas producirían un resultado muy similar.
Una clase básica de teoría musical debería ayudar con esto. Aprender cómo se construyen los acordes, en función de las escalas, le brinda rápidamente el conocimiento para descubrir qué acordes funcionan bien con una nota en particular y cuándo usar una en particular.
Pi no tiene un patrón repetitivo; los acordes que coinciden con la melodía, por lo tanto, no podrían tener ese patrón.

Respuestas (3)

Para responder a su pregunta principal, sí, puede hacerlo aplicando contrapunto a los tonos de la melodía. Si elige un pequeño libro llamado "El estudio del contrapunto" de Johann Fux, básicamente le proporciona un algoritmo para armonizar cualquier tono de melodía.

El chico del video no está haciendo nada especial; su mano izquierda simplemente está recorriendo una progresión de acordes estándar y bastante básica.

La mano izquierda no puede estar en bicicleta, ese es el punto de usar pi.
@reinierpost lo que quiero decir es que su mano izquierda no está haciendo nada particularmente interesante o inusual.
@Michael Martinez: Posiblemente no, aún así es interesante preguntar qué reglas cumplen estos acordes en el ejemplo y qué tipo de reglas se deben seguir en general. Las reglas de Fux son un ejemplo: ya no son triviales en el sentido de que los acordes que se pueden tocar con una nota dada no solo dependen de la nota que se toca, sino también de una pequeña ventana de acordes precedentes.

El infinito de la serie no es un gran problema: cualquier lenguaje completo de Turing puede manejar infinitos. En los lenguajes procedimentales, esto tiende a requerir construcciones de bucle bastante desagradables. Es mucho más agradable en lenguajes funcionales perezosos, siendo Haskell el más destacado.

En cuanto al algoritmo en sí, puede hacer algo utilizable (aunque algo aburrido; la solución que citó permite cosas un poco más llamativas) con bastante facilidad, basado en la resolución de dominantes.

módulo PiMelody donde

importar lista de datos

datos MelodyNote = Gs | un | B | C' | D' | mi' | F' | Gs' | un' | B'
 derivación (Eq, Show, Enum)

type Melody = [MelodyNote] -- Supone un ritmo simple de corcheas.

piMelody :: Melodía
piMelody = map toEnum piDigits


Acorde de datos = Am | Dm | C | G7 | mi
 derivación (Eq, Show, Enum)

tipo Composición = [(Melodía, Acorde)]
     -- (Infinita) lista de pares: un fragmento de melodía y qué acorde acompañarlo.

chordMNotes :: Chord -> [MelodyNote] -- Sin suspensiones.
acordeMNotas Am = [A , C', E', A']
acordeMNotas Dm = [A , D', F', A']
acordeMNotes E = [Gs, B , D', E', Gs', B', F'] -- La dominante menor también puede ser disminuida-7ma.
acordeMNotas C = [C', E']
acordeMNotas G7 = [B , D', F', B']

resuelve :: Acorde -> [Acorde]
resuelve E = [Am, E] -- Los dominantes deben resolver su tónico, si es que lo hacen.
resuelve G7 = [C, G7, Am, E] -- Para mayor dominante, permite también resolver en paralelos menores.
resuelve _ = [Am .. E] -- El acorde no dominante puede resolver cualquier cosa.


acompañar :: Melodía -> Composición -- Elija los acordes adecuados para una melodía.

melodía de acompañamiento = melodía acc Am
 donde acc :: Acorde -> Melodía -> Composición

       acc lastChord (n1:n2:ml) -- Intenta encontrar un acorde que se ajuste a dos notas de la melodía
        | (Just nextChord) -- y funciona con el acorde anterior (posiblemente dominante).
             all(`elem` chordMNotes ch) [n1,n2]) $ resuelve lastChord
                 = ([n1,n2], siguienteAcorde) : acc siguienteAcorde ml
                                   -- Si dos notas de la melodía no caben en un acorde, use dos.
        | (Solo c1)

(Código como GitHub Gist)

Se puede usar así:

$ghci PiMelody.hs
GHCi, versión 7.6.2: http://www.haskell.org/ghc/   :? para ayuda
Cargando paquete ghc-prim... enlazando... hecho.
Cargando paquete entero-gmp... enlazando... hecho.
Cargando paquete base... enlazando... hecho.
[1 de 1] Compilando PiMelody (PiMelody.hs, interpretado)
Ok, módulos cargados: PiMelody.
*PiMelody> toma 24 $ acompaña a piMelody
[([C',A],Am),([D',A],Dm),([E',B'],E),([B,F'] ,E),([E',C'],Am),([E',A'],Am),([B',Gs'],E),([B'],E),( [C'],Am),([B],G7),([C'],C),([A',D'],Dm),([F',B],G7),([ F',D'],G7),([C',C'],C),([A',C'],Am),([B,Gs'],E),([B', E'],E),([Gs,B],E),([A',A'],Am),([D',A],Dm),([B',Gs'],

Aquí hay una demostración en Ideone.com , produciendo miles de notas hasta que se agote el tiempo.

Ja, bonito! También estoy usando Haskell (con Euterpea EDSL) para codificarlo. ¿Podría explicar brevemente qué son los paralelos menores? No estoy seguro de haber visto este término aplicado a los acordes. Además, su función acc no es la misma que en GitHub.
Ignore el código aquí, todavía está destrozado por la "detección" de la etiqueta html. El de GitHub tiene razón. — ¡Genial, Euterpea! ¿Subirás lo que estás haciendo allí? Creo que podría intentarlo yo mismo de otra manera... — En cuanto a los paralelos menores, podría explicarlos brevemente, pero no creo que sean muy efectivos. Mire el código y/o lea un libro sobre teoría musical básica. Wikipedia también tiene bastante sobre esto .

Creo que la razón por la que esto funciona es que todos los dígitos están asignados a notas dentro de una escala, La menor armónica. Esto en sí mismo es un conjunto de reglas y reduce la complejidad del lenguaje armónico. Del mismo modo, se pueden crear reglas para acompañar la melodía de forma consonante. La forma más fácil de comenzar sería tener una regla de que la nota melódica en cada tiempo fuerte sería un tono de acorde. A partir de ahí, se necesitarían algunas reglas para que la elección de los acordes tuviera sentido en una configuración tonal, función armónica, básicamente agregando teoría. V va a I y tal. A medida que las reglas se vuelven más complejas, será necesario agregar una cierta cantidad de aleatoriedad para que sea auténtico. Seguir estrictamente las reglas a menudo sonaría muy aburrido, también en la caja. La aleatoriedad ocasionalmente permitiría la disonancia en tiempos fuertes o una armonización menos probable.

El ejemplo está en el lado simple en cuanto a la elección melódica. Supongo que el compositor eligió sus propios acordes para seguir la melodía. Si se usó un algoritmo de algún tipo, fue relativamente complejo, lo que dudo dada la simplicidad de la elección melódica, o el compositor usó y modificó un algoritmo muy simple. En última instancia, lo que hace que el ejemplo sea especialmente agradable es el arpegio. Añade el sentimiento humano. El compositor también optó por jugar con el tempo y la dinámica, contribuyendo de nuevo al efecto humanizador. Si quisieras escribir un artículo completo que fuera convincente y basado exclusivamente en algoritmos, tendría que ser increíblemente complejo. Como, eso podría ser el trabajo de una vida. Sin embargo, hay muchos DAW y complementos que tienen "humanización". funciones o la capacidad de agregar aleatoriedad a cualquiera de las dinámicas/longitud de nota, nota, ubicación de nota, etc. pero esto no siempre hará una actuación convincente, a veces suena aleatorio. Entonces, hacer que un ser humano reinterprete un algoritmo básico probablemente daría el mejor resultado.