The Csound Blog by Jacob Joaquin email jacobjoaquin@gmail.com web www.thumbuki.com/csound/blog (C)2006 Jacob Joaquin Licensed under Creative Commons (see below) 2006.12.27 Back in the ADSR One goal I have for these blogging explorations is to regularly refine my coding practices. Starting with today's entry, I'm enumerating my instruments with multiples of 10, a technique I'm borrowing from my Commodore 64 BASIC days. The reason being I'm designing instruments that feed information into one another. Events in Csound are processed from the lowest instrument to the highest, so the order matters. By spacing out instruments, extra headroom exists for inserting instruments later, without having to go through the trouble of re-labeling existing instruments and score events. At least, that's the working theory. More hands on experience is necessary before I know whether or not this will work in practice. 10 PRINT "@!#@! YOU" 20 GOTO 10 * A typical BASIC program, often found running on store computers in the 1980's. Every once in awhile, an opcode that's been sitting in the manual waiting to be discovered leaps from the screen and smacks me square in the face. Csound is full of surprises like that. For eight years, the schedule opcode has been completely ignored by yours truly. Much like me to the ladies in high school, it's as if it didn't exist. I must say, this is an opcode with near infinite potential. In today's example, I've utilized schedule to design a quirky little ADSR patch that is built using three instruments: instr 10, 20 and 30. Here's the run-down. instr 10 is instantiated in the score. instr 10 is responsible for the attack-decay-sustain portion of the envelope. The envelope stream is sent over a k-rate zak channel, chosen by user defined opcode ZakEnvAssign. instr 10 schedules two score events. The first is an instr 20 event, which begins at time p3, coinciding with the moment instr 10 finishes. This is the release portion of the envelope. The second schedule instantly instantiates instr 30. The duration is calculated by summing instr 10's p3 duration with the release time. instr 30 is the sound engine module and sends resulting audio to the Main Mixer, instr 200. Although this instrument is split into three, the composer only needs to worry about enacting it in the score with instr 10. The rest is automated. I'm utilizing one extra p-field in the score for demonstrating a varietal of release times. The nice thing about this designs handling of the release, that even if the original p3 duration of instr 10 is shorter than the time it takes to finish the attack and/or decay portion of the envelope, the release will still function properly, without clicks or pops, by using the final value of instr 10's envelope before entering the release stage. *breath* Another technique I'm exploring is using the opcode opcode to automate the distribution of zak channels. For every instance of instr 10, my user defined opcode ZakEnvAssign designates a k-rate zak channel. The mechanism used to choose the channel is a basic rotary switcher. When ZakEnvAssign is called, the envelope is assigned the zak channel stored in macro value ZKENVCURRENT. ZKENVCURRENT is then incremented by one. If ZKENVCURRENT is greater than ZKENVLAST, it is then set to ZKENVFIRST. Once again, the macro system has proven to be both a time saver and a wonderful way to manage the zak channels. And I was hoping this blog entry would be shorter than the last. Permalink http://www.thumbuki.com/20061227/back-in-the-adsr.html License (cc) Creative Commons Attribution-ShareAlike 2.5 You are free: * to Share -- to copy, distribute, display, and perform the work * to Remix -- to make derivative works Under the following conditions: * Attribution. You must attribute the work in the manner specified by the author or licensor. * Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. * For any reuse or distribution, you must make clear to others the license terms of this work. * Any of these conditions can be waived if you get permission from the copyright holder. http://creativecommons.org/licenses/by-sa/2.5/ sr = 44100 kr = 4410 ksmps = 10 nchnls = 1 ; instr 1 Initialize Settings ; instr 10 Release instr Part I Attack-Decay-Sustain, Schedule i20 & i30 ; instr 20 Release instr Part II Release Portion of Envelope ; instr 30 Release instr Part III The Sound Engine ; instr 200 Master Mixer ; instr 300 Zak Clear ; Master Volume #define VOLUME #5000# ; Zak Busses # define ZACHANNELS #1# # define ZKCHANNELS #30# zakinit $ZACHANNELS, $ZKCHANNELS ; k-rate zak channels # define ZKENVCURRENT #3# ; k-channels 3 through 7 reserved for ZakEnvAssign # define ZKENVFIRST #4# # define ZKENVLAST #28# ; a-rate zak channels # define ZMIXER #1# ; ---- opcode ZakEnvAssign ---- opcode ZakEnvAssign, i, 0 ; Assign a zak channel for envelope izak zir $ZKENVCURRENT ifoo init izak ; Select next zak envelope channel izak = izak + 1 if( izak <= $ZKENVLAST ) igoto continue izak = $ZKENVFIRST continue: ziw izak, $ZKENVCURRENT xout ifoo endop ; ---- Initialize Settings ---- instr 1 ziw $ZKENVFIRST, $ZKENVCURRENT endin ; ---- Release instr Part I ---- instr 10 ipch = cpspch ( p4 ) iattackT = 0.01 idecayT = 0.1 isustainV = 0.5 ireleaseT = p5 ienvT = p3 + ireleaseT ; Assign a zak envelope channel to this instance izkchannel ZakEnvAssign ; attack delay sustain portion of adsr kenv linseg 0, iattackT, 1, idecayT, isustainV, p3 - ( iattackT + idecayT ), isustainV zkw kenv, izkchannel ; release portion of adsr schedule 20, p3, ireleaseT, izkchannel ; the audio porion of voice schedule 30, 0, ienvT, izkchannel, ipch endin ; ---- Release instr Part II ---- instr 20 izak = p4 ival zir izak kenv line ival, p3, 0 zkw kenv, izak endin ; ---- Release instr Part III ---- instr 30 idur = p3 izak = p4 ipch = p5 kenv zkr izak ivib random 3, 6 kenv2 linseg 2, idur * 0.2, 6, idur * 0.8, ivib kenv3 expon 0.001, idur, 0.1 klfo oscil 1, kenv2, 1, -1 aosc vco kenv, ipch, 3, 0.1 aosc2 vco kenv, ipch + ipch * klfo * kenv3, 3, 0.7 amix = aosc + aosc2 zawm amix, $ZMIXER endin ; ---- Master Mixer ---- instr 200 ain zar $ZMIXER out ain * $VOLUME endin ; ---- Zak Clear ---- instr 300 zacl 0, $ZACHANNELS ; zkcl 0, $ZKCHANNELS ; Clearing the k-channels breaks the envelopes endin f1 0 8192 10 1 t 0 122 i1 0 0 i200 0 30 i300 0 30 i10 0 0.01 8.09 0.01 i10 0.33 . 8.05 . i10 0.66 . 8.02 . i10 1 . 8.09 < i10 1.33 . 8.05 . i10 1.66 . 8.02 . i10 2 . 8.09 . i10 2.33 . 8.05 . i10 2.66 . 8.02 . i10 3 . 8.09 . i10 3.33 . 8.05 . i10 3.66 . 8.02 . i10 4 0.33 8.10 . i10 4.33 . 8.05 . i10 4.66 . 8.02 . i10 5 . 8.10 . i10 5.33 . 8.05 . i10 5.66 . 8.02 . i10 6 . 8.10 . i10 6.33 . 8.05 . i10 6.66 . 8.02 . i10 7 . 8.10 . i10 7.33 . 8.05 . i10 7.66 . 8.02 . i10 8 . 8.11 0.8 i10 8.33 . 8.05 . i10 8.66 . 8.02 . i10 9 . 8.11 . i10 9.33 . 8.05 . i10 9.66 . 8.02 . i10 10 . 8.11 . i10 10.33 . 8.05 . i10 10.66 . 8.02 . i10 11 . 8.11 . i10 11.33 . 8.05 . i10 11.66 . 8.02 . i10 12 . 8.10 . i10 12.33 . 8.05 . i10 12.66 . 8.02 . i10 13 . 8.10 . i10 13.33 . 8.05 . i10 13.66 . 8.02 . i10 14 . 8.10 < i10 14.33 . 8.05 . i10 14.66 . 8.02 . i10 15 . 8.05 . i10 15.33 . 8.10 . i10 15.66 . 9.02 . i10 16.012 4 9.02 2.6 i10 16.005 . 8.05 . i10 16.01 . 8.09 . i10 16 5 6.02 . i10 16.008 4 7.02 . e