It is needed to implement a Conterpoint algorithm using Music21, The basic code is as follow:
from music21 import *
# Definir la melodía principal
melodia_principal = "C4 D4 E4 F4 G4 A4 B4 C5"
# Crear una lista de notas a partir de la melodía principal
notas_principales = [note.Note(nota) for nota in melodia_principal.split()]
# Definir la figura rítmica para el contrapunto (primera especie)
figura_contrapunto = duration.Duration(1) # q indica negras, e indicaría corcheas, etc.
# Crear una lista de notas para el contrapunto con la figura rítmica deseada
contrapunto_notas = []
for i in range(len(notas_principales)):
nota_acompanante = note.Rest()
nota_acompanante.duration = figura_contrapunto
contrapunto_notas.append(nota_acompanante)
# Asignar las alturas a las notas del contrapunto
contrapunto_notas[0].pitch = note.Note("C4").pitch # Asignar la primera nota para evitar el Rest inicial
for i in range(1, len(contrapunto_notas)):
contrapunto_notas[i].pitch = notas_principales[i].pitch
# Crear la voz de la melodía principal
voz_melodia = stream.Part()
voz_melodia.append([nota for nota in notas_principales])
# Crear la voz de la melodía acompañante
voz_acompanante = stream.Part()
voz_acompanante.append([nota for nota in contrapunto_notas])
# Verificar las reglas de armonía
for i in range(len(notas_principales)):
if abs(notas_principales[i].pitch.ps - contrapunto_notas[i].pitch.ps) in [1, 11]: # Verificar disonancias (segundas menores o tritones)
contrapunto_notas[i].transpose(-1, inPlace=True) # Resolver moviendo la nota hacia abajo (segunda menor o tritón)
elif abs(notas_principales[i].pitch.ps - contrapunto_notas[i].pitch.ps) in [10]: # Verificar séptimas mayores
contrapunto_notas[i].transpose(-2, inPlace=True) # Resolver moviendo la nota hacia abajo (séptima mayor)
# Verificar el paralelismo y los cruces de voces
for i in range(1, len(notas_principales)):
if abs(notas_principales[i].pitch.ps - contrapunto_notas[i].pitch.ps) in [4, 5, 7]: # Paralelos en tercera, cuarta o sexta
contrapunto_notas[i].transpose(-1, inPlace=True) # Resolver moviendo la nota hacia abajo
if abs(notas_principales[i].pitch.ps - contrapunto_notas[i-1].pitch.ps) in [0, 12]: # Cruces de voces
contrapunto_notas[i].transpose(-1, inPlace=True) # Resolver moviendo la nota hacia abajo
# Asegurar el inicio y final en unísono o en octava
if notas_principales[0].pitch.ps not in [contrapunto_notas[0].pitch.ps, contrapunto_notas[0].pitch.ps + 12]:
contrapunto_notas[0].transpose(-1, inPlace=True) # Resolver moviendo la nota hacia abajo (para que coincida en unísono u octava)
if notas_principales[-1].pitch.ps not in [contrapunto_notas[-1].pitch.ps, contrapunto_notas[-1].pitch.ps + 12]:
contrapunto_notas[-1].transpose(-1, inPlace=True) # Resolver moviendo la nota hacia abajo (para que coincida en unísono u octava)
# Crear la partitura con ambas voces
partitura = stream.Score()
partitura.insert(0, voz_melodia)
partitura.insert(0, voz_acompanante)
# Mostrar la partitura
show(partitura)