View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide

aroh/avaroh

Uploaded Image: ln.gif

Classical indian music often often uses a different scale upwards than when
moving downwards. The upward scale is called aroh, whereas the downward one
is avaroh. There are many similar improvisation and composition rules that
are not specially mentioned here, so this is a simplification regarding
those composition systems.

Implementing this simple rule implies that there must be some place where the
last note stays in memory. (In this case the note is the degree into the scale.)
The first example simply uses the variable lastDegree.
degree_to_key is the function that is evaluated in order to translate the degree
into a frequency each time the stream recieves the message 'next'.
[see also:Pmemo]

note:

in sc3 a pattern is included in the souces: Pavaroh. see helpfiles for the examples



//this is code for sc3d5

(
//___indian video game (1)
#{
        
        var aroh, avaroh, scale, lastDegree=0, degree_to_key;
        //gandhari raga.  vadi: dha (7) samvadi: ga (3)
        aroh = #[0, 2, 5, 7, 10];
        avaroh =  #[0, 1, 3, 5, 7, 9, 10];
        
        degree_to_key = { arg degree;
                
                scale = if(degree >= lastDegree, { aroh }, {avaroh});
                lastDegree = degree;
                (degree.degreeToKey(scale, 12) + 60).midicps;
        };
        
        { var pat, trig;
                trig = Impulse.kr(LFClipNoise.kr(4, 3, LFClipNoise.kr(0.2, 2, 7)));
                
                pat = Pcollect(degree_to_key, Prand([0, 2, 3, 4, 2, 1, 0, -1, -2], inf));
                RLPF.ar(
                        SinOsc.ar(
                                Sequencer.kr(pat.asStream, trig), 0, Decay.kr(trig, 1.8)
                        ).distort
                , 554, 0.3) * 0.1
        }.play
}.send;
                
)


//The following example is intended as a first step towards using this concept
//in EventStreams, using a protoevent to store the data, with the same result.

(
//___indian video game (2) protoEvent
#{
        
        var scale,  degree_to_key, protoevent;
        
        protoevent = Event.protoEvent;
        protoevent.use({
                //gandhari raga.  vadi: dha (7) samvadi: ga (3)
                ~aroh = #[0, 2, 5, 7, 10];
                ~avaroh =  #[0, 1, 3, 5, 7, 9, 10];
                ~lastDegree = 0;
        });
        
        degree_to_key = { arg degree;
                                        var freq;
                                        protoevent.use({
                                                ~scale = if(degree >= ~lastDegree, { ~aroh }, {~avaroh});
                                                ~lastDegree = degree;
                                        freq = (degree.degreeToKey(~scale, 12) + 60).midicps;
                                        });
                                        freq
        };
        
        { var pat, trig;
                trig = Impulse.kr(LFClipNoise.kr(4, 3, LFClipNoise.kr(0.2, 2, 7)));
                pat = Pcollect(degree_to_key, Prand([0, 2, 3, 4, 2, 1, 0, -1, -2], inf));
                RLPF.ar(
                        SinOsc.ar(
                                Sequencer.kr(pat.asStream, trig), 0, Decay.kr(trig, 1.8)
                        ).distort
                , 554, 0.3) * 0.1
        }.play
}.send;
                
)



When trying to simply use the protoevent and an EventStream and including the translation
in the protoevent, there is the question how to access past data from within an eventstream.
I found no other way than to write a class that puts the last event into the current event, so 
that one can always look one step back. This might be also interesting for other conditional structures referring
one step back. Apart from the input pattern it holds one instance variable, lastEvent. 
The last event gets put into the event at \lastEvent.



Pmemo : FilterPattern { 
        *new { arg pattern; 
                ^super.new(pattern) 
        } 
        asStream { 
                ^Routine({ arg inval; 
                        var lastEvent; 
   					lastEvent = Event.protoEvent; 
                        	pattern.asStream.collect({ arg event; 
                                var newevent; 
                                lastEvent.put(\lastEvent, nil); //wipe out the previous last event so that there is no chain back to all events. 
                                newevent = event.put(\lastEvent, lastEvent); 
                                lastEvent = event.copy.finishEvent; 
                                newevent 
                         }).embedInStream(inval); 
                }) 
        } 
}



