Wednesday, May 14, 2014

19. Function Tables


Now we will talk about some opcodes used to read tables. A table is an array of some given size. A table could be a calculated function or a sampled audio wave. Here, we will use sine functions.




The print opcode is used to print i-time variables, such as p fields from the score i-lines.




The phasor opcode creates a linear changing line which repeats at some frequency. The slope of the line is determined by the given frequency in the paramater list. A phasor opcode has two arguments, and only 1 is necessary. Usually the phase argument is left out so the line starts at 0. The x for the audio format, means it can accept i-time, k-rate or a-rate variables. The kcps terms means the frequency can be either k-rate or i-time.





This is an Instrument String. First, the 3 p-values are printed, and a phasor of 1 Hz is created for the audio channels.




The table opcode can be used to read a table. The first parameter is the index, which can either be a raw value or a normalized value. In the example, we use the normalized version, so the mode is 1. The index goes from 0 to 1 as in the phasor function.




This is an Instrument multi-line String where we have a phasor acting as an index term for the two audio rate variables. These two audio-rate variables, lookup table 1 and table 2.




One of the most often used opcodes is oscil. The function of oscil is to combine the functions of the phasor and table opcodes. In addition, there is an amplitude term.




This is the instrument String, using the oscil opcode. We don't have to create new i-time variables, as we did here. We could just as easily enter constants directly in the oscil opcode. Like here, you might use them for clarity.




Notice, the instrument() function has changed. It now has 3 parameters, with the first parameter being a comment string.




Next, we have two calls to the table function. This will create the two tables that will be used. The table functions uses the GEN 10 routine which is a sum, of sines, at different harmonics. They were covered in Tutorial 6. The first table is a single sine wave and the second table is different harmonics composing a square wave.




This is the table function. There is a documentation string indicating it creates f-lines in a score section. We use f-lines to create different tables. The function is very similar to the i-line, except now a table is generated.




After importing the module, we don't have to remember the ordering of parameters, since writing table and starting the parenthesis, in ipython, gives the format and doc string.




The score has examples for the three instruments. Now we have an extra function, rem() to insert a comment in the csd file.


# moduleCsound.py

from os import system
from time import sleep

L = []

startSyn,stopSyn='<CsoundSynthesizer>','</CsoundSynthesizer>'
startOpt,stopOpt='<CsOptions>','</CsOptions>'
startIns,stopIns='<CsInstruments>','</CsInstruments>'
startSco,stopSco='<CsScore>','</CsScore>'

def add(*b):
    """
    Adding terms to csd file
    """
    L.extend(b)
    return

def rem(remark):
    """
    Generates one line of comment
    """
    L.append('; %s' % remark)

def header(sr=44100,ksmps=10,nch=1,amp=1):
    """
    Generates 4 headers in the orchesta section
    """
    L.append('sr = %d' % sr)
    L.append('ksmps = %d' % ksmps)
    L.append('nchnls = %d' % nch)
    L.append('0dbfs = %d' % amp)
    return

def instrument(rem,instr,S):
    """
    Generates instrument code given a String
    in the orchestra section
    """
    tL = S.split('\n')
    if tL[0]!='' or tL[-1]!='' : raise Exception("Instr Str")
    tL = [' '*2 + tl for tl in tL]
    tL[0] = 'instr %d' % instr # (3)
    tL[-1] = 'endin'
    if rem!='': L.append('; ' + rem)
    L.extend(tL)
    return

def table(rem,tabNum,tabTime,tabSize,tabGEN,*tab):
    """
    Generates f line inside score section
    """
    tup = (tabNum,tabTime,tabSize,tabGEN)
    String = 'f %s %s %s %s' % tup
    LString1=[' ' + str(i) for i in tab]
    String1 = "".join(LString1)
    if rem!='': L.append('; ' + rem)
    L.append(String+String1)
    return

def score(instr,start,dur,*p):
    """
    Generates i line inside score section
    """
    String = 'i %s %s %s' % (instr,start,dur)
    LString1=[' ' + str(pf) for pf in p]
    String1 = "".join(LString1)
    L.append(String+String1)
    return
    
def writeRun(fname):
    """
    Write out the csd file and perform it
    """
    OutL=[Lu + '\n' for Lu in L]
    out = open('%s.csd' % fname,'w')
    out.writelines(OutL)
    out.close()
    sleep(1)
    cmd = 'csound -o %s.wav %s.csd' % (fname,fname)
    status=system(cmd)
    if status!=0: raise Exception ('Could not write wav file')
    return



The text output, as captured by the Anaconda Command Prompt, shows the output due to the print statements.


# Main.py

from moduleCsound import *
add(startSyn,startOpt,stopOpt,startIns)
header(nch=2)

# *** Instrument Strings ***

PhasorEx="""
print p1,p2,p3
aphas phasor 1
out aphas,aphas
"""
TableEx="""
print p1,p2,p3
aphas phasor 1
atab1 table aphas,1,1
atab2 table aphas,2,1
out atab1,atab2
"""
OscilEx="""
iamp=0.5
ifreq=2
print p1,p2,p3,iamp,ifreq
aoscil1 oscil iamp,ifreq,1
aoscil2 oscil iamp,ifreq,2
out aoscil1,aoscil2
"""

instrument('1. phasor example',1,PhasorEx)
instrument('2. table example',2,TableEx)
instrument('3. oscil example',3,OscilEx)

add(stopIns,startSco)

# *** Table ***
table('1. Sine wave',1,0,1024,10,1)
table('2. Square wave',2,0,1025,10,1,0,0.33,0,0.20,0,0.14)

# *** Score ***
rem('Examples for phasor, table, oscil')
score(1,0,2)
score(2,2,2)
score(3,4,2)

add(stopSco,stopSyn)
writeRun('Tut19')



Finally, running the csd file results in this wave file.


<CsoundSynthesizer>
<CsOptions>
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 10
nchnls = 2
0dbfs = 1
; 1. phasor example
instr 1
  print p1,p2,p3
  aphas phasor 1
  out aphas,aphas
endin
; 2. table example
instr 2
  print p1,p2,p3
  aphas phasor 1
  atab1 table aphas,1,1
  atab2 table aphas,2,1
  out atab1,atab2
endin
; 3. oscil example
instr 3
  iamp=0.5
  ifreq=2
  print p1,p2,p3,iamp,ifreq
  aoscil1 oscil iamp,ifreq,1
  aoscil2 oscil iamp,ifreq,2
  out aoscil1,aoscil2
endin
</CsInstruments>
<CsScore>
; 1. Sine wave
f 1 0 1024 10 1
; 2. Square wave
f 2 0 1025 10 1 0 0.33 0 0.2 0 0.14
; Examples for phasor, table, oscil
i 1 0 2
i 2 2 2
i 3 4 2
</CsScore>
</CsoundSynthesizer>



You will find additional information at pythonaudio.blogspot.com, including the source code.



This is the video of Tutorial 19:


1 comment:

About Me

I have used Python for the last 10+ years. I have a PhD in Electrical Engineering. I have taught Assembly Language programming of Intel-compatible chips as well as PC hardware interfacing. In my research, I have used Python to automate my calculations in physics and chemistry. I also use C++ and Java, often with Python.