A través de su API (Application Programming Interface), Csound puede ser importado como un módulo de Python.
De esta manera se puede utilizar todo el motor de síntesis de Csound dentro de un programa escrito en Python, mediante el uso del módulo csnd6.
IMPORTANTE: el módulo csnd6 sólo puede ser importado por Python2.
Mediante esta técnica se pueden desarrollar aplicaciones completas que utilicen el motor de Csound para la generación de sonido.
También puede utilizarse esta facilidad para generar algorítmicamente bloques de código de orquesta y/o de partitura y compilarlos con Csound, todo desde un mismo programa de Python.
Para este tipo de aplicación es suficiente conocer las llamadas básicas para crear y utilizar instancias del objeto Csound.
El siguiente programa es un ejemplo mínimo del uso del objeto Csound para compilar una orquesta ya existente.
# ejemplo 1
# se importa el módulo csnd6
import csnd6
c = csnd6.Csound() # se crea una instancia del objeto Csound
c.Compile('test.csd') # se compila una orquesta de Csound existente
c.Perform() # se ejecuta la instancia de Csound
c.Stop() # se finaliza
En este caso la llamada c.Stop() es innecesaria, porque la ejecución termina al finalizar la orquesta. Pero en otros casos es necesaria, y por lo tanto es una buena práctica incluirla siempre.
En el ejemplo siguiente, la orquesta y la partitura están definidas dentro del mismo programa, como variables de tipo string.
Las llamadas respectivas son CompileOrc() para compilar la orquesta, y ReadScore para compilar la partitura.
Al tratarse de cadenas de caracteres, es necesaria la llamada a .Start() antes de la llamada a .Perform().
# ejemplo 2
# se importa el módulo csnd6
import csnd6
# se define la orquesta y la partitura como variables de tipo string
# la orquesta es una cadena multilínea
orc = """
sr = 48000
ksmps = 8
0dbfs = 1
instr 1
iamp init ampdbfs(p4)
ifrec init p5
kamp linen iamp, .01, p3, .05
asig vco2 kamp, ifrec
out asig
endin
"""
sco = "i1 0 3 -6 300"
c = csnd6.Csound()
c.SetOption("-odac") # SetOption() establece opciones de compilación (una por cada llamada)
c.CompileOrc(orc) # se compila la cadena con la orquesta
c.ReadScore(sco) # se compila la cadena con la partitura
c.Start() # cuando se compila de cadenas, es necesaria esta llamada antes de Perform()
c.Perform()
c.Stop()
La llamada SetOption() establece las opciones de la línea de comando (flags). Este método admite un único argumento, por lo que es necesario una llamada por cada opción que se quiera pasar a Csound.
En el ejemplo siguiente la cadena de la partitura se genera mediante un loop.
En primer término se define una función que crea una cadena con formato de evento i de Csound, a partir de un iterable (lista o tuple) con los p-fields. El número de intrumento (p1) y el offset temporal para sumar a p2 se pueden recibir como argumentos opcionales (por defecto 1 y 0 respectivamente).
El loop genera elementos con p2 incremental, p3 y p4 fijos, y p5 aleatorio.
# ejemplo 3
import csnd6
import random
# se define la orquesta como variable de tipo string
orc = """
sr = 48000
ksmps = 8
0dbfs = 1
instr 1
iamp init ampdbfs(p4)
ifrec init cpsmidinn(p5) ; p5 en número de nota MIDI
print ifrec
kamp linen iamp, .01, p3, .05
asig vco2 kamp, ifrec
out asig
endin
"""
# función para generar un evento de Csound a partir de un iterable con p-fields
def csnd_event(pfields, instr=1, offset=0):
'''convierte una lista o tuple con p-fields en un evento de csound'''
pfields = list(pfields)
pfields[0] += offset # desplazamiento del init-time
evento = "i" + str(instr) + "\t" + "\t".join(str(i) for i in pfields) + "\n"
return evento
# crea una cadena vacía para la partitura
sco = ""
dur = .12
# agrega eventos a la partitura mediante un loop
for i in range(50):
a = csnd_event([i*dur, dur, -3, random.randint(48, 72)]) # p5 aleatorio
sco += a
c = csnd6.Csound()
c.SetOption("-odac")
c.CompileOrc(orc)
c.ReadScore(sco)
c.Start()
c.Perform()
c.Stop()
Como la función csnd_event puede ser útil en otras oportunidades, resulta conveniente incluirla en un módulo que pueda ser luego importado por otros programas que necesiten la misma funcionalidad.
%load csound_tools.py
# función para generar un evento de Csound a partir de un iterable con p-fields
def csnd_event(pfields, instr=1, offset=0):
'''convierte una lista o tuple con p-fields en un evento de csound'''
pfields = list(pfields)
pfields[0] += offset # desplazamiento del init-time
evento = "i" + str(instr) + "\t" + "\t".join(str(i) for i in pfields) + "\n"
return evento
En el módulo csound_tools podemos incluir en el futuro otras funciones relacionadas que puedan ser reutilizadas.
En el ejemplo siguiente se incorpora la función desarrollada oportunamente para generar una melodía isorrítmica a partir de una talea y un color.
# ejemplo 4
import csnd6
import csound_tools as cs # se importa el módulo con la función csnd_event()
# se define la orquesta como variable de tipo string
orc = """
sr = 48000
ksmps = 8
0dbfs = 1
instr 1
iamp init .5
ifrec init cpsmidinn(p4) ; p4 en número de nota MIDI
print ifrec
kamp linen iamp, .01, p3, .05
asig vco2 1, ifrec
afilt moogladder asig, 4000, 0.3
out afilt*kamp
endin
"""
def isorritmico(talea, color, t_inicial=0):
'''crea una melodía isorrítmica a partir de una talea y un color'''
# extiende las secuencias para que tengan la misma cantidad de elementos
clen, tlen = len(color), len(talea)
talea_rep = talea * clen
color_rep = color * tlen
tiempos = [t_inicial]
for i in range(len(talea_rep)-1):
tiempos.append(tiempos[i]+talea_rep[i])
# crea la lista de notas como tuples (tiempo inicial, altura, duración)
notas = [(z, x, y) for z, x, y in zip(tiempos, talea_rep, color_rep)]
return notas
talea = [1.25, 0.75, 0.5, 0.25, 0.5]
color = [72, 62, 59, 56, 67, 70, 66, 57, 63, 76, 73, 65]
notas = isorritmico(talea, color)
# crea una partitura con indicación de tempo
sco = "t0 92\n"
for nota in notas:
evento = cs.csnd_event(nota)
sco += evento
c = csnd6.Csound()
c.SetOption("-odac")
c.CompileOrc(orc)
c.ReadScore(sco)
c.Start()
c.Perform()
c.Stop()
Steven Yi: Csound 6 - Python API Examples
https://github.com/csound/csoundAPI_examples/tree/master/python
François Pinot: Real-time Coding Using the Python API: Score Events
Csound Journal - Issue 14, 2011
http://www.csounds.com/journal/issue14/realtimeCsoundPython.html