The Csound Blog by Jacob Joaquin email jacobjoaquin@gmail.com web http://www.thumbuki.com/csound/blog/ (C)2008 Jacob Joaquin Licensed under Creative Commons (see below) 2008.01.26 SineBox Today's blog is on SineBox: a "music box" like instrument that plays itself. Once a user starts SineBox with a single i-event in the score, SineBox creates instances of itself, generating multiple sine tones over time. This may not be the most musical piece of Csound technology ever conceived of. It can, however, be molded to fit a wide range of uses, musical and otherwise. Using SineBox in the Score The instrument SineBox was created for demonstration purposes. Thus, it has been stripped down to only the bare essentials. Most characteristics, such as random pitches and start times, have been hard wired directly into the instrument. This leaves the instrument with the standard three required p-fields plus two additional user defined p-fields. P-field 4 is used for amplitude, and p-field 5 is the total number of notes to play. The following is the line of code from the score: i "SineBox" 0 2 0.125 200 Figure 1. This single score event starts SineBox. Since p-field 5 contains the value 200, it will generate 200 notes. How it Works There are three primary components that makeup the self-playing mechanism: a p-field, the if conditional and the schedule opcode. P-field 5 accepts the initial number of notes to play, specified by the user, and stored in the i-rate variable inotesLeft. The if conditional checks inotesLeft to see how many notes are left to be generated. If inotesLeft has a value greater than one, the schedule opcode is used to create a new instance of SineBox. When the next SineBox instance is scheduled, inotesLeft is decremented by 1. This cycle will repeat, generating new sine tones until there are none left to play. schedule p1, istartNext, idurNext, iamp, inotesLeft - 1 Figure 2. inotesLeft is decremented by 1 when scheduled. Other data is also passed to the next instance, including randomized start and duration times. The original value of iamp is passed through unchanged. And the value of p1 is the instrument number of Sinebox. Watch out! One detail that is worth mentioning is the fact that sometimes Csound will stop before all the notes are played. This happens, I think, because Csound doesn't recognize any scheduled events in the queue. So if there is a break in Csound instrument processes, it ends. This can be avoided using the "e" score statement. Though since SineBox start times are random, it's nearly impossible to calculate when the actual end time will be. A good guess would be: ( istartMax - istartMin ) / 2 * [p5 in score] + idurMax Figure 3. A good guess on how long SineBox will play Until next time, Jake Permalink http://www.thumbuki.com/20080126/sinebox.html License (cc) Creative Commons Attribution-Noncommercial 3.0 Unported You are free: * to Share -- to copy, distribute and transmit the work * to Remix -- to adapt the work Under the following conditions: * Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). * Noncommercial. You may not use this work for commercial purposes. * For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page. * Any of the above conditions can be waived if you get permission from the copyright holder. * Nothing in this license impairs or restricts the author's moral rights. http://creativecommons.org/licenses/by-nc/3.0/ sr = 44100 kr = 4410 ksmps = 10 nchnls = 2 instr SineBox idur = p3 ; Duration iamp = p4 ; Amp scale inotesLeft = p5 ; Number of notes left to generate ; Hard-wired SineBox characteristics ibasePch = cpspch( 6.10 ) ; Base pitch irange = 37 ; Range of random pitches iattack = 0.001 ; Attack time of envelope idurMin = 2 ; Minimum duration for next note idurMax = 6 ; Maximum duration for next note istartMin = 0.01 ; Minimum start time for next note istartMax = 1 ; Maximum start time for next note ; Pick a random equal tempered note ipch = ibasePch * ( 2 ^ ( ( int( rnd( irange ) ) ) / 12 ) ) ; Random pan position for the sine tone ipan = rnd( 1 ) ; Amplitude enveloped sine tone aenv linseg 0, idur * iattack, iamp * 0dbfs, idur * ( 1 - iattack ), 0 aosc oscil3 aenv, ipch, 1 ; Output audio outs aosc * sqrt( 1 - ipan ), aosc * sqrt( ipan ) ; Schedule a sine tone if there are notes left to be played if ( inotesLeft <= 1 ) igoto bypassScheduler ; Select start time and duration of next note randomly, with constraints istartNext = rnd( istartMax - istartMin ) + istartMin idurNext = rnd( idurMax - idurMin ) + idurMin ; Schedule the next sine tone schedule p1, istartNext, idurNext, iamp, inotesLeft - 1 ; Print number of notes left to the output window printf_i "%d notes left\n", 1, inotesLeft - 1 bypassScheduler: endin ; High resolution sine table f 1 0 [2^16+1] 10 1 ; Start Sine Box i "SineBox" 0 2 0.125 200 e 105