Un sistema donde la tónica actúa como sol gravitacional y los acordes orbitan según su función armónica
Diciembre 2025
Mientras que la teoría Neo-Riemanniana trata los acordes como ciudadanos iguales en un espacio simétrico, la armonía funcional de Jean-Philippe Rameau (1722) los organiza en una jerarquía gravitacional. Este artículo presenta Rameau Machine, un sistema generativo donde la tónica actúa como centro de masa, la tensión se acumula al alejarse de ella, y las cadenas de Markov con pesos dinámicos producen progresiones que respetan tres siglos de práctica musical.
Palabras clave: armonía funcional, Rameau, gravedad tonal, Markov, voice leading, Web Audio API
En el vasto territorio de la teoría musical occidental, dos paradigmas fundamentales compiten por explicar cómo se organizan los acordes y por qué ciertas progresiones nos resultan satisfactorias mientras otras nos sorprenden o inquietan.
El primero, codificado por Jean-Philippe Rameau en 1722, concibe la armonía como un sistema solar: la tónica es el sol, centro gravitacional alrededor del cual orbitan los demás acordes. Cada acorde tiene una función —estabilidad, tensión, preparación— y la música es un viaje de alejamiento y retorno al hogar.
El segundo, desarrollado por los teóricos neo-riemannianos a finales del siglo XX, imagina la armonía como un espacio homogéneo: un toroide donde todos los acordes son ciudadanos iguales, conectados por transformaciones simétricas (P, L, R). No hay centro, no hay gravedad, solo movimiento parsimonioso entre vecinos cercanos.
Rameau Machine implementa el primer paradigma: un generador de armonía funcional donde las progresiones emergen de la tensión acumulada y la atracción gravitacional hacia la tónica.
Jean-Philippe Rameau (1683-1764) fue compositor, teórico y polemista. Su Traité de l'harmonie réduite à ses principes naturels (1722) revolucionó la teoría musical al proponer que la armonía —no la melodía ni el contrapunto— era el fundamento de la música.
La innovación clave de Rameau fue el concepto de basse fondamentale (bajo fundamental): cada acorde, independientemente de su inversión, tiene una raíz que determina su identidad y función. Un acorde de Do mayor en primera inversión (Mi-Sol-Do) sigue siendo "un acorde de Do", con Do como su bajo fundamental.
De este principio emergen las funciones armónicas: no todos los acordes son iguales. Algunos proporcionan estabilidad (tónica), otros crean tensión que demanda resolución (dominante), y otros preparan esa tensión (subdominante).
En la tonalidad mayor, los siete grados de la escala se agrupan en tres familias funcionales:
┌─────────────────────────────────────┐
│ TÓNICA (T) │
│ I vi iii │
│ estabilidad │
└─────────────────┬───────────────────┘
│
┌───────────┴───────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ SUBDOMINANTE (S) │ │ DOMINANTE (D) │
│ IV ii │────▶│ V viiº │
│ preparación │ │ tensión │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
└───────────┬───────────────┘
▼
(resolución a T)
| Función | Grados | Sensación | Analogía Física |
|---|---|---|---|
| Tónica (T) | I, vi, iii | Reposo, hogar, resolución | Punto de equilibrio |
| Subdominante (S) | IV, ii | Alejamiento, expansión | Energía potencial |
| Dominante (D) | V, viiº | Tensión, urgencia | Compresión del resorte |
Rameau identificó una progresión "natural" que recorre las tres funciones:
Esta progresión (por ejemplo: I → IV → V → I) representa el viaje armónico arquetípico: partimos del hogar (T), nos alejamos (S), acumulamos tensión (D), y resolvemos volviendo (T). Es el patrón detrás de incontables canciones populares, himnos religiosos y obras clásicas.
En Rameau Machine, implementamos las funciones armónicas como un campo gravitacional. La tónica es el centro de masa; cuanto más nos alejamos, mayor es la "tensión" acumulada y mayor la fuerza de atracción hacia el centro.
Visualización del Campo Gravitacional
======================================
Zona T (centro)
┌───┐
╱ I ╲
╱ vi ╲
│ iii │
│ ▪▪▪▪▪▪ │ ← menor tensión
╲ ╱
╲ ╱
┌──────────────┐
│ Zona D │
│ V viiº │ ← tensión media
│ ▪▪▪▪▪▪▪▪ │
└──────────────┘
┌────────────────────┐
│ Zona S │
│ IV ii │ ← mayor distancia
│ ▪▪▪▪▪▪▪▪▪▪▪▪ │
└────────────────────┘
El modelo asigna a cada función un peso de tensión:
const TENSION_WEIGHTS = {
'T': 0, // Sin tensión - equilibrio
'S': 0.3, // Tensión moderada - alejamiento
'D': 0.7 // Alta tensión - necesita resolver
};
A medida que la progresión avanza, acumulamos tensión. Esta tensión modifica las probabilidades de transición: a mayor tensión acumulada, mayor probabilidad de ir hacia la tónica.
El corazón probabilístico de Rameau Machine es una cadena de Markov de primer orden, pero con una modificación crucial: las probabilidades de transición no son estáticas, sino que dependen del estado interno del sistema (la tensión acumulada).
Definimos una matriz de transición basada en las convenciones de la armonía funcional:
// Desde I (Tónica)
'I': { 'I': 0.05, 'ii': 0.15, 'iii': 0.1, 'IV': 0.25, 'V': 0.35, 'vi': 0.08, 'viiº': 0.02 }
// Desde V (Dominante)
'V': { 'I': 0.65, 'ii': 0.02, 'iii': 0.03, 'IV': 0.05, 'V': 0.05, 'vi': 0.18, 'viiº': 0.02 }
// Desde IV (Subdominante)
'IV': { 'I': 0.15, 'ii': 0.1, 'iii': 0.05, 'IV': 0.05, 'V': 0.5, 'vi': 0.1, 'viiº': 0.05 }
Observa que desde V, hay un 65% de probabilidad de ir a I (cadencia auténtica) y un 18% de ir a vi (cadencia rota/deceptiva).
Estas probabilidades base se modifican en tiempo real según la tensión acumulada:
getTransitionProbabilities() {
const baseProbs = TRANSITIONS[this.position];
const modified = {};
let total = 0;
for (const [chord, prob] of Object.entries(baseProbs)) {
const func = CHORDS[chord].function;
let newProb = prob;
if (func === 'T') {
// Aumentar probabilidad hacia tónica según tensión
newProb *= (1 + this.tension * this.gravityStrength);
} else if (func === 'D' && this.tension > 0.5) {
// Reducir dominante si ya hay mucha tensión
newProb *= 0.7;
}
modified[chord] = newProb;
total += newProb;
}
// Normalizar
for (const chord in modified) {
modified[chord] /= total;
}
return modified;
}
Una de las características más poderosas de Rameau Machine es la capacidad de manipular las probabilidades de transición en tiempo real. En lugar de editar la matriz completa, el usuario controla modificadores globales que "doblan" las reglas.
El control principal es el slider de gravedad (0-100%):
| Gravedad | Comportamiento | Resultado Musical |
|---|---|---|
| 0% | Distribución uniforme (1/7 para cada acorde) | Caos, deriva aleatoria, sin dirección tonal |
| 50% | Matriz base de transiciones | Comportamiento estándar, balance entre sorpresa y estructura |
| 100% | Matriz estricta funcional (D→T al 95%) | Cadencias perfectas constantes, muy predecible |
Matemáticamente, la gravedad interpola entre tres matrices:
// Interpolación según gravedad
if (gravity <= 0.5) {
// Entre uniforme y base
const t = gravity * 2;
p = UNIFORM_PROB * (1 - t) + baseProb * t;
} else {
// Entre base y estricta
const t = (gravity - 0.5) * 2;
p = baseProb * (1 - t) + strictProb * t;
}
El botón "Inyectar Caos" añade ruido temporal a todas las probabilidades, útil para escapar de bucles predecibles:
injectChaos(amount = 0.4) {
this.chaosNoise = Math.min(1, this.chaosNoise + amount);
}
// El caos decae automáticamente cada acorde
decayChaos() {
this.chaosNoise *= 0.7; // 30% de decay por paso
if (this.chaosNoise < 0.01) this.chaosNoise = 0;
}
El caos inyectado perturba las probabilidades durante 4-8 acordes antes de disiparse, creando momentos de "sorpresa controlada".
La interfaz muestra la matriz de transición P(j|i) como un heatmap 7×7 en tiempo real:
I ii iii IV V vi viiº
┌─────────────────────────────────────────────┐
I │ ░░░ ▓▓░ ░░░ ▓▓▓ ████ ▓░░ ░░░ │
ii │ ░░░ ░░░ ░░░ ░░░ ████ ░░░ ▓▓░ │
iii │ ░░░ ░░░ ░░░ ▓▓▓ ░░░ ████ ░░░ │
IV │ ▓░░ ░░░ ░░░ ░░░ ████ ░░░ ▓░░ │
V │ ████ ░░░ ░░░ ░░░ ░░░ ▓▓░ ░░░ │ ← V→I muy alto
vi │ ░░░ ▓▓▓ ░░░ ████ ▓▓░ ░░░ ░░░ │
viiº│ ████ ░░░ ░░░ ░░░ ░░░ ░░░ ░░░ │
└─────────────────────────────────────────────┘
░ = baja probabilidad ▓ = media █ = alta
La fila actual (acorde presente) se resalta, permitiendo ver de un vistazo las probabilidades del siguiente paso. Los colores siguen la convención funcional: verde (T), azul (S), rojo (D).
La entropía de Shannon mide la "predictibilidad" del estado actual:
getEntropy() {
const probs = this.getTransitionProbabilities();
let entropy = 0;
for (const p of Object.values(probs)) {
if (p > 0) entropy -= p * Math.log2(p);
}
// Normalizar: max entropy = log2(7) ≈ 2.807
return entropy / Math.log2(7);
}
Generar una secuencia de acordes es solo el primer paso. Para que suene como música real —no como una sucesión de bloques sonoros— necesitamos voice leading: la conducción suave de cada voz de un acorde al siguiente.
Trabajamos con cuatro voces en el estilo coral tradicional:
Soprano ────────────────────────────────── (C4 - G5) voz aguda
Alto ────────────────────────────────── (G3 - D5) voz media-alta
Tenor ────────────────────────────────── (C3 - G4) voz media-baja
Bajo ────────────────────────────────── (E2 - C4) voz grave, lleva la raíz
El VoiceLeader implementa las reglas clásicas del contrapunto:
| Regla | Descripción | Penalización |
|---|---|---|
| Quintas paralelas | Dos voces no pueden moverse en quintas justas paralelas | +50 puntos |
| Octavas paralelas | Dos voces no pueden moverse en octavas paralelas | +50 puntos |
| Cruce de voces | Una voz inferior no puede subir por encima de una superior | +30 puntos |
| Salto grande | Intervalos mayores a una sexta son desaconsejados | +10 puntos |
| Movimiento conjunto | Se prefiere movimiento por grado conjunto (2das) | -5 puntos (bonus) |
| Resolución de sensible | La sensible (7mo grado) debe resolver a tónica | +20 puntos si no resuelve |
findOptimalVoicing(targetChord, previousVoicing) {
const candidates = this.generateCandidates(targetChord);
let bestVoicing = null;
let bestScore = Infinity;
for (const candidate of candidates) {
let score = 0;
// Evaluar movimiento total
score += this.totalMovement(previousVoicing, candidate);
// Penalizar paralelas
if (this.hasParallelFifths(previousVoicing, candidate)) score += 50;
if (this.hasParallelOctaves(previousVoicing, candidate)) score += 50;
// Penalizar cruces
if (this.hasVoiceCrossing(candidate)) score += 30;
// Bonus por movimiento conjunto
score -= this.stepwiseMotionBonus(previousVoicing, candidate) * 5;
if (score < bestScore) {
bestScore = score;
bestVoicing = candidate;
}
}
return bestVoicing;
}
Un refinamiento importante: además de minimizar el movimiento, el VoiceLeader aplica una penalización por distancia al centro ideal de cada voz:
// Centros ideales (registro más resonante)
const voiceCenters = {
bass: 48, // C3
tenor: 52, // E3
alto: 64, // E4
soprano: 72 // C5
};
// Costo total = movimiento + distancia_al_centro × 0.15
const totalCost = movementCost + (centerCost * centerPenaltyWeight);
Esto evita que las voces se "escapen" a registros extremos donde los osciladores suenan delgados o fangosos.
El bajo no se limita a tocar notas sostenidas. Según el estilo seleccionado, ejecuta patrones rítmicos característicos:
| Estilo | Patrón | Subdivisión | Carácter |
|---|---|---|---|
| Clásico | Alberti (1-5-3-5) | Semicorcheas | Mozartiano, elegante |
| Barroco | 1-3-5-3 | Corcheas | Bajo continuo |
| Romántico | Octavas rotas (1-8-1-8) | Corcheas | Expresivo, amplio |
| Jazz | Walking (aproximación cromática) | Negras | Swing, direccional |
// Generador de patrones de bajo
const patterns = {
alberti: (root, third, fifth) => [root, fifth, third, fifth],
barroco: (root, third, fifth) => [root, third, fifth, third],
octaves: (root) => [root, root + 12, root, root + 12],
walking: (root, third, fifth, nextRoot) => {
const approach = nextRoot > root ? nextRoot - 1 : nextRoot + 1;
return [root, third, fifth, approach];
}
};
Mientras el bajo ejecuta su patrón, las voces superiores (Soprano, Alto, Tenor) mantienen el "colchón" armónico, creando una textura más rica que los simples acordes en bloque.
┌─────────────────────────────────────────────────────────────────────┐
│ RAMEAU MACHINE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ TonalGravity │───▶│ VoiceLeader │───▶│ VoiceLeadingSynth │ │
│ │ │ │ │ │ │ │
│ │ - tensión │ │ - SATB │ │ - 4 osciladores │ │
│ │ - position │ │ - reglas │ │ - ADSR envelopes │ │
│ │ - markov │ │ - scoring │ │ - bajo continuo │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────────────┐ │
│ │TonalForceField│ │ Web Audio API │ │
│ │ │ │ │ │
│ │ - D3.js │ │ - AudioContext │ │
│ │ - force sim │ │ - GainNode │ │
│ │ - anillos │ │ - MediaRecorder │ │
│ └──────────────┘ └──────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
Para permitir cualquier tonalidad, usamos un sistema de transposición basado en semitonos:
const KEY_PITCH = {
'C': 0, 'C#': 1, 'Db': 1, 'D': 2, 'D#': 3, 'Eb': 3,
'E': 4, 'F': 5, 'F#': 6, 'Gb': 6, 'G': 7, 'G#': 8,
'Ab': 8, 'A': 9, 'A#': 10, 'Bb': 10, 'B': 11
};
function transposeNote(baseMidi, key) {
const offset = KEY_PITCH[key] || 0;
return baseMidi + offset;
}
Los acordes se definen en Do mayor y se transponen en tiempo real según la tonalidad seleccionada.
La duración de cada acorde varía según su función y la tensión acumulada:
getDuration(chord, tension) {
const func = CHORDS[chord].function;
const baseDuration = 60000 / this.tempo; // ms por pulso
let multiplier = 1.0;
if (func === 'T') {
multiplier = 1.5; // Tónica respira más
} else if (func === 'D' && tension > 0.6) {
multiplier = 0.7; // Dominante urgente
}
// Rubato en estilo romántico
if (this.style === 'romantic') {
multiplier *= 0.9 + Math.random() * 0.2;
}
return baseDuration * multiplier;
}
Los acordes se disponen en anillos concéntricos usando una simulación de fuerzas:
// Fuerza radial según función
const functionRadii = {
'T': height * 0.08, // Centro (con espacio para separar I, vi, iii)
'D': height * 0.25, // Anillo medio
'S': height * 0.40 // Anillo exterior
};
const forceRadial = d3.forceRadial(d => functionRadii[d.function], cx, cy)
.strength(0.8);
simulation
.force('radial', forceRadial)
.force('collide', d3.forceCollide(40))
.force('charge', d3.forceManyBody().strength(-100));
Es instructivo comparar Rameau Machine con Tonnetz Atractor, que implementa el paradigma neo-riemanniano.
| Aspecto | Rameau Machine | Tonnetz Atractor |
|---|---|---|
| Geometría | Anillos concéntricos (jerarquía) | Toroide (espacio homogéneo) |
| Centro | Tónica como atractor | Sin centro privilegiado |
| Transiciones | Funcionales (T→S→D→T) | Parsimoniosas (P, L, R) |
| Tensión | Acumulativa, se resuelve | Uniforme |
| Repertorio ideal | Barroco, Clásico, Jazz standards | Romántico tardío, cine, ambient |
| Ejemplo canónico | I - IV - V - I | C - E - Ab (eje mayor-tercera) |
La armonía funcional brilla especialmente en el modo menor, donde las tensiones son más complejas y la sensible del acorde V juega un rol crucial. Rameau Machine implementa el modo menor armónico, que mantiene el V como acorde mayor para preservar la fuerza de la cadencia auténtica.
Un simple switch en la interfaz permite cambiar entre modos. Al activar el modo menor:
TRANSITIONS_MINOR
MODO MENOR ARMÓNICO
═══════════════════════════
Grados: i iiº III iv V VI viiº
Funciones:
┌───────────────────────────────────────────────┐
│ T: i, III, VI (más ambiguo que en mayor) │
│ S: iv, iiº (iv más oscuro que IV) │
│ D: V, viiº (V SIEMPRE mayor: sensible→tónica) │
└───────────────────────────────────────────────┘
Cadencias típicas:
• Auténtica: V → i (70%)
• Plagal: iv → i
• Deceptiva: V → VI (15%)
| Aspecto | Modo Mayor | Modo Menor |
|---|---|---|
| Tónica | I (mayor) | i (menor) |
| Subdominante | IV (mayor) | iv (menor, más oscuro) |
| Dominante | V (mayor) | V (mayor, sensible elevada) |
| Relativa | vi (menor) | VI (mayor, "puerto seguro") |
| Mediante | iii (menor) | III (mayor, relativo mayor) |
| Cadencia deceptiva | V → vi | V → VI (más luminoso) |
El elemento crucial del modo menor armónico es la sensible elevada. En Do menor natural, el VII grado sería Si♭. Pero para crear la atracción dominante→tónica característica de la armonía funcional, elevamos este grado a Si♮:
Do menor NATURAL: C D E♭ F G A♭ B♭ C
↑ ↑
tónica VII sin atracción
Do menor ARMÓNICO: C D E♭ F G A♭ B♮ C
↑ ↑
tónica sensible (→ C)
Esta elevación convierte el acorde v (menor) en V (mayor), creando el mismo "tirón gravitacional" que en modo mayor. Es lo que hace que la cadencia V→i suene tan conclusiva.
CHORDS_MINOR, el acorde V tiene third: 11 (Si♮ en Do menor), no third: 10 (Si♭). Esto garantiza que el acorde V siempre contenga la sensible, independientemente de la tonalidad seleccionada.
Las probabilidades en modo menor difieren significativamente del mayor:
Rameau Machine demuestra que los principios de armonía funcional de hace 300 años pueden implementarse como sistemas generativos contemporáneos. La combinación de:
...produce progresiones que suenan coherentes y "musicales" porque respetan las expectativas que tres siglos de práctica musical han inscrito en nuestros oídos. Los bias sliders permiten explorar el espectro completo entre caos total y rigidez funcional, revelando que la música más interesante suele habitar el territorio intermedio.
Más allá del ejercicio técnico, el proyecto invita a reflexionar sobre la naturaleza de la creatividad musical. ¿Es la armonía funcional un descubrimiento (leyes naturales de la acústica y la cognición) o una invención (convenciones culturales arbitrarias)? Rameau creía lo primero; la existencia de sistemas musicales no tonales sugiere lo segundo. Quizá la verdad, como siempre, yace en algún punto intermedio.
La armonía no está en los acordes individuales.
Está en la gravedad que los conecta.
[1] Rameau, J.P. (1722). Traité de l'harmonie réduite à ses principes naturels. Paris: Ballard.
[2] Christensen, T. (1993). Rameau and Musical Thought in the Enlightenment. Cambridge University Press.
[3] Kostka, S. & Payne, D. (2012). Tonal Harmony (7th ed.). McGraw-Hill.
[4] Temperley, D. (2007). Music and Probability. MIT Press.
[5] Tymoczko, D. (2011). A Geometry of Music. Oxford University Press.
[6] Cohn, R. (2012). Audacious Euphony: Chromaticism and the Triad's Second Nature. Oxford University Press.
[7] Lerdahl, F. & Jackendoff, R. (1983). A Generative Theory of Tonal Music. MIT Press.
[8] Huron, D. (2006). Sweet Anticipation: Music and the Psychology of Expectation. MIT Press.