Ir al contenido
learn

Lección 10: Sustituciones y mezcla modal

La lección 9 midió cuánto dista un acorde del siguiente. Esta lección pregunta qué acorde puede ocupar el lugar de otro, y qué acordes puede tomar prestados una tonalidad de sus modos homónimos. Guitar Alchemist (GA) responde en cinco lugares: una habilidad (skill) del chatbot, una herramienta de su servidor MCP, una segunda herramienta con el mismo nombre en su API web, un servicio de esa API y un archivo YAML. El programa del curso comprueba cada uno, y ejecuta el propio código de GA siempre que puede.

Todos los enlaces a GA apuntan al commit a826864. Las salidas proceden del comando de abajo; el punto de entrada es l12.

Ventana de terminal
dotnet run --project code/music-theory-ga/GaTheory -c Release -- l12

Una sustitución cambia un acorde por otro que hace el mismo trabajo. Wikipedia cita a Alfred Blatter: “A chord substitution occurs when a chord is replaced by another that is made to function like the original. Usually substituted chords possess two pitches in common with the triad that they are replacing.” (Chord substitution, según Blatter 2007, p. 186). La lección 9 mostró qué tríadas comparten dos notas: aquellas cuyas fundamentales están a una tercera. En C mayor, A menor y E menor pueden sustituir a C, y D menor y A menor a F. Wikipedia llama al primer caso la sustitución por el relativo mayor o menor, que “shares two common tones” (mismo artículo).

El curso toma las tríadas de la tonalidad sobre los demás grados y las ordena por el número de notas que comparten con el acorde (Lesson12.CourseSubstitutes). Un acorde de séptima tiene cuatro notas, así que una tríada puede compartir tres con él: B disminuido es G7 sin su fundamental, y E menor es Cmaj7 sin la suya.

== Diatonic substitutes in C major, by the notes they share (GA: ga_chord_substitutions, the closure rewritten)
chord course GA check
Am C 2, F 2, Dm 1, Em 1 C 2, F 2, Dm 1, Em 1 ok
Em C 2, G 2, Am 1, Bdim 1 C 2, G 2, Am 1, Bdim 1 ok
F Dm 2, Am 2, C 1, Bdim 1 Dm 2, Am 2, C 1, Bdim 1 ok
C Em 2, Am 2, F 1, G 1 Em 2, Am 2, F 1, G 1 ok
G7 Bdim 3, Dm 2, Em 2, C 1, F 1 Bdim 3, Dm 2, Em 2, C 1, F 1 ok
Cmaj7 Em 3, G 2, Am 2, F 1, Bdim 1 Em 3, G 2, Am 2, F 1, Bdim 1 ok
Bm7b5 Dm 3, F 2, G 2, Em 1, Am 1 Dm 2, G 2, Bdim 2, Em 1, F 1, Am 1 DIFF
the course's Bm7b5: B D F A; the closure's: B D F# A

Los empates conservan el orden de la escala. La última fila es un acorde de séptima semidisminuido, B D F A, y D menor, D F A, comparte tres de sus notas.

En GA: ga_chord_substitutions, la herramienta del servidor MCP

Sección titulada «En GA: ga_chord_substitutions, la herramienta del servidor MCP»