(
//___testing Pmemo (sc3d)
#{
        
        var scale, protoevent;
        
        protoevent = Event.protoEvent;
                
        //necessary modifications in the protoEvent:
        protoevent.use({
                //gandhari raga.  vadi: dha (7) samvadi: ga (3)
                ~aroh = #[0, 2, 5, 7, 10];
                ~avaroh =  #[0, 1, 3, 5, 7, 9, 10];
                ~scale = {      if(~degree >= ~lastEvent.at(\degree), { ~aroh }, { ~avaroh }) };
                ~note = { (~degree + ~mtranspose).degreeToKey(~scale.value, ~stepsPerOctave) };
                        
        });
        
        
        { 
                Pmemo( 
                        Pbind(
                                \ugenFunc, { arg freq, amp, sustain, p=0.5; 
                                        Line.kr(1, 0, sustain) * SinOsc.ar(freq, SinOsc.ar(freq*p, 0, BrownNoise.kr(pi/8)), amp)
                                }, 
                                \degree, Pseq([0, 1, 2, 3, 4, 5, 6, Pshuf([7, 3, 4, \rest, 5, Prand([0, -1, 6, 8], 2)], 2), 4, 3, 2, 1, 0, -1], inf), 
                                \dur, 0.2,
                                \legato, Prand([0.8, 0.8, 2.8, 1.4], inf),
                                \amp, Prand([0.1, 0.05, 0.08], inf),
                                \p, Pseq([0, 0.4, 0.8, 0.2], inf),
                                \pan, Prand([0.1, -0.1, 0], inf)
                                )
                ).ar(2, protoevent)
        }.play
        
}.send;
                
)
( 
//___indian video game (1)  sc2 version
  
        var aroh, avaroh, scale, lastDegree=0, degree_to_key; 
        //gandhari raga.  vadi: dha (7) samvadi: ga (3) 
        aroh = #[0, 2, 5, 7, 10]; 
        avaroh =  #[0, 1, 3, 5, 7, 9, 10]; 
         
        degree_to_key = { arg degree; 
                 
                scale = if(degree >= lastDegree, { aroh }, {avaroh}); 
                lastDegree = degree; 
                (degree.degreeToKey(scale, 12) + 60).midicps; 
        }; 
         
        { var pat, trig; 
                trig = Impulse.kr(LFClipNoise.kr(4, 3, LFClipNoise.kr(0.2, 2, 7))); 
                 
                pat = Pcollect(degree_to_key, Prand([0, 2, 3, 4, 2, 1, 0, -1, -2], inf)); 
                RLPF.ar( 
                        SinOsc.ar( 
                                Sequencer.kr(pat.asStream, trig), 0, Decay.kr(trig, 1.8) 
                        ).distort 
                , 554, 0.3) * 0.1 
        }.play 

                 
) 
)

It is also possible to wrap it further to make it more convenient: //basic implementation of the biscale scheme used in indian raga //aroh: raising scale //avaroh: falling scale Pbiscale : Pmemo { var <>aroh, <>avaroh; *new { arg aroh, avaroh, pattern; ^super.new(pattern).aroh_(aroh).avaroh_(avaroh) } asStream { ^super.asStream.collect({ arg item; var delta; delta = item.at(\degree) - item.at(\lastEvent).at(\degree); if(delta.isKindOf(SequenceableCollection), { delta = delta.at(0) }); if(delta > 0, { item.put(\scale, aroh) }, { item.put(\scale, avaroh) }); }); } } //new delhi dreams (sc2 test) ( a = Pbiscale(#[0, 1, 3, 5.7, 10], #[0, 2, 3, 7, 10.5], Pbind( \instrument, \sine, \degree, Pseq([Pseries(0, 1, 6), Prand([0, 3, 2, 4], 5), 0, 0, 0, Pseries(6, -1, 6), 0, -1, 0, 0], inf) + Pseq([0, 0, 0, [0, 3]], inf), \dur, Pseq([0.2, Pshuf(#[0.2, 0.1], 1)], inf) * 0.9, \pan, Pshuf([-1, -1, -1, 1, 1, 1], inf) / 4 ) ); { a.ar + Saw.ar([1, LFNoise1.kr(0.1, 0.01, 1)]*60.midicps/2, 0.03) }.play;

authors so far: Julian Rohrhuber
back to Theory

Links to this Page