Script en Python para Armonizar en Tiempo Real

Epiphone
por hace 3 semanas
Hola Hispasonicos, con la ayuda de Gemini he creado un script ahorrándome mucho trabajo. Esta diseñado para Ubuntu Studio pero quizas con alguna modificación sirva para otros sistemas operativos, paso a detallar cual su función, ese resumen también lo ha redactado Gemini, soy algo vago :-D



# 🎹 Presentación: Armonizador MIDI Dinámico de Tríadas en Cascada

### ¿Qué es este script?

Es una herramienta en Python que actúa como un **asistente de armonización inteligente en tiempo real**. El usuario solo tiene que tocar una línea melódica (una sola nota a la vez) y el script genera automáticamente un acompañamiento rico de tres voces (tríadas), asegurándose de que **ninguna nota suene fuera de la escala elegida**.

---

### 🚀 Las 3 Características Clave

#### 1. Inteligencia Diatónica (Se adapta a cualquier escala)

Al arrancar el script, el usuario introduce la escala mayor en la que quiere tocar (ej: *Do Mayor, Fa# Mayor, Mi Bemol Mayor*).

* Si el músico toca una nota dentro de la escala, el script la armoniza.
* Si por error toca una nota fuera de la escala (una alteración accidental), el script la detecta y la deja pasar "limpia" sin armonizar para evitar disonancias desagradables.

#### 2. La Melodía manda (Criterio de Voz Aguda)

En muchos armonizadores comerciales, las voces añadidas quedan por encima de lo que tocas, ensuciando la melodía. En este script, **la nota que tú tocas siempre es la más aguda (la voz principal)**. El script calcula los intervalos matemáticos necesarios para construir el acorde físicamente **por debajo** de tu dedo, logrando un sonido de acompañamiento robusto y natural.

#### 3. Variación de Acordes Dinámica (Ciclo de 3 Pasos)

Para evitar que el acompañamiento suene monótono, el script no repite siempre el mismo molde. Cada nota de una escala pertenece exactamente a tres acordes diferentes. El script aprovecha esto y, **cada vez que pulsas una nota, alterna cíclicamente entre esos 3 acordes**:

* **Pulsación 1:** Crea un intervalo de 3ª y 6ª inferior (Ej. tocando Do: genera *Do - La - Mi* ➔ **La menor**).
* **Pulsación 2:** Crea un intervalo de 3ª y 5ª inferior (Ej. tocando Do: genera *Do - La - Fa* ➔ **Fa Mayor**).
* **Pulsación 3:** Crea un intervalo de 4ª y 6ª inferior (Ej. tocando Do: genera *Do - Sol - Mi* ➔ **Do Mayor**).

---

### 🛠️ ¿Cómo funciona bajo el capó? (Para los interesados en la técnica)

1. **Conexión MIDI Flexible:** Utiliza la librería `mido` para detectar cualquier teclado controlador de entrada y conectarse a cualquier sintetizador o DAW (como Ableton, Logic o FL Studio) como salida.
2. **Cuidado del "Note Off":** El script realiza un seguimiento en tiempo real de qué notas extra ha creado para cada pulsación. Cuando el usuario levanta el dedo del teclado, el script apaga instantáneamente todo el bloque de notas para evitar que los acordes se queden "pegados" o se mezclen entre sí.

> **Resumen para la audiencia:** Es un script que transforma líneas melódicas simples en progresiones de acordes en cascada sobre la marcha, ideal para experimentar con texturas armónicas en directo o inspirarse en el proceso de composición.



Os Adjunto un Audio Ejemplo
Archivos adjuntos ( para descargar)
🎵 TriadasCromaticas.mp3
Epiphone
por hace 3 semanas
#1 Se me olvido adjuntar el script....perdón
Parece que no deja adjuntar el archivo  

import sys
import mido

# --- CONFIGURACIÓN DINÁMICA DE ESCALAS ---
DICCIONARIO_NOTAS = {
    "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
}

INTERVALOS_MAYOR = [2, 2, 1, 2, 2, 2, 1]

def generar_escala_mayor(tonica_str):
    """Genera los 7 semitonos de la escala mayor a partir de una tónica."""
    nota_raiz = DICCIONARIO_NOTAS.get(tonica_str.strip())
    if nota_raiz is None:
        print(f"Nota '{tonica_str}' no válida. Usando 'C' (Do) por defecto.")
        nota_raiz = 0
   
    escala = []
    nota_actual = nota_raiz
    for intervalo in INTERVALOS_MAYOR:
        escala.append(nota_actual % 12)
        nota_actual += intervalo
   
    return sorted(escala)

def obtener_nota_en_escala(nota_midi):
    """Devuelve la nota base (0-11) y la octava de una nota MIDI."""
    return nota_midi % 12, nota_midi // 12

def buscar_nota_diatonica_inferior(nota_midi, escala_mayor, grado_descendente):
    """
    Calcula una nota diatónica hacia abajo en la escala.
    grado_descendente=3 significa una tercera hacia abajo (bajar 2 posiciones en la lista).
    """
    nota_base, octava = obtener_nota_en_escala(nota_midi)
    if nota_base not in escala_mayor:
        return None
       
    idx = escala_mayor.index(nota_base)
    idx_armonia = idx - (grado_descendente - 1)
   
    # Ajuste automático de octavas inferiores en Python
    nueva_octava = octava + (idx_armonia // 7)
    nuevo_idx_escala = idx_armonia % 7
   
    return (nueva_octava * 12) + escala_mayor[nuevo_idx_escala]

def seleccionar_puerto(lista_puertos, tipo_puerto):
    if not lista_puertos:
        print(f"No se detectaron puertos de {tipo_puerto} disponibles.")
        sys.exit(1)
    print(f"\n--- Puertos de {tipo_puerto} disponibles ---")
    for i, puerto in enumerate(lista_puertos):
        print(f"[{i}] {puerto}")
    while True:
        try:
            seleccion = int(input(f"Selecciona el número ({tipo_puerto}): "))
            if 0 <= seleccion < len(lista_puertos):
                return lista_puertos[seleccion]
        except ValueError:
            pass

def obtener_intervalos_descendentes(estado):
    """
    Devuelve los grados diatónicos descendentes desde la nota más aguda.
    - Estado 0: C -> A (3ª inf) -> E (6ª inf)
    - Estado 1: C -> A (3ª inf) -> F (5ª inf)
    - Estado 2: C -> G (4ª inf) -> E (6ª inf)
    """
    if estado == 0:
        return [3, 6], "Melodía + 3ª inf + 6ª inf (Ej: C A E)"
    elif estado == 1:
        return [3, 5], "Melodía + 3ª inf + 5ª inf (Ej: C A F)"
    else:
        return [4, 6], "Melodía + 4ª inf + 6ª inf (Ej: C G E)"

def main():
    print("Iniciando Armonizador de Melodía Aguda (3 Pasos Descendentes)...")
   
    # 1. Selección de Escala
    tonica_seleccionada = input("Introduce la tónica de la Escala Mayor (Ej: C, F#, Bb): ").upper()
    if tonica_seleccionada not in DICCIONARIO_NOTAS:
        tonica_seleccionada = "C"
       
    NOTAS_ESCALA_MAYOR = generar_escala_mayor(tonica_seleccionada)
   
    # 2. Selección de Puertos MIDI
    puertos_entrada = mido.get_input_names()
    puertos_salida = mido.get_output_names()
   
    nombre_entrada = seleccionar_puerto(puertos_entrada, "ENTRADA")
    nombre_salida = seleccionar_puerto(puertos_salida, "SALIDA")
   
    print(f"\nSistema listo en {tonica_seleccionada} MAYOR.")
    print("La nota que toques SIEMPRE será la más aguda. Armonizaciones por debajo:")
    print("  Pulsación 1 -> 3ª inf y 6ª inf (Ej con C: C A E)")
    print("  Pulsación 2 -> 3ª inf y 5ª inf (Ej con C: C A F)")
    print("  Pulsación 3 -> 4ª inf y 6ª inf (Ej con C: C G E)")
    print("Presiona Ctrl+C para salir.\n")
   
    contador_armonias = 0     
    notas_armonizadas_activas = {}

    try:
        with mido.open_input(nombre_entrada) as puerto_in, mido.open_output(nombre_salida) as puerto_out:
            for mensaje in puerto_in:
               
                # === GESTIÓN DE NOTA PRESIONADA (NOTE ON) ===
                if mensaje.type == 'note_on' and mensaje.velocity > 0:
                   
                    # Filtro de escala: Si no está en la escala, pasa sola sin armonizar
                    if buscar_nota_diatonica_inferior(mensaje.note, NOTAS_ESCALA_MAYOR, grado_descendente=1) is None:
                        puerto_out.send(mensaje)
                        print(f"Nota: {mensaje.note} -> Fuera de escala (Pasa libre).")
                        continue

                    # Enviamos la nota original (Voz 1 - La más aguda)
                    puerto_out.send(mensaje)
                   
                    # Determinar el patrón según el orden cíclico (0, 1, 2)
                    estado_actual = contador_armonias % 3
                    intervalos, nombre_patron = obtener_intervalos_descendentes(estado_actual)
                   
                    # Calcular las dos voces inferiores SIEMPRE partiendo de la nota original
                    voz_2 = buscar_nota_diatonica_inferior(mensaje.note, NOTAS_ESCALA_MAYOR, intervalos[0])
                    voz_3 = buscar_nota_diatonica_inferior(mensaje.note, NOTAS_ESCALA_MAYOR, intervalos[1])
                   
                    notas_triada = []
                   
                    # Validar y enviar Voz 2
                    if voz_2 and 0 <= voz_2 <= 127:
                        notas_triada.append(voz_2)
                        puerto_out.send(mensaje.copy(note=voz_2))
                       
                    # Validar y enviar Voz 3
                    if voz_3 and 0 <= voz_3 <= 127:
                        notas_triada.append(voz_3)
                        puerto_out.send(mensaje.copy(note=voz_3))
                       
                    if notas_triada:
                        notas_armonizadas_activas[mensaje.note] = notas_triada
                       
                    print(f"🎵 [Pulsación #{estado_actual + 1}] Nota Aguda: {mensaje.note} -> Acorde: {notas_triada} [{nombre_patron}]")
                   
                    # Avanzar el ciclo
                    contador_armonias += 1
                       
                # === GESTIÓN DE NOTA SOLTADA (NOTE OFF) ===
                elif mensaje.type == 'note_off' or (mensaje.type == 'note_on' and mensaje.velocity == 0):
                    puerto_out.send(mensaje)
                   
                    if mensaje.note in notas_armonizadas_activas:
                        lista_notas_a_apagar = notas_armonizadas_activas.pop(mensaje.note)
                        for nota_extra in lista_notas_a_apagar:
                            puerto_out.send(mensaje.copy(note=nota_extra))
               
                else:
                    puerto_out.send(mensaje)
                   
    except KeyboardInterrupt:
        print("\n\nArmonizador apagado.")

if __name__ == "__main__":
    main()
Epiphone
por hace 3 semanas
Un nuevo Script :

🎹 Presentación: Armonizador MIDI a Dos Voces con Movimiento Pendular (Secuencia 3-4-5-6-5-4)
¿Qué es este script?
Es un asistente de armonización inteligente en tiempo real escrito en C nativo para Linux (ALSA). A diferencia de los armonizadores tradicionales estáticos, este script genera una segunda voz dinámica que se mueve de forma pendular por debajo de la melodía principal, creando líneas de contrapunto automáticas y orgánicas sin salirse jamás de la escala elegida.

🚀 Las 3 Características Clave
1. Movimiento Armónico Pendular (Ciclo de 6 Pasos)
El núcleo creativo de este script es su comportamiento cíclico. Cada vez que pulsas una nota en tu teclado, el script calcula una nota acompañante más grave siguiendo estrictamente este orden de intervalos diatónicos:

3ª inferior→4ª inferior→5ª inferior→6ª inferior→5ª inferior→4ª inferior
Si tomamos como ejemplo la nota Do (C) dentro de la escala de Do Mayor, el sistema generará de forma sucesiva las siguientes notas de acompañamiento:

Pulsación 1: C → A (3ª inf)

Pulsación 2: C → G (4ª inf)

Pulsación 3: C → F (5ª inf)

Pulsación 4: C → E (6ª inf)

Pulsación 5: C → F (5ª inf)

Pulsación 6: C → G (4ª inf)

Y el ciclo vuelve a comenzar automáticamente.

2. Inteligencia de Escala Total (Filtro Diatónico)
El usuario define la tónica de la escala mayor al iniciar el programa (ej: C, G, F#, Eb). El motor en C calcula matemáticamente las distancias correctas. Si el músico toca una nota que pertenece a la escala, se activa el juego de voces; si toca una nota fuera de la escala (una alteración accidental), el script la deja pasar limpia y sola para mantener la coherencia musical y evitar notas falsas.

3. Arquitectura C/ALSA de Ultra Baja Latencia
Al estar desarrollado en C utilizando la API nativa de ALSA Sequencer en Ubuntu Studio:

Latencia Cero: El procesamiento de los mensajes MIDI se realiza a nivel de kernel, eliminando cualquier retraso perceptible, ideal para ejecuciones en vivo.

Puertos Virtuales Inteligentes: No requiere configurar números de puertos en el código; el script crea sus propias conexiones virtuales (Entrada MIDI y Salida Armonizada) que aparecen inmediatamente en el Patchbay de Carla o QjackCtl.

🛠️ Gestión Inteligente del Silencio (Note Off)
El código incluye un búfer de rastreo que asocia de forma única cada nota extra generada con la nota real que tienes presionada. En el momento en que levantas el dedo del teclado, el script envía un mensaje Note Off instantáneo para ambas voces, garantizando que el contrapunto sea estricto y que los acordes no se queden "pegados" ni emborronen la mezcla.

Resumen para la comunidad: Es una herramienta diseñada para romper la monotonía de los acordes fijos. Al alternar la distancia de la segunda voz en cada pulsación, se genera una sensación de "pregunta y respuesta" interna que enriquece cualquier línea melódica simple sobre la marcha.

Adjunto audio de una ejemplo. Si alguien esta interesado para otro sistema operativo podrá solicitarlo a su IA favorita.
Archivos adjuntos ( para descargar)
🎵 ar2.mp3
Epiphone
por hace 2 semanas
He seguido practicando y  me he pasado a C que permite script ejecutables, Os presento este:

Alguien escribió:
## **Armonizador Multicanal Orquestal en C (para ALSA Sequencer)**

Este script es una herramienta de **orquestación y armonización generativa en tiempo real** diseñada específicamente para el ecosistema de audio de Linux (**Ubuntu Studio**, PipeWire/JACK). El programa actúa como un nodo MIDI inteligente: recibe una melodía monofónica o polifónica por una entrada MIDI virtual y la transforma instantáneamente en un bloque sonoro orquestal de **4 voces distribuidas en 4 canales MIDI independientes**.

### **¿Qué hace exactamente el script?**

Al ejecutarse, el script solicita al usuario una **tonalidad mayor base** (por ejemplo: Do, Sol, Fa#) y calcula automáticamente tanto su escala diatónica como su correspondiente **escala pentatónica mayor**.

A partir de ahí, cada nota que recibe se duplica y redefine en tiempo real a través de cuatro capas:

* **Canal MIDI 1 (Melodía Principal):** Replica la nota original idéntica a como fue tocada en el teclado o secuenciador, manteniendo el fraseo intacto.
* **Canal MIDI 2 (Armonía Diatónica Móvil):** Genera una segunda voz aplicando una secuencia cíclica inteligente de intervalos inferiores (3ª,4ª,,5ª,6ª,5ª,4ª). Esto evita la rigidez de las armonías paralelas fijas, aportando movimiento orgánico y contrapunto dentro de la escala mayor elegida.


* **Canal MIDI 3 (Bajo Pentatónico):** Genera en cada pulsación una nota de bajo calculada de forma aleatoria, pero estrictamente restringida a la escala pentatónica de la tonalidad, transpuesta automáticamente **dos octavas por debajo** para dar un soporte subgrave con cuerpo y sin disonancias.
* **Canal MIDI 4 (Textura / Pad):** Genera simultáneamente otra nota aleatoria de la escala pentatónica en la **misma octava** de la melodía actual. Al asignarse a un sintetizador con ataque lento (*Pad*), crea un colchón armónico flotante y ambiental que cohesiona todo el bloque.

### **Características Técnicas Destacadas**

* **Integración Nativa con ALSA:** Utiliza la API de `alsa/asoundlib.h`, creando puertos virtuales mapeables de forma inmediata en herramientas de enrutamiento gráfico como **QjackCtl**, **Helvum**, **Patchage** o **Carla**.
* **Gestión Polifónica de Voces:** El script realiza un rastreo en tiempo real de cada una de las notas activas. Cuando se suelta una tecla en el controlador, el script envía las órdenes de apagado (`Note Off`) correspondientes a las cuatro voces de forma matemática, garantizando una ejecución limpia y sin notas colgadas en los sintetizadores virtuales (*Yoshimi, Calf Plugins, Ardour, etc.*).
* **Algoritmo de Pánico / Muro de Seguridad No Bloqueante:** Implementa un temporizador de precisión (`clock_gettime`) que monitoriza el flujo de datos. Si detecta inactividad total durante más de 4 segundos, el script ejecuta un silenciado preventivo en los canales de acompañamiento por si se ha interrumpido la conexión MIDI o se ha detenido la sesión de improvisación de golpe.

---

*Es una excelente base para experimentar con síntesis multitimbral en Ubuntu Studio, ideal para live coding, improvisación con guitarra MIDI o teclados, y composición generativa.*

Adjunto un audio de muestra.

Podeis pedir a vuestra IA Favorita que os diseñe un script ejecutable adaptado a vuestro sistema operativo:-D
Archivos adjuntos ( para descargar)
🎵 Armonia_orquestal.mp3
Nuevo post

Regístrate o para poder postear en este hilo

Música
Temas