El servidor MCP de GA responde con ga_chord_substitutions (GaDslTool.cs#L208-L222), que ejecuta una closure de F#, domain.chordSubstitutions (DomainClosures.fs#L535-L621). Hace lo mismo: las tríadas de la tonalidad que comparten al menos una nota con el acorde, ordenadas por cuántas con la ordenación estable de F#, List.sortByDescending (#L602), y el propio acorde descartado cuando coinciden su fundamental y su calidad (#L587). La closure es de F# y el programa del curso de C#, así que el programa la reescribe, con el parser al que llama (Lesson12.ParseChord, Lesson12.GaSubstitutions). Para esta herramienta, el curso comprueba su lectura del código de GA, no el servidor en marcha.

Los dos coinciden en seis acordes. El séptimo es otra vez el defecto de la lección 9: el parser guarda el ♭5 de Bm7♭5 como una alteración (ChordParser.fs#L69-L84), y la closure construye el acorde solo a partir de su calidad y sus extensiones (DomainClosures.fs#L85-L98, #L349-L355). B D F♯ A solo comparte dos notas con D menor, y B disminuido se cuela en la lista con dos. En la rama main de GA, la closure toma sus notas de chordTones, que introdujo GA #681 (#L446-L450 y #L663 en el commit 5c3a52a); leído, no ejecutado.

Esta es la respuesta de la propia closure para A menor, reescrita línea a línea, junto al ejemplo de la descripción de la herramienta (GaDslTool.cs#L212):

== The closure's answer for Am in C major, and the example in the tool's description (GaDslTool.cs line 212)
Substitutions for Am in key of C major:
★★ C — 2 shared: C(m3/P1) E(P5/M3)
★★ F — 2 shared: A(P1/M3) C(m3/P5)
★ Dm — 1 shared: A(P1/P5)
★ Em — 1 shared: E(P5/P1)
description: Am in key of C major → C (★★★, relative major), Em (★★, shared E/B), F (★, shared A)

La descripción se equivoca en los tres acordes. C comparte dos notas con A menor, no tres. E menor solo comparte E, porque A menor no tiene B. F comparte A y C, y queda empatado con C.

La tonalidad es opcional. Sin ella, la closure toma la letra de la fundamental del acorde, descarta la alteración y supone una tonalidad mayor (#L558-L559); el parámetro de la herramienta solo dice “Defaults to chord root if omitted” (GaDslTool.cs#L215).

== Without a key, the closure uses the chord's root letter as a major key (line 558)
chord GA's key GA's ranking
Am A major A 2, C#m 1, D 1, E 1, F#m 1
Bb7 B major C#m 1, D#m 1, E 1, F# 1, G#m 1, A#dim 1; tritone E7
F#m F major F 1, Am 1, Dm 1
Eb E major G#m 1, B 1, D#dim 1

El primer sustituto de A menor es A mayor: la tonalidad de A mayor lo contiene, y la closure solo descarta un acorde cuando coinciden la fundamental y la calidad. F♯ menor se compara con los acordes de F mayor, ninguno de los cuales contiene F♯ ni C♯; E♭ con los de E mayor.

Open Music Theory: “Tritone substitutions replace a dominant chord with another dominant chord a tritone away. The name refers both to the interval between the original and substituted chords and to the fact that the two chords share the same tritone.” (Open Music Theory, “Substitutions”). G7 es G B D F; D♭7 es D♭ F A♭ C♭, y C♭ suena como B. El tritono B–F está en los dos acordes con los papeles intercambiados: B es la tercera de G7 y la séptima de D♭7. Los dos resuelven en C, y el sustituto lo hace por semitono en el bajo: “the most reliable way to recognize a tritone substitution in a song is by its chromatic resolution downward by a minor second” (mismo capítulo). El módulo Streeling MUS-005 · Armonía de jazz para guitarra la trabaja en su sección 5, sobre las técnicas de sustitución.

El curso llama dominante a un acorde que tiene una tercera mayor y una séptima menor sobre su fundamental, con o sin extensiones, y nombra el sustituto una quinta disminuida por encima de la fundamental: D♭ para G.

La closure añade una línea de tritono con la misma prueba, una tercera mayor y una séptima menor entre sus intervalos (#L603-L609), y escribe la fundamental con bemoles:

== The tritone substitute: the course's dominant chords, and the closure's test for M3 and m7 (lines 603-609)
chord course GA check
G7 Db7 Db7 ok
D7 Ab7 Ab7 ok
E7 Bb7 Bb7 ok
C7 Gb7 Gb7 ok
G9 Db7 (none) DIFF
G13 Db7 (none) DIFF
Gm7 (none) (none) ok
Cmaj7 (none) (none) ok

G9 y G13 no tienen sustituto. En el commit a826864, «9» y «13» solo añaden su propio grado (#L94-L98), así que la closure nunca ve la séptima menor que contienen los dos acordes. chordTones, en main, la sobrentiende (lección 9).

Una dominante secundaria es la dominante de un acorde distinto de la tónica. Open Music Theory las llama “secondary dominant chords (V(7))” y da la más común: “ii becomes II♯, which is V/V” (Open Music Theory, “Tonicization”). En C mayor, es D7 yendo a G. El destino debe ser una tríada mayor o menor: “Diminished and augmented triads can’t be tonicized, since there are no diminished or augmented keys” (mismo capítulo). MUS-003 · Cómo funciona la armonía las trata en su sección 5; una fila de su tabla en G mayor está mal (véase el diario).

La dominante backdoor llega a la tónica desde un tono por debajo: ♭VII⁷ → I, B♭7 → C en C mayor. Wikipedia cita a Jerry Coker: “The I chord, in a given progression, is often preceded by IV–7 to ♭VII7, instead of the usual V7 chord” (Chord substitution, según Coker 1997, p. 82). MUS-005 también la presenta, como bVII7 → I.

El curso lee un par de acordes con los cinco nombres que usa la habilidad de GA (Lesson12.CourseRelations): dos séptimas de dominante a un tritono; una tríada mayor o una séptima de dominante una quinta por encima de un acorde mayor o menor; una séptima de dominante un tono por debajo de su resolución; la misma forma prima, la clase de conjuntos de la lección 4; y vectores interválicos a 2 como mucho.

En GA: la habilidad ChordSubstitutionSkill del chatbot

Sección titulada «En GA: la habilidad ChordSubstitutionSkill del chatbot»

El chatbot responde a estas preguntas con ChordSubstitutionSkill, sin modelo de lenguaje. Como la habilidad de la lección 9, se elige por el significado (ProductionOrchestrator.cs#L200-L206); luego lee los cifrados de acordes con su propia expresión regular (ChordSubstitutionSkill.cs#L69-L71). Dos cifrados dan una comparación, uno solo una lista (#L144-L174). El programa copia el patrón, las tablas y la selección, sin el logger ni el texto de la respuesta, y llama a GrothendieckService y GrothendieckDelta de GA, compilados tal cual (Lesson12.cs#L281-L416). Los doce ejemplos de consultas de la habilidad (#L35-L55) pasan primero por el patrón:

== GA's chatbot skill: what its own twelve example prompts parse to (ChordSubstitutionSkill.cs lines 146-160)
Tritone substitution for G7 lists substitutes for G7
What can I substitute for Cmaj7 in a ii-V-I? lists substitutes for Cmaj7
Reharmonize Dm7 in a jazz context lists substitutes for Dm7
Alternative chord for F major in C compares F with C
What's the secondary dominant of Am? lists substitutes for Am
Show me a backdoor dominant for C major lists substitutes for C
Alternative chord for Cmaj7 lists substitutes for Cmaj7
What can replace Dm7? lists substitutes for Dm7
Swap chord for G7 lists substitutes for G7
Modal interchange substitutes for C major lists substitutes for C
Borrow a chord from parallel minor no chord: "Could not identify a chord symbol in your message."
Modal interchange options in F major lists substitutes for F

El patrón distingue mayúsculas y quiere una mayúscula de A a G sin letra detrás, así que «Alternative» y «Borrow» no son acordes. «Alternative chord for F major in C» encuentra dos acordes, F y C, y los compara en lugar de dar alternativas a F. «Borrow a chord from parallel minor» no tiene ningún cifrado de acorde. Las comparaciones:

== Two chords: the course's reading and the skill's labels (ClassifySubstitution, lines 246-298)
G7 Db7 DIFF
course: Tritone Substitution, Set-Class Equivalent, ICV Neighbor (L1 = 0)
GA: Tritone Substitution, Set-Class Equivalent, ICV Neighbor (L1 = 1)
G7 C ok
course and GA: Secondary Dominant
D7 G ok
course and GA: Secondary Dominant
Dm G DIFF
course: Set-Class Equivalent, ICV Neighbor (L1 = 0)
GA: Secondary Dominant, Set-Class Equivalent, ICV Neighbor (L1 = 1)
F# Bdim DIFF
course: Harmonic Distance
GA: Secondary Dominant
C C DIFF
course: Set-Class Equivalent, ICV Neighbor (L1 = 0)
GA: Set-Class Equivalent, ICV Neighbor (L1 = 1)
C Am DIFF
course: Set-Class Equivalent, ICV Neighbor (L1 = 0)
GA: Set-Class Equivalent, ICV Neighbor (L1 = 1)
Bb7 C ok
course and GA: Backdoor Dominant

Dos pruebas contradicen los manuales. Secondary Dominant solo mira las fundamentales (#L262): D menor la obtiene antes de G, y F♯ antes de B disminuido, aunque un acorde menor no es una dominante y una tríada disminuida no se puede tonicizar. ICV Neighbor da distancia 1 para dos acordes con el mismo vector interválico, donde la distancia es 0: GrothendieckDelta.FromIcVs convierte una diferencia nula en 1, “to preserve musical differentiation expected by callers/tests” (GrothendieckDelta.cs#L125-L131). Así, C está a un paso de sí mismo.

Para un solo acorde, la habilidad da cinco sustitutos “ranked by ICV distance” (ChordSubstitutionSkill.cs#L182). FindNearby de GA (GrothendieckService.cs#L45-L90) recorre los 4096 conjuntos de clases de altura y se queda con aquellos cuyo vector interválico (lección 4) difiere del del acorde en 3 como mucho, sumado sobre las seis clases. Cada uno recibe un coste de 0,6 veces esa distancia (#L39-L42). La habilidad se queda con los conjuntos del tamaño del acorde y toma los cinco primeros por coste (ChordSubstitutionSkill.cs#L164-L174).

Ordenar por una clave que empata es una cuestión de C#. Enumerable.OrderBy es estable: “if the keys of two elements are equal, the order of the elements is preserved”. Aquí casi todo empata. Las transposiciones e inversiones de un acorde tienen el mismo vector, así que las 24 tríadas mayores y menores comparten uno, y las 12 séptimas de dominante y las 12 semidisminuidas otro. Con el cero convertido en uno, todos salen a distancia 1 y coste 0,60, y la ordenación estable los deja en el orden en que FindNearby los encontró: el orden de los números de 12 bits.

El programa compila FindNearby tal cual, cuenta por sí mismo los conjuntos con el mismo vector e imprime las cinco líneas de la habilidad con el número de 12 bits de cada conjunto y las notas que comparte con el acorde (Lesson12.SkillCandidates):

== The skill's list for one chord: GA's FindNearby, then the first five of the same size, by cost
course: the other chords of the same size with the same ICV; GA: the chords at the lowest cost it lists
chord course GA check
G7 23 23 ok
- **Dm7b5** — harmonic cost 0.60 (Δ L1=1) id 293, 2 notes in common with G7
- **Ab7** — harmonic cost 0.60 (Δ L1=1) id 329, 0 notes in common with G7
- **F7** — harmonic cost 0.60 (Δ L1=1) id 553, 1 note in common with G7
- **D7** — harmonic cost 0.60 (Δ L1=1) id 581, 1 note in common with G7
- **Ebm7b5** — harmonic cost 0.60 (Δ L1=1) id 586, 0 notes in common with G7
textbook Db7: number 19 of the 155 it lists, cost 0.60
Am 23 23 ok
- **Cm** — harmonic cost 0.60 (Δ L1=1) id 137, 1 note in common with Am
- **C** — harmonic cost 0.60 (Δ L1=1) id 145, 2 notes in common with Am
- **Ab** — harmonic cost 0.60 (Δ L1=1) id 265, 1 note in common with Am
- **Dbm** — harmonic cost 0.60 (Δ L1=1) id 274, 1 note in common with Am
- **Fm** — harmonic cost 0.60 (Δ L1=1) id 289, 1 note in common with Am
textbook C: number 2 of the 95 it lists, cost 0.60
textbook F: number 8 of the 95 it lists, cost 0.60
C 23 23 ok
- **Cm** — harmonic cost 0.60 (Δ L1=1) id 137, 2 notes in common with C
- **Ab** — harmonic cost 0.60 (Δ L1=1) id 265, 1 note in common with C
- **Dbm** — harmonic cost 0.60 (Δ L1=1) id 274, 1 note in common with C
- **Fm** — harmonic cost 0.60 (Δ L1=1) id 289, 1 note in common with C
- **Db** — harmonic cost 0.60 (Δ L1=1) id 290, 0 notes in common with C
textbook Am: number 6 of the 95 it lists, cost 0.60
textbook Em: number 21 of the 95 it lists, cost 0.60
Cmaj7 11 11 ok
- **Dbmaj7** — harmonic cost 0.60 (Δ L1=1) id 291, 1 note in common with Cmaj7
- **Abmaj7** — harmonic cost 0.60 (Δ L1=1) id 393, 2 notes in common with Cmaj7
- **Fmaj7** — harmonic cost 0.60 (Δ L1=1) id 561, 2 notes in common with Cmaj7
- **Dmaj7** — harmonic cost 0.60 (Δ L1=1) id 582, 0 notes in common with Cmaj7
- **Amaj7** — harmonic cost 0.60 (Δ L1=1) id 786, 1 note in common with Cmaj7
textbook Em7: not listed (Δ L1=4, beyond 3)
textbook Am7: not listed (Δ L1=4, beyond 3)
Dm7 11 11 ok
- **Fm7** — harmonic cost 0.60 (Δ L1=1) id 297, 2 notes in common with Dm7
- **F#m7** — harmonic cost 0.60 (Δ L1=1) id 594, 1 note in common with Dm7
- **Am7** — harmonic cost 0.60 (Δ L1=1) id 657, 2 notes in common with Dm7
- **Ebm7** — harmonic cost 0.60 (Δ L1=1) id 1098, 0 notes in common with Dm7
- **Cm7** — harmonic cost 0.60 (Δ L1=1) id 1161, 1 note in common with Dm7
textbook Fmaj7: not listed (Δ L1=4, beyond 3)

La lista son los cinco números más pequeños de la clase de conjuntos del acorde, sin contar el propio acorde. El sustituto de los manuales queda más abajo. D♭7, el sustituto por tritono que promete la propia descripción de la habilidad (“tritone subs (G7 → Db7)”, #L28-L33), llega en el puesto 19, así que el primer ejemplo de consulta de la habilidad, «Tritone substitution for G7», nunca lo muestra. Em7 y Am7, que comparten tres notas con Cmaj7, no aparecen: su vector está a 4. Y los mismos pocos acordes vuelven para casi todas las fundamentales:

== Over the twelve roots of each chord type, the skill's lists of five
type different chords first suggestion, and for how many roots
major 6 Cm 12
m 6 C 1, Cm 11
dim 6 Dbdim 1, Cdim 11
aug 4 Dbaug 3, Caug 9
7 6 Dm7b5 12
maj7 6 Dbmaj7 11, Abmaj7 1
m7 6 Fm7 11, Dm7 1
m7b5 6 Dm7b5 11, Ab7 1
dim7 3 Dbdim7 4, Cdim7 8

Dm7♭5 es la primera sugerencia para las doce séptimas de dominante. Una ordenación cuya clave empata tanto necesita una segunda clave con sentido: las notas comunes, que el programa imprime, o el movimiento de la fundamental.

GaApi, la API web de GA, sirve la misma lógica de la habilidad como dos herramientas MCP propias, ga_chord_substitutions y ga_chord_compare (ChordSubstitutionMcpTools.cs#L44, #L97), en su punto de acceso /mcp (registradas en Program.cs#L354-L357, expuestas en #L514). Dos herramientas llamadas ga_chord_substitutions responden, pues, de forma distinta: la del servidor MCP ordena los acordes de una tonalidad por notas comunes, la de GaApi ordena todos los conjuntos por distancia de vector.

Open Music Theory: “Modal mixture (or borrowing) is the harmonic technique of mixing the notes from the parallel major and natural-minor modes (e.g., C major and C minor).” La mezcla “is more common in major keys (borrowing from the parallel minor)”, y “changes the quality of a chord, but not its function” (Open Music Theory, “Modal Mixture”). Las fundamentales rebajadas llevan un bemol: “Chords with lowered roots use a flat sign in front of the Roman numeral (e.g., ♭VI).” En C mayor, los más comunes son iv (F menor), ii° y iiø⁷ (D F A♭, con C), ♭VI (A♭), ♭III (E♭) y ♭VII (B♭); cambiar I por i también es común, V por v menos (mismo capítulo).

Tomar prestado de los otros modos homónimos, dórico, frigio, lidio, mixolidio y locrio, amplía la idea; los músicos de jazz y de rock lo llaman intercambio modal (modal interchange). El curso escribe cada modo sobre C, una letra por grado, y enumera las tríadas que C mayor no tiene, con números romanos leídos respecto a la escala mayor (Lesson12.CourseBorrowed, Lesson12.Numeral):

== The course's borrowed chords, mode by mode: every triad of the parallel mode that C major lacks
mode chords
Dorian i Cm, bIII Eb, v Gm, vi° Adim, bVII Bb
Phrygian i Cm, bII Db, bIII Eb, iv Fm, v° Gdim, bVI Ab, bvii Bbm
Lydian II D, #iv° F#dim, vii Bm
Mixolydian iii° Edim, v Gm, bVII Bb
Aeolian i Cm, ii° Ddim, bIII Eb, iv Fm, v Gm, bVI Ab, bVII Bb
Locrian i° Cdim, bII Db, biii Ebm, iv Fm, bV Gb, bVI Ab, bvii Bbm
count course GA check
distinct chords 18 18 ok

La fila Aeolian, el modo eólico, es la mezcla de Open Music Theory. Entre los seis modos hay 18 acordes distintos; la columna GA de la última fila procede de la sección siguiente.

La herramienta MCP get_borrowed_chords de GA pasa la tonalidad a GaApi (ContextualChordsTool.cs#L72-L83, ContextualChordsController.cs#L38-L41), cuyo ContextualChordService.GetBorrowedChordsAsync (ContextualChordService.cs#L75-L119) construye las tríadas de cada modo homónimo y se queda con las que le faltan a la tonalidad de partida. El programa compila el servicio tal cual, con ChordTemplateFactory de GA, y le pide C mayor. GA escribe los sostenidos como ♯; la comparación los lee como #, así que solo cuenta la grafía.

== Borrowed chords for C major: GA's get_borrowed_chords (ContextualChordService, compiled as it is), chord by chord
GA's mode course GA check
Dorian i Cm i Cm ok
notes: course C Eb G, GA C D♯ G
Dorian bIII Eb III D# DIFF
notes: course Eb G Bb, GA D♯ G A♯
Dorian v Gm v Gm ok
notes: course G Bb D, GA G A♯ D
Dorian vi° Adim vi° Adim ok
notes: course A C Eb, GA A C D♯
Dorian bVII Bb VII A# DIFF
notes: course Bb D F, GA A♯ D F
Phrygian bII Db II C# DIFF
notes: course Db F Ab, GA C♯ F G♯
Phrygian iv Fm iv Fm ok
notes: course F Ab C, GA F G♯ C
Phrygian v° Gdim v° Gdim ok
notes: course G Bb Db, GA G A♯ C♯
Phrygian bVI Ab VI G# DIFF
notes: course Ab C Eb, GA G♯ C D♯
Phrygian bvii Bbm vii A#m DIFF
notes: course Bb Db F, GA A♯ C♯ F
Lydian II D II D ok
Lydian #iv° F#dim iv° F#dim DIFF
Lydian vii Bm vii Bm ok
Mixolydian iii° Edim iii° Edim ok
notes: course E G Bb, GA E G A♯
Aeolian ii° Ddim ii° Ddim ok
notes: course D F Ab, GA D F G♯
Locrian i° Cdim i° Cdim ok
notes: course C Eb Gb, GA C D♯ F♯
Locrian biii Ebm iii D#m DIFF
notes: course Eb Gb Bb, GA D♯ F♯ A♯
Locrian bV Gb V F# DIFF
notes: course Gb Bb Db, GA F♯ A♯ C♯

Encuentra los mismos 18 acordes, con tres diferencias. Cada acorde se atribuye al primer modo del bucle que lo contiene (#L93-L109): B♭ y G menor salen como dóricos, y el menor homónimo de Open Music Theory, el eólico, se queda solo con D disminuido. Cada fundamental de tecla negra se escribe con sostenido (#L137, a través de Note.cs#L75): D♯ por E♭, A♯ por B♭, G♯ por A♭, e incluso C menor sale como C D♯ G. Y los números romanos no llevan ninguna alteración (#L157-L170): el acorde de A♭ es «VI», y D♭ y D son los dos «II».

GA también describe el intercambio modal en un archivo de configuración, ModalInterchange.yaml, 1549 líneas de números romanos, acordes escritos en C mayor o en A menor, canciones y consejos. El programa escribe cada acorde a partir de su número romano en su modo de origen (Lesson12.ReadMixtureChords):

== GA's ModalInterchange.yaml: each chord spelled from its numeral in its source mode
entry, numeral course GA check
Parallel Minor bVI Ab major Ab major ok
Parallel Minor bVII Bb major Bb major ok
Parallel Minor iv F minor F minor ok
Parallel Minor ii° D diminished D diminished ok
Parallel Major VI F# minor F major DIFF
F major is already a chord of A natural minor: nothing is borrowed
Parallel Major VII G# diminished G major DIFF
G major is already a chord of A natural minor: nothing is borrowed
Parallel Major III C# minor C major DIFF
C major is already a chord of A natural minor: nothing is borrowed
Dorian IV D major D major ok
Dorian ii B minor B minor ok
Phrygian bII Bb major Bb major ok
Phrygian bii° Bb major Bb diminished DIFF
Mixolydian bVII Bb major Bb major ok
Mixolydian v G minor G minor ok

Nueve de los trece son correctos. Los tres acordes «prestados del mayor homónimo» en A menor son acordes propios de A menor (#L271-L362); tomarlos de A mayor daría F♯ menor, G♯ disminuido y C♯ menor. «bii°, Bb diminished» no está en A frigio, cuyo segundo grado es B♭ mayor, la entrada justo encima (#L616-L619). Los ejemplos de las menores armónica y melódica solo dan números romanos (#L826-L875):

== Its chromatic numerals, read in C: the chord on that degree of the mode
mode, numeral course GA check
Harmonic Minor V7 V7 V7 ok
G B D F
Harmonic Minor vii°7 vii°7 vii°7 ok
B D F Ab
Harmonic Minor bVI+ bVI bVI+ DIFF
Ab C Eb
Melodic Minor iv+ IV iv+ DIFF
F A C
Melodic Minor V7 V7 V7 ok
G B D F
Melodic Minor vii°7 viiø7 vii°7 DIFF
B D F A

El ♭VI de la menor armónica es mayor, y su tríada aumentada es ♭III+. El cuarto grado de la menor melódica lleva un acorde mayor. Su acorde de séptima sobre vii es semidisminuido, no disminuido.

Esperaba que nada en GA leyera este archivo: el vigilante de configuración lo enumera, y un cambio en él acaba en “Unknown configuration file” (ConfigurationWatcherService.cs#L55, #L157-L158). Me equivocaba. YamlKnowledgeLoader (YamlKnowledgeLoader.fs#L128-L140) lee todos los archivos YAML del directorio de configuración, salvo cinco que tienen su propio cargador, y aplana cada entrada en texto. YamlKnowledgeSyncService guardaría esos textos con embeddings “for semantic retrieval by the chatbot agents”, dice su comentario (YamlKnowledgeSyncService.cs#L8-L25), pero nada lo ejecuta en a826864: solo AddSyncServices lo registraría (ServiceCollectionExtensions.cs#L32-L54), nada llama a ese método, y GaCLI tiene la llamada comentada (Program.cs#L320-L321). El programa llama al cargador, que ya compila con GA.Business.Config:

== Who reads the file: GA's YamlKnowledgeLoader (GA.Business.Config, compiled), which flattens every content YAML
8 entries from ModalInterchange.yaml:
Borrowed Chords from Parallel Minor
Borrowed Chords from Parallel Major
Dorian Interchange
Phrygian Interchange
Mixolydian Interchange
Chromatic Modal Interchange
Parallel Modal Regions
Modal Pivot Chords
"InKeyOfAm: F major" in their text: yes
"InKeyOfAm: Bb diminished" in their text: yes
"bVI+" in their text: yes
"iv+" in their text: yes

Los acordes y números romanos incorrectos llegan a ese texto. Pero nada en a826864 guarda ese texto, y nada lee la colección yaml_knowledge que llenaría el servicio de sincronización: fuera de ese servicio, la colección solo aparece como propiedad de MongoDbService (MongoDbService.cs#L56-L57). De paso, el cargador se salta SpecializedTunings.yaml, que no se puede leer, con un mensaje en la salida de error y nada más.

En la rama main de GA, en el commit 5c3a52a, las notas de la closure han cambiado (#681); la tonalidad por defecto, el ejemplo de la descripción, las dos pruebas de la habilidad, la distancia forzada a 1, la grafía del servicio y su atribución al primer modo siguen como arriba. Leído, no ejecutado.

  1. Ordena los sustitutos diatónicos de D menor en F mayor por las notas que comparten.
  2. ¿Cuál es el sustituto por tritono de A7, y qué tritono comparten los dos acordes?
  3. ¿Qué acorde da primero la habilidad del chatbot para A7, y por qué?
  4. ¿Qué acordes toma prestados G mayor de G menor? ¿Cómo los escribe get_borrowed_chords("G major")?
Soluciones
  1. F 2, B♭ 2, G menor 1, A menor 1. F y B♭ tienen la fundamental a una tercera de D; C y E disminuido no comparten nada con D menor.
  2. E♭7. A7 es A C♯ E G y E♭7 es E♭ G B♭ D♭: G y C♯, que suena como D♭, intercambian sus papeles.
  3. Dm7♭5, el número de 12 bits 293, el menor de los 23 conjuntos con el vector de A7. El E♭7 de los manuales queda más abajo.
  4. G menor, A disminuido, B♭, C menor, D menor, E♭ y F. GA encuentra los mismos siete entre sus acordes prestados para G mayor, con A♯ por B♭ y D♯ por E♭.
== Exercise solutions
question course GA check
1. Dm in F major F 2, Bb 2, Gm 1, Am 1 F 2, Bb 2, Gm 1, Am 1 ok
2. A7, tritone Eb7 Eb7 ok
A7: A C# E G; Eb7: Eb G Bb Db
3. chatbot, A7 Eb7 Dm7b5 DIFF
4. G minor in G Gm Adim Bb Cm Dm Eb F Gm Adim A# Cm Dm D# F DIFF
  • Un sustituto hace el trabajo del acorde original; un sustituto diatónico comparte dos notas con una tríada, con su fundamental a una tercera. La closure MCP de GA ordena los acordes de una tonalidad del mismo modo, pero sin tonalidad usa la tonalidad mayor de la letra de la fundamental, y en el commit a826864 perdía las alteraciones.
  • Dos séptimas de dominante a un tritono comparten su tritono, y el sustituto resuelve un semitono más abajo. La prueba de GA, una tercera mayor y una séptima menor, no veía las novenas ni las trecenas, que no llevaban su séptima en el commit a826864.
  • Una dominante secundaria es una tríada mayor o una séptima de dominante una quinta por encima de un acorde mayor o menor. La habilidad de GA solo comprueba las fundamentales, y su distancia entre vectores interválicos convierte 0 en 1.
  • Ordenar por distancia de vector empata todos los acordes de un tipo, y el OrderBy estable de LINQ conserva el orden de enumeración: los cinco sustitutos del chatbot son los números de 12 bits más pequeños de la clase de conjuntos del acorde, con Dm7♭5 en cabeza para cada séptima de dominante. Una ordenación necesita un desempate con sentido.
  • La mezcla modal toma prestado del menor homónimo y, por extensión, de cada modo homónimo. El servicio de GA encuentra los mismos 18 acordes que el curso para C mayor, pero los escribe con sostenidos, quita el ♭ de los números romanos y atribuye cada acorde al primer modo de su bucle. ModalInterchange.yaml tiene mal 4 de 13 acordes y 3 de 6 números romanos, y su texto llega al cargador de conocimiento YAML de GA, aunque nada en a826864 ejecuta el servicio que lo guardaría con embeddings.
  • Mark Gotham et al., Open Music Theory, versión 2, 2023, CC BY-SA 4.0: capítulos Modal Mixture, Substitutions y Tonicization.
  • Wikipedia: Chord substitution, que cita a Alfred Blatter, Revisiting Music Theory, 2007, y a Jerry Coker, Elements of the Jazz Language for the Developing Improvisor, 1997.
  • Microsoft Learn: Enumerable.OrderBy.
  • GuitarAlchemist/ga en el commit a826864: GaMcpServer/Tools/GaDslTool.cs, Common/GA.Business.DSL/Closures/BuiltinClosures/DomainClosures.fs, Common/GA.Business.ML/Agents/Skills/ChordSubstitutionSkill.cs, Common/GA.Domain.Services/Atonal/Grothendieck/GrothendieckService.cs, Common/GA.Domain.Services/Atonal/Grothendieck/GrothendieckDelta.cs, Apps/ga-server/GaApi/Services/ContextualChordService.cs, Common/GA.Business.Config/ModalInterchange.yaml, Common/GA.Business.Config/YamlKnowledgeLoader.fs, GA.Data.MongoDB/Services/DocumentServices/YamlKnowledgeSyncService.cs, GA.Data.MongoDB/Extensions/ServiceCollectionExtensions.cs, GA.Data.MongoDB/Services/MongoDbService.cs, GaCLI/Program.cs.