From: owner-sc-users-digest@lists.io.com (sc-users-digest) To: sc-users-digest@lists.io.com Subject: sc-users-digest V1 #48 Reply-To: sc-users Sender: owner-sc-users-digest@lists.io.com Errors-To: owner-sc-users-digest@lists.io.com Precedence: bulk sc-users-digest Wednesday, June 30 1999 Volume 01 : Number 048 ---------------------------------------------------------------------- Date: Mon, 28 Jun 1999 11:14:37 +0200 From: Staffan Liljegren <---@---.---> Subject: Pattern question? All, I tried out patterns a bit and wanted to change the last note in a parallel pattern with bass and melody and I could do it randomly with ( // Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4),\midinote, Pseq([\rest, 63,64,67,Prand(#[71,72,73,72],1)],4)) ]).play(Event.protoEvent) ) But how can I get the last note to change sequentially through the melody cycle , ie 63,64,67,71 63,64,67,72 63,64,67,73 63,64,67,72 I tried using Pser, but it restarts on each new cycle. I assume there is a simple solution to this but right now I just can't see through this . - -Staffan ------------------------------ Date: Mon, 28 Jun 1999 11:15:37 +0200 From: "Iannis Zannos" <---@---.---> Subject: MixerPlayer: Increasing overhead when copying Pattern-Instruments Dear James, please have a look at this, as at present it is not practical to start processes involving Patterns (Pbind) in MixerPlayer because of a strange accumulation of UGen processes at startup of each copied pattern process. The problem also occurs with copying the Demo process. On a weak machine (PPC 604, 150MHz) it may occasionally crash the demo process after just one copy. I tested this with a freshly unpacked SC 2.1.5 installation. Test code provided below. - ---- Abstract When repeatedly making a copy of an instrument involving a pattern (Pbind), using the copy button on instrument mixer, there will be more ugens created at start time for each successive copy of that instrument than required for the previous copy. This will lead to overload if the copy process is repeated many times. Details: Strange successive cumulations of UGens at start occurs, when starting following instrument with MixerPlayer (default) and then copying it repeatedly with the Copy button of MixerPlayer: Instrument(\test, Pbind.new.asUGenFunc(Event.protoEvent, 1)).play When started alone on the mixer player, the number of UGens will oscillate between 13 and 16. When clicking on the "Copy" button, the number of UGens will temporarily rise to a much higher number before dropping back to oscillate between 22 and 28 If one copies the process with the copy button, then stops the copy with the kill check-box, and makes a new copy again with the copy button, each time more UGens will be created in the beginning of the new copy. On a 266 MHZ G3, after ca 20 repetitions the overload will become audible as jitter. The problem becomes acute when starting a pattern which requires more ugens. For example, when playing a 6 note chord pattern like this: Instrument(\test, Pbind(\degree, #[-10, -3, -1, 1, 3, 5]) .asUGenFunc(Event.protoEvent, 1)).play Then overload will be audible (jitter) even within the very first 1-5 copies. Sometimes even the first copy may cause SC to report "error. out of ugen space". This also happens with any Ugen func bound with Pbind.: Instrument(\test, Pbind ( \ugenFunc, { arg synth, dur; FSinOsc.ar(400, Line.ar(0.1, 0, dur)) } ).asUGenFunc(Event.protoEvent, 1)).play ================================================= An instrument without a pattern does not show this problematic behavior. Tested with: Instrument.new(\sines, { var out; out = FSinOsc.ar(200.0.rrand(4000), 0.01); 20.do({ out = out + FSinOsc.ar(200.0.rrand(4000), 0.01) }); out }).play ====================== Running the default demo of SC will also show this overload problem. I counted ca. 15 copies of the demo process before permanent overload-jitter occured. (while running always at most 2 demo processes in parallel). I also tried to check whether the overload is due to copying of the MixerVoice in MixerPlayer by subclassing MixerPlayer and changing its playFunc process as follows: // For testing the starting of multiple // patterns (of same kind). PatternMixerPlayer : MixerPlayer { *playFunc { arg input; ^{ arg synth; var outs; outs = TSpawn.ar({ arg argTSpawn, i, tsynth, argInput; Pause.ar({ argInput.value(tsynth) }, MouseX.kr(0.0, 1.0) ) }, numChannels); tspawn = outs.source; synth.sched(0, { tspawn.trigger(input) }); outs } } } Testcode: w = GUIWindow.new(\test); b = ButtonView.new(w, Rect.newBy(10, 10, 200, 20), \trigger_pattern); b.action_({ arg me; if ( me.model.isNil, { me.model = PatternMixerPlayer.new; Synth.play(PatternMixerPlayer.playFunc({ FSinOsc.ar(200, 0.1) })); }); PatternMixerPlayer.tspawn.trigger( Pbind.new.asUGenFunc(Event.protoEvent, 1) )}); The problem persists also with this version. Regards, Iannis Z. ------------------------------ Date: Mon, 28 Jun 1999 05:02:01 -0600 From: James McCartney <---@---.---> Subject: Re: subclassing Orchestra error At 3:59 PM -0600 6/26/99, crucial wrote: >I tried to subclass Orchestra but got > >Cannot find superclass 'Orchestra' for class 'Orc' > >I could subclass : > >Object, Collection > > >I could not subclass : > > >Set, IdentitySet, Orchestra, Dictionary, IdentityDictionary > > > >Orchestra and Instruments are working just fine actually. This happens because these classes have other classes in their .sc files. Separate the classes into separate files. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 10:23:03 -0600 From: James McCartney <---@---.---> Subject: Re: MixerPlayer: Increasing overhead when copying Pattern-Instruments OK I found this one. The fix will be in the next release. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 10:57:04 -0600 From: James McCartney <---@---.---> Subject: Re: Pattern question? Here's the trivial way: ( a = Pseq([ \rest, 63, 64, 67 ]); Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4),\midinote, Pseq([a, 71, a, 72, a, 73, a, 72] )) ]).play(Event.protoEvent) ) Here's a more interesting way: Add this class to ListPatterns.sc: Place : Pseq { asStream { ^Routine.new({ arg inval; var item, offsetValue; offsetValue = offset.value; if (inval.eventAt('reverse') == true, { repeats.value.do({ arg j; list.size.reverseDo({ arg i; item = list @@ (i + offsetValue); if (item.isKindOf(Array), { item = item @@ j; }); inval = item.embedInStream(inval); }); }); },{ repeats.value.do({ arg j; list.size.do({ arg i; item = list @@ (i + offsetValue); if (item.isKindOf(Array), { item = item @@ j; }); inval = item.embedInStream(inval); }); }); }); }); } } Then you can write : ( // Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), \midinote, Place(#[ \rest, 63, 64, 67, [71,72,73,72] ], 4)) ]).play(Event.protoEvent) ) --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: < ------------------------------ Date: Mon, 28 Jun 1999 11:58:40 -0600 From: James McCartney <---@---.---> Subject: Re: Pattern question? Also I should point out that you can use a Routine to generate any sequence of values algorithmically. ( // Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), \midinote, Prout({ 4.do({ arg i; \rest.yield; 63.yield; 64.yield; 67.yield; #[71,72,73,72].at(i).yield; }); }) ) ]).play(Event.protoEvent) ) --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: < ------------------------------ Date: Mon, 28 Jun 1999 19:24:36 +0200 From: Staffan Liljegren <---@---.---> Subject: Re: Pattern question? Thanks James, I'll go for the trivial one, although I liked the "lace" variant. But it might be confusing to have two semantics for lists in Patterns, ie lists for both laced values and chords. If its in a Pseq, play it as a chord, if it's in a Place , lace them... - -Staffan James McCartney wrote: > Here's the trivial way: > > ( > a = Pseq([ \rest, 63, 64, 67 ]); > > Ppar([ > // bass > Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), > // melody > Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4),\midinote, > Pseq([a, 71, a, 72, a, 73, a, 72] )) > ]).play(Event.protoEvent) > ) > > Here's a more interesting way: > Add this class to ListPatterns.sc: > > Place : Pseq { > asStream { > ^Routine.new({ arg inval; > var item, offsetValue; > > offsetValue = offset.value; > if (inval.eventAt('reverse') == true, { > repeats.value.do({ arg j; > list.size.reverseDo({ arg i; > item = list @@ (i + offsetValue); > if (item.isKindOf(Array), { > item = item @@ j; > }); > inval = item.embedInStream(inval); > }); > }); > },{ > repeats.value.do({ arg j; > list.size.do({ arg i; > item = list @@ (i + offsetValue); > if (item.isKindOf(Array), { > item = item @@ j; > }); > inval = item.embedInStream(inval); > }); > }); > }); > }); > } > } > > Then you can write : > > ( > // > Ppar([ > // bass > Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), > // melody > Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), > \midinote, Place(#[ \rest, 63, 64, 67, [71,72,73,72] ], 4)) > ]).play(Event.protoEvent) > ) > > --- james mccartney james@audiosynth.com http://www.audiosynth.com > If you have a PowerMac check out SuperCollider2, a real time synth program: > ------------------------------ Date: Mon, 28 Jun 1999 12:52:51 -0600 From: James McCartney <---@---.---> Subject: Re: Pattern question? At 11:24 AM -0600 6/28/99, Staffan Liljegren wrote: >Thanks James, > >I'll go for the trivial one, although I liked the "lace" variant. But >it might be confusing to have two semantics for lists in Patterns, >ie lists for both laced values and chords. If its in a Pseq, play it as >a chord, if it's in a Place , lace them... If you want to play a chord in a Place then you would write [[chord]] --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 20:27:56 -0600 From: James McCartney <---@---.---> Subject: Re: PrndGated At 3:57 PM -0600 6/26/99, crucial wrote: >Also of possible interest to y'all : > >This plays the list as does Pseq. >On each event, if gate evaluates to true, >the function filter is valued, passed the inval, >and the result placed at that point in the list. > >PseqLooper : Pseq { > var <>gate,<>filter; > > *new { arg list, filter, gate,repeats=1, offset=0; > ^super.new(list, repeats).offset_(offset).filter_(filter).gate_(gate) > } > asStream { > ^Routine.new({ arg inval; > var item, offsetValue; > > offsetValue = offset.value; > repeats.value.do({ arg j; > list.size.do({ arg i; > var iv; > iv=i + offsetValue; > item = list @@ (iv); You should make a local copy of the list in your asStream function or else you will be altering the list for all streams instantiated from that pattern. asStream { ^Routine.new({ arg inval; var item, offsetValue, localList; offsetValue = offset.value; localList = list.copy; repeats.value.do({ arg j; localList.size.do({ arg i; var iv; iv=i + offsetValue; item = localList @@ (iv); if(gate.value(item,iv),{ item = filter.value(item,iv); localList.wrapPut(iv,item); }); inval = item.embedInStream(inval); }); }); }); } } --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 20:29:07 -0600 From: James McCartney <---@---.---> Subject: Re: the gc crash At 3:57 PM -0600 6/26/99, crucial wrote: >There's this one that happens once every week or so : > > >gc->numGrey 1, but none found >set 0 black list obj color wrong 127 (2, 1, 0) 32F632C Ive not seen this. If you notice what you do that leads to this, tell me. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 20:35:41 -0600 From: James McCartney <---@---.---> Subject: [fwd] Re: Pattern question? From: Ioannis Zannos <---@---.---> Staffan Liljegren wrote: > All, > > I tried out patterns a bit and wanted to change the last note in a parallel pattern with > bass and melody and I could do it randomly with . [...] > > But how can I get the last note to change sequentially through the melody cycle , ie > > 63,64,67,71 > 63,64,67,72 > 63,64,67,73 > 63,64,67,72 > > I tried using Pser, but it restarts on each new cycle. I assume there is a simple solution > to this but right now I just can't see through this . > > -Staffan This is not a trivial question: It means nesting a pattern in another pattern where the enclosed pattern moves at a "deeper level" of repetitions than the enclosing pattern. I can think of two solutions: 1. Evaluating a stream possibly created outside the bindings within a Pfunc. 2. Using a special kind of pattern which may manipulate the data of another pattern or even totally exchange the pattern returned at the beginning of each repetition. Solution 1 is rather straightforward. Solution 2 is more subtle, because it involves a very short but powerful pattern definition which is rather nice if one likes recursive, "fractal" like structures. (-> incrementally changing data between repetiions .... ) Note that both solutions presented here require compilation of new pattern classes, albeit very small ones. Details below. Hope it is not too long an email. Iannis - ---------- Solution 1. Evaluating a stream in Pfunc. 1a. Macro class for repeating (just syntactic sugar saving one from having to write Pseq([....]) Repeat { *new { arg aPattern, times; ^Pseq([aPattern], times ? inf) } } 1b. Making a macro-pattern by using a stream inside a Pfuncn. ( //variable outside the environment for "deeper pattern": var superpattern; superpattern = Repeat(Pseq(#[71,72,73,72],1)).asStream; // Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), \midinote, Pseq([\rest, 63,64,67, Pfuncn( { superpattern.next },1) ],4)) ]).play(Event.protoEvent) ) 1c. Trick just for fun: Adding some emphasis by writing directly into a key of the current event: ( //variable outside the environment for "deeper pattern": var superpattern; superpattern = Repeat(Pseq(#[71,72,73,72],1)).asStream; // Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), \midinote, Pseq([\rest, 63,64, // this is needed for the input to pfunc to be the event... Repeat(67, 1), Pfuncn( { arg inval; inval.put(\amp, 0.5); inval.put(\legato, 0.1); superpattern.next },1) ],4)) ]).play(Event.protoEvent) ) Solution 2. Using a stream like pattern Pstream. 2a. Pstream class. 'stream' because it produces a new kind of stream (i.e. new value) each time it is repeated. Pstream : Pattern { var <>initFunc, <>initPat; *new { arg initFunc, initPat; ^super.new.initFunc_(initFunc).initPat_(initPat); } asStream { ^initFunc.value(initPat, this).asStream; } } 2b. The solution using Pstream. Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), \midinote, Repeat(Pstream({ arg stream; Pseq([\rest, 63,64,67,stream.next])}, Pseq(#[71,72,73,72]).asStream ), 4) ) ]).play(Event.protoEvent) 2c. Some examples showing use of Pstream. (// Reversing a sequence: Pbind(\dur, 0.1, \legato, 0.3, \degree, Repeat(Pstream({ arg pat, me; me.initPat = pat.reverse; Pseq(pat); }, #[1, 2, 5, 4]), 5)).play ) (// "Growing" a pattern's list recursively var palin; palin = Pstream({ arg pat, me; me.initPat = pat.add(pat.last + 1); Pseq(pat); }, #[0]); Pbind(\dur, 0.08, \legato, 0.3, \degree, Repeat(palin, 10)).play ) (// Pattern reversing, recursively growing, and adding to itself // Toccata like. var palin; palin = Pstream({ arg pat, me; me.initPat = (pat - 1).reverse.add(pat.last + 1); Pseq(pat, 1); }, #[30]); Pbind(\dur, 0.06, \legato, 0.3, \midinote, Repeat(Pstep2add(palin, palin), 20)).play ) (// Pattern getting strangely static ... var palin; palin = Pstream({ arg pat, me; me.initPat = -1 * pat.reverse.add(pat.last + 2); Pseq(pat); }, #[1, 0, -2]); Pbind(\dur, 0.08, \legato, 0.3, \degree, Repeat(Pstep2add(palin, palin), 10)).play ) (// Pattern getting strangely static 2... var palin; palin = Pstream({ arg pat, me; me.initPat = -1 * pat.reverse.add(pat.last + 2); Pseq(pat); }, #[1, 0, -1]); Pbind(\dur, 0.08, \legato, 1.3, \degree, Repeat(Pstep2add(palin, palin), 10)).play ) (// An overly diligent (mandolin?) student var palin; palin = Pinit({ arg pat, me; me.initPat = pat ++ (pat + 1); Pseq([pat]); }, Pseq(#[0])); Pbind(\dur, 0.08, \legato, 0.3, \degree, Repeat(palin, 20)).play(channels: 1) ) (// The same student, 2 hours later var palin; palin = Pinit({ arg pat, me; pat.list = pat.list.reverse; me.initPat = pat ++ (pat + 1); Pseq([pat]); }, Pseq(#[0])); Pbind(\dur, 0.08, \legato, 0.3, \degree, Repeat(palin, 20)).play(channels: 1) ) (// OOOhhh, the student is getting creative! var palin; palin = Pinit({ arg pat, me; me.initPat = pat ++ (pat + [-2 -1, 0, 1, 1].choose); Pseq([pat]); }, Pseq(#[0])); Pbind(\dur, 0.08, \legato, 0.3, \degree, Repeat(palin, 20)).play(channels: 1) ) ------------------------------ Date: Mon, 28 Jun 1999 20:36:11 -0600 From: James McCartney <---@---.---> Subject: [fwd] Re: Simple pop-up widget From: Ioannis Zannos <---@---.---> andreas pieper wrote: > > ps i think the test routine has a little typo: > .. 'Instrument'], { arg s; me.label = "Select a Class. (Current:)" + s } > should be "++ s" at the end, otherwise this would cause an error on my > system. ++ is correct. There is a typo in the code of String class, which I have pointed out to this list about 3 times now. You have to replace the message "primCat" with "prCat" in method ++. Then it works. IZ. ------------------------------ Date: Mon, 28 Jun 1999 22:25:48 -0400 From: "crucial" <---@---.---> Subject: Re: subclassing Orchestra error James : ouch ! take a holiday mate ! Or do a Stephan Hawkins, just sit there and ruminate. good luck. meanwhile, back in gotham... Yes, I did now suss the matter. this explains it more fully for anyone else : So I now guess the rule is you can only subclass one class per .sc file unless the subclassed class is on that same file. right ? eg: Today I tried a file in my DefaultLibrary called Plib.sc Plib : Orchestra { } This compiled fine. Then I tried adding in : Plib : Orchestra { } Orc : Orchestra { } Instr : Instrument { } into this Plib.sc (in my attempts to pervert SC into a slanguage). and then I get : compiling class library.. NumPrimitives = 401 pass 1 done Ä ERROR: Cannot find superclass 'Orchestra' for class 'Plib' in file 'Macintosh HD:Desktop Folder:super collider:DefaultLibrary:Plib.sc' line 5 char 0 : ÄPlib : Orchestra { - ----------------------------------- Ä ERROR: Cannot find superclass 'Orchestra' for class 'Orc' in file 'Macintosh HD:Desktop Folder:super collider:DefaultLibrary:Plib.sc' line 13 char 15 : Orc : OrchestraÄ { } - ----------------------------------- >I tried to subclass Orchestra but got > >Cannot find superclass 'Orchestra' for class 'Orc' > >I could subclass : > >Object, Collection > > >I could not subclass : > > >Set, IdentitySet, Orchestra, Dictionary, IdentityDictionary > > > >Orchestra and Instruments are working just fine actually. > >__________________________________________ :\\_______ > http://crucial-systems.com > >__________________________________________ :\\_______ > __________________________________________ :\\_______ http://crucial-systems.com __________________________________________ :\\_______ ------------------------------ Date: Mon, 28 Jun 1999 21:04:43 -0600 From: James McCartney <---@---.---> Subject: Re: [fwd] Re: Pattern question? >(// OOOhhh, the student is getting creative! >var palin; >palin = Pinit({ arg pat, me; > me.initPat = pat ++ (pat + [-2 -1, 0, 1, 1].choose); ^ you need a comma here, else you have -2-1 == -3 --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 21:58:47 -0600 From: James McCartney <---@---.---> Subject: Re: subclassing Orchestra error At 8:25 PM -0600 6/28/99, crucial wrote: >So I now guess the rule is you can only subclass one class per >.sc file unless the subclassed class is on that same file. > >right ? That is part of it. The other problem is that SC can't figure out what order to compile the files in because there are files (like MixerPlayer.sc) that have superclasses for multiple unrelated branches. I should separate these out. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 21:59:32 -0600 From: James McCartney <---@---.---> Subject: Re: subclassing Orchestra error At 8:25 PM -0600 6/28/99, crucial wrote: >James : > > >ouch ! take a holiday mate ! That *was* my holiday.. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 20:32:57 -0600 From: James McCartney <---@---.---> Subject: Re: choices based on midi values At 3:30 AM -0600 6/25/99, garrett james wrote: >Hi, > >I know the following is not right, but what is a method to imitate this >type of functionality? I have many uses for different Midi slider messages >that can be interpreted... > >I guess what Im asking, is how can one consistantly poll the current value >of a *.kr type function and act on that value, use a little logic... > >if (MIDIController.kr(16,23,0,2).value < 1.0, >{MIDIController.kr(16,23,0,1)},{1.0}); > >(This example/idea would ideally control would go up at 1:1, then >completely flat not increasing at all for the second half of the slider's >movement...) You can use either a sched task or Sequncer to poll a value and execute code, but what you are doing above is trivial : min( MIDIController.kr(16,23,0,2), 1.0) ) --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Mon, 28 Jun 1999 22:08:44 -0600 From: James McCartney <---@---.---> Subject: Re: [fwd] Re: Pattern question? >From: Ioannis Zannos <<---@---.---> >(// OOOhhh, the student is getting creative! >var palin; >palin = Pinit({ arg pat, me; > me.initPat = pat ++ (pat + [-2 -1, 0, 1, 1].choose); > Pseq([pat]); }, Pseq(#[0])); >Pbind(\dur, 0.08, \legato, 0.3, > \degree, Repeat(palin, 20)).play(channels: 1) >) One problem with Pstream is that it modifies the pattern's instance variables which is not a good thing because then you cannot create multiple independant instances of the pattern. If you did they would all be modifying the same data. Here is a Prout that does the same as the above, but only modifies data local to the routine so it can be used in multiple streams, for example in a Ppar. (The embedInStream method will make a pattern yield all its values.) Pbind( \dur, 0.08, \legato, 0.3, \degree, Prout({ arg inval; var pat; pat = Pseq(#[0]); 20.do({ inval = pat.embedInStream(inval); pat = pat ++ (pat + [-2, -1, 0, 1, 2].choose); }); }) ).play(channels: 1) --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: < ------------------------------ Date: Tue, 29 Jun 1999 11:45:00 +0800 From: Mark Ballora <---@---.---> Subject: Re: Pattern question? >Also I should point out that you can use a Routine to generate any sequence >of values algorithmically. I'd thought of Routines when I tried (without success) to get Staffan's patch to work. I tried things like the following: ( var endNote; endNote=Prout.new({ 71.yield; 72.yield; 73.yield; 72.yield; }); b=endNote.asStream; // Ppar([ // bass Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), // melody Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), \midinote, Pseq([\rest, 63, 64, 67, b.next ],4)) ]).play(Event.protoEvent) ) ... which simply produces note 71 each time. I can see why your code below works, but am not clear why mine does not. Am I missing something obvious? In the docs, I see you've used Routines with a) a Sequencer and b) as a collection iterated with the .do method (as below). Are these the correct ways to use Routines? > > >( >// > Ppar([ > // bass > Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), > // melody > Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), > \midinote, > Prout({ > 4.do({ arg i; > \rest.yield; > 63.yield; > 64.yield; > 67.yield; > #[71,72,73,72].at(i).yield; > }); > }) > ) > ]).play(Event.protoEvent) >) > ------------------------------ Date: Mon, 28 Jun 1999 22:56:37 -0600 From: James McCartney <---@---.---> Subject: Re: Pattern question? At 9:45 PM -0600 6/28/99, Mark Ballora wrote: >>Also I should point out that you can use a Routine to generate any sequence >>of values algorithmically. > >I'd thought of Routines when I tried (without success) to get Staffan's >patch to work. I tried things like the following: > >( var endNote; >endNote=Prout.new({ 71.yield; 72.yield; 73.yield; 72.yield; }); >b=endNote.asStream; >// > Ppar([ > // bass > Pbind( \dur, 4, \midinote, Pseq(#[40], 4)), > // melody > Pbind( \dur, Pseq(#[0.5,0.5,0.5,0.5,2],4), > \midinote, Pseq([\rest, 63, 64, 67, b.next ],4)) > ]).play(Event.protoEvent) >) > >... which simply produces note 71 each time. >I can see why your code below works, but am not clear why mine does not. >Am I missing something obvious? b.next returns a single value once when the list is made and so that pattern returns that value from then on. Look at this: ( var endNote; endNote=Prout.new({ 71.yield; 72.yield; 73.yield; 72.yield; }); b=endNote.asStream; [\rest, 63, 64, 67, b.next ].postln; ) That list is what the pattern is getting as an argument so of course it will always give 71. > >In the docs, I see you've used Routines with a) a Sequencer and b) as a >collection iterated with the .do method (as below). Are these the correct >ways to use Routines? You can use a Routine any way you see fit. Whenever you want something like a stream but with some algorithm that needs to preserve state between calls, a Routine may be the right thing. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: < ------------------------------ Date: Tue, 29 Jun 1999 11:27:22 +0200 From: Staffan Liljegren <---@---.---> Subject: Re: Pattern question? All, Thanks for all the replies to my last question, it was stimulating ! Here is a new one. If I try to access/printing Synth.blockSize in one of Your Pattern Part 4 examples it fails (error code attached last). I have only introduced one line , synth.blockSize.postln; Why ? - -Staffan ( var a, b, c, pattern, stream; a = { arg synth, freq, amp, pan; Pan2.ar(SinOsc.ar(freq), pan, amp); }; b = { arg synth, amp, pan, freq; Pan2.ar(RLPF.ar(Saw.ar(freq), freq * 6, 0.1), pan, amp); }; c = { arg synth, pan, freq, amp; Pan2.ar(Resonz.ar(GrayNoise.ar, freq * 4, 0.04), pan, amp * 8); }; pattern = Pbind( \freq, Pseq([100, 150, 200, 225, 250, 275, 300, 350, 400], inf), \amp, 0.1, \pan, Pfunc({ 1.0.rand2 }), \instr, Prand([ Pseq([a],3), Pseq([b],3), Pseq([c],3) ], inf) ); stream = pattern.asEventStream(Event.new); Synth.scope({ var out; out = OverlapTexture.ar({ arg synth; var event; event = stream.next; event.use({ ~instr.valueEnvir(synth); synth.blockSize.postln; }); }, 1, 0.2, 2, 2); CombN.ar(out, 0.2, 0.2, 3, 1, out); }, 0.04); ) - --------------------------------- Error Code ------------------------------------- ERROR: Message 'blockSize' not understood. RECEIVER: Instance of Spawn ''{ (094CFE84, gc=02, fmt=00, flg=00, set=06) instance variables [16] synth : instance of Synth (094C79DC, size=0, set=06) inputs : instance of Array (094D991C, size=2, set=01) rate : Symbol 'audio' state : Integer 2 channels : instance of Array (094DA56C, size=2, set=01) newEventFunction : instance of Function (094C862C, size=0, set=01) nextTime : Float 0.7 3FE66666 66666666 nextTimeValue : nil defaultNextTime : Float 0.7 3FE66666 66666666 maxRepeats : nil numRepeats : Integer 0 runningSynths : instance of Array (094D4944, size=0, set=04) recentSynth : nil maxVoices : nil stop : false envir : instance of Environment (094C0FD4, size=0, set=01) } ARGS: Instance of Array { (08F9BBA8, gc=80, fmt=01, flg=81, set=00) } CALL STACK: Object : doesNotUnderstand arg this = arg selector = 'blockSize' arg args = [*0] (no arguments or variables) Environment : use arg this = arg function = var result = nil var saveEnvir = arg synth = var event = arg spawn = arg i = 0 arg synth = arg synth = Meta_Synth : new arg this = arg ugenGraphFunc = Spawn : getNewEvent arg this = var newSynth = nil ... ------------------------------ Date: Tue, 29 Jun 1999 06:06:52 -0600 From: James McCartney <---@---.---> Subject: Re: Pattern question? At 3:27 AM -0600 6/29/99, Staffan Liljegren wrote: >All, > >Thanks for all the replies to my last question, it was stimulating ! > >Here is a new one. >If I try to access/printing Synth.blockSize in one of Your Pattern >Part 4 examples it fails (error code attached last). > >I have only introduced one line , synth.blockSize.postln; > >Why ? > > out = OverlapTexture.ar({ arg synth; should be : out = OverlapTexture.ar({ arg spawn, i, synth; --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Tue, 29 Jun 1999 20:04:06 +0800 From: Mark Ballora <---@---.---> Subject: Re: Pattern question? >At 3:27 AM -0600 6/29/99, Staffan Liljegren wrote: >>I have only introduced one line , synth.blockSize.postln; >> >>Why ? >> > >> out = OverlapTexture.ar({ arg synth; > >should be : > >out = OverlapTexture.ar({ arg spawn, i, synth; > > I got the same error even after making this change. M ------------------------------ Date: Tue, 29 Jun 1999 09:32:39 -0600 From: James McCartney <---@---.---> Subject: version 2.1.6 available Version 2.1.6 is now available via ftp: BinHex : ftp://www.audiosynth.com/pub/updates/SC2.1.6.sea.hqx MacBinary (smaller) : ftp://www.audiosynth.com/pub/updates/SC2.1.6.sea.bin Changes in Version 2.1.6 There was a scheduling bug in Spawn. There was a bug that caused ControlIn not to be compatible with Plug. Compander had a bug that could cause its Synth to stop prematurely if spawned. An unterminated single quote Symbol literal would crash the parser. There was a typo in String ++. Instruments are no longer passed synth as the first argument so that they can be used as UGens. The current synth can be accessed via Synth.newSynth. (You might also try MIDIOut, I've not tested it yet, but I fixed a bug in it.) --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: < ------------------------------ Date: Tue, 29 Jun 1999 19:15:54 -0400 From: "crucial" <---@---.---> Subject: Re: version 2.1.6 available >(You might also try MIDIOut, I've not tested it yet, >but I fixed a bug in it.) > > > --- james mccartney Is it time for me to try reading sound file headers in a thread ? Or should I just wait a while ? __________________________________________ :\\_______ http://crucial-systems.com __________________________________________ :\\_______ ------------------------------ Date: Tue, 29 Jun 1999 20:18:42 -0600 From: James McCartney <---@---.---> Subject: Re: version 2.1.6 available At 5:15 PM -0600 6/29/99, crucial wrote: >>(You might also try MIDIOut, I've not tested it yet, >>but I fixed a bug in it.) >> >> >> --- james mccartney > > >Is it time for me to try reading sound file headers >in a thread ? no. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ Date: Wed, 30 Jun 1999 18:57:10 +0800 From: Mark Ballora <---@---.---> Subject: Re: Streams-Events-Patterns >One thing: Pseq, Prand, etc are not necessarily value patterns. >They can be either depending on what they return. So I misunderstood in S-P-E 4: The patterns discussed in parts 2 and 3 are known as "value patterns" because their streams return a single value for each call to next. Which, then, of the patterns discussed in part 3 are value patterns? In the same general ballpark: I was looking at the Class definition for Pfsm, to understand the working of the Markov example, and I've hit a wall. I'm fine up until: index = list.at(index).choose.clip(0, maxState) * 2 + 2; The .choose suggests that we're working with an array of arrays; I don't grasp why we arrived at maxState's value, why we're doing this extra multiplication/addition, how this fits in with the Markov example. >>One wee question: what is a lazy sequence of values? > >A lazy sequence is one where you get the values on demand. >An eager sequence is something like an array or list where >you have all the values at once. > >A lazy sequence can be indefinitely long whereas an eager sequence must >have a finite length. > Thanks! I'm eager to grok all this, and my determination is indefinitely long ... ------------------------------ Date: Wed, 30 Jun 1999 00:14:09 -0600 From: "David Cottle" <---@---.---> Subject: Writing to a file Hi, I've gotten to the File section of the documentation. The help files don't give any examples of code. Could you give me a simple example showing how to write data (other than sound file‹I get that) to a file? For example, multiple rotations through a collection. Thanks. - -- ><><><><><><><><><><><> David Cottle composition, notation, contra lime@uiuc.edu ------------------------------ Date: Wed, 30 Jun 1999 09:49:23 -0600 From: James McCartney <---@---.---> Subject: Re: Streams-Events-Patterns At 4:57 AM -0600 6/30/99, Mark Ballora wrote: >>One thing: Pseq, Prand, etc are not necessarily value patterns. >>They can be either depending on what they return. > >So I misunderstood in S-P-E 4: > >The patterns discussed in parts 2 and 3 are known as "value patterns" >because their streams return a single value for each call to next. Pseq([1, 2, 3]) is a value pattern. Pseq([Event.make({ ~degree = 0 }), Event.make({ ~degree = 2 })]) is an event pattern. Pseq([ // this Pseq is an event pattern Pbind(\degree, // Pbind is always an event pattern Pseq([0, 1, 2]) // this Pseq is a value pattern ), Pbind(\degree, Pseq([3, 4, 5]) // this Pseq is a value pattern ) ]) >In the same general ballpark: >I was looking at the Class definition for Pfsm, to understand the working >of the Markov example, and I've hit a wall. > >I'm fine up until: > >index = list.at(index).choose.clip(0, maxState) * 2 + 2; Pfsm has the following syntax: Pfsm([ , , , , , ... , , ], repeats) The multiply and add is just internal stuff so that I retrieve the proper from the Pfsm's list. e.g. the array for state 1 is at index 4. 1 * 2 + 2 == 4 Since the choose method on a Function is equivalent to calling value, you may use a Function instead of an array of next states. If your fsm has a terminal state, then you use nil as the pattern for that state and [] as the array of next states. --- james mccartney james@audiosynth.com http://www.audiosynth.com If you have a PowerMac check out SuperCollider2, a real time synth program: ------------------------------ End of sc-users-digest V1 #48 *****************************