The linseg envelope opcode is used to create envelopes for a sound oscillator.
For the python file to write the csound file, we will need a list in pts of levels and duration between levels.
For example for first fourth of note duration we go from 220 to 230. Then for half of note duration, we go from 230 to 260. Finally for last fourth, we go linearly to 240.
This program uses the envelope to control frequency of oscillator.
# ex7.py
# linseg opcode
from csd import CSD
import table
from opcodes import envelope, output, source
csd = CSD(__file__)
csd.begin()
csd.add_instrument(
num = 1,
opcodes = [envelope.linseg(
sig_out = 'kfreq',
pts = [220,'idur/4',230,'idur/2',260,'idur/4',240]
),
source.lfo(
sig_out = 'klfo',
amp = 5,
freq = 2),
envelope.adsr(
sig_out = 'kadsr'
),
source.poscil(
sig_out = 'aOsc',
amp = 'kadsr',
freq = 'kfreq+klfo'
),
output.outs(
sig_in = ['aOsc', 'aOsc' ]
)
]
)
csd.middle()
csd.add('i 1 0 40')
csd.add_tables([table.sine(
num=1,
amps=[1,1/2,1/3,1/4,1/5,1/6,1/7,1/8]
)
])
csd.end()
We use table.py file:
We use output.py from opcodes folder:
# output.py
# ver 0
import sys
#1. out
def out(**dic):
''' Writes mono audio data to an external device or stream.
sig_in '''
sig_in = dic.get('sig_in', '')
if len(sig_in) == '':
print('We need sig_in for out')
sys.exit(-1)
return 'out %s' % sig_in
#2. outs
def outs(**dic):
''' Writes stereo audio data to an external device or stream.
sig_in (2-len) '''
sig_in = dic.get('sig_in', [])
if len(sig_in) != 2:
print('We need sig_in (2-len) for outs')
sys.exit(-1)
return 'outs %s,%s' % (sig_in[0],sig_in[1])
This is the new envelope.py file from opcodes folder:
# envelope.py
# ver 1
import sys
#1. adsr
def adsr(**dic):
''' Calculates the classical ADSR envelope using linear segments.
sig_out
attack, duration of attack phase
decay, duration of decay
sustain_level, level for sustain phase
release, duration of release phase
delay, period of zero before the envelope starts '''
sig_out = dic.get('sig_out', '')
if sig_out == '':
print('We need sig_out for adsr')
sys.exit(-1)
attack = dic.get('attack','0.1*idur')
decay = dic.get('decay', '0.1*idur')
sustain_level = dic.get('sustain_level', 0.5)
release = dic.get('release', '0.1*idur')
delay = dic.get('delay', 0)
t = sig_out,attack,decay,sustain_level,release,delay
return '%s adsr %s,%s,%s,%s,%s' % t
#2. line
def line(**dic):
''' Trace a straight line between specified points.
sig_out
end_pts, [ia, ib] where ia is start value and ib is value after dur
dur, duration in seconds of segment '''
sig_out = dic.get('sig_out', '')
if sig_out == '':
print('We need sig_out for line')
sys.exit(-1)
end_pts = dic.get('end_pts', [])
if len(end_pts) != 2:
print('We need end_pts (2-len) for line')
sys.exit(-1)
dur = dic.get('dur', 1)
return '%s line %s,%s,%s' % (sig_out,end_pts[0],dur,end_pts[1])
#3. linen
def linen(**dic):
''' Applies a straight line rise and decay pattern to an input amp signal
sig_out, amp
rise, rise time in seconds. None, if <= 0.
dur, overall duration in seconds.
decay, decay time in seconds. Zero means no decay. '''
sig_out = dic.get('sig_out','')
if sig_out == '':
print('We need sig_out for linen')
sys.exit(-1)
amp = dic.get('amp', 1)
rise = dic.get('rise', '0.1*idur')
dur = dic.get('dur', 'idur')
decay = dic.get('decay', '0.1*idur')
return '%s linen %s,%s,%s,%s' % (sig_out,amp,rise,dur,decay)
#4. linseg
def linseg(**dic):
''' Trace a series of line segments between specified points
sig_out
pts, [ia,idur1,ib,idur2,ic] where ia is starting level, ib, ic are
..levels and idur1, idur2 are duration in seconds between levels.'''
sig_out = dic.get('sig_out', '')
if sig_out == '':
print('We need sig_out for linseg')
sys.exit(-1)
pts = dic.get('pts', [])
if len(pts) == 0:
print('We need pts for lineseg')
sys.exit(-1)
pts_str = [str(p) for p in pts]
return '%s linseg %s' % (sig_out,','.join(pts_str))
The audio for the output file is here.
No comments:
Post a Comment