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

scale2beat

Home   How To   Code Pool   Public Library   Theory   Events
//////////////////////////////////////////////////////
//-- scale->beat /f0 031221  updated 071029

//"no one cares about pitches any more, only beats.." -jmc

(
//--settings
var path= "sounds/a11wlk01.wav";						//replace with your own drumloop
var tempo= 125;									//the drumloop's tempo
var beats= 8;										//length of drumloop in beats
/*
GUI.cocoa;
GUI.swing;
*/



//--this section by jmc/jrh. copied from http://swiki.hfbk-hamburg.de:8888/MusicTechnology/601


// a scale dictionary
// some of these names are the names that musicians give to the scales
// and have no accurate relation to their actual origin.
// no microtuning here, all equal tempered.

z = (
// 5 note scales
minorPentatonic: [0,3,5,7,10],
majorPentatonic: [0,2,4,7,9],
ritusen: [0,2,5,7,9], // another mode of major pentatonic
egyptian: [0,2,5,7,10], // another mode of major pentatonic

kumoi: [0,2,3,7,9],
hirajoshi: [0,2,3,7,8],
iwato: [0,1,5,6,10], // mode of hirajoshi
chinese: [0,4,6,7,11], // mode of hirajoshi
indian: [0,4,5,7,10],
pelog: [0,1,3,7,8],

prometheus: [0,2,4,6,11],
scriabin: [0,1,4,7,9],

// 6 note scales
whole: (0,2..10),
augmented: [0,3,4,7,8,11],
augmented2: [0,1,4,5,8,9],

// hexatonic modes with no tritone
hexMajor7: [0,2,4,7,9,11],
hexDorian: [0,2,3,5,7,10],
hexPhrygian: [0,1,3,5,8,10],
hexSus: [0,2,5,7,9,10],
hexMajor6: [0,2,4,5,7,9],
hexAeolian: [0,3,5,7,8,10],

// 7 note scales
ionian: [0,2,4,5,7,9,11],
dorian: [0,2,3,5,7,9,10],
phrygian: [0,1,3,5,7,8,10],
lydian: [0,2,4,6,7,9,11],
mixolydian: [0,2,4,5,7,9,10],
aeolian: [0,2,3,5,7,8,10],
locrian: [0,1,3,5,6,8,10],

harmonicMinor: [0,2,3,5,7,8,11],
harmonicMajor: [0,2,4,5,7,8,11],

melodicMinor: [0,2,3,5,7,9,11],
bartok: [0,2,4,5,7,8,10], // jazzers call this the hindu scale

// raga modes
todi: [0,1,3,6,7,8,11], // maqam ahar kurd
purvi: [0,1,4,6,7,8,11],
marva: [0,1,4,6,7,9,11],
bhairav: [0,1,4,5,7,8,11],
ahirbhairav: [0,1,4,5,7,9,10],

superLocrian: [0,1,3,4,6,8,10],
romanianMinor: [0,2,3,6,7,9,10], // maqam nakriz
hungarianMinor: [0,2,3,6,7,8,11], 
neapolitanMinor: [0,1,3,5,7,8,11],
enigmatic: [0,1,4,6,8,10,11],
spanish: [0,1,4,5,7,8,10],

// modes of whole tones with added note:
leadingWhole: [0,2,4,6,8,10,11],
lydianMinor: [0,2,4,6,7,8,10],
neapolitanMajor: [0,1,3,5,7,9,11],
locrianMajor: [0,2,4,5,6,8,10],

// 8 note scales
diminished: [0,1,3,4,6,7,9,10],
diminished2: [0,2,3,5,6,8,9,11],

// 12 note scales
chromatic: (0..11),

// some raga modes from asawari thata
// without pakads (movements) or vakras (twists)

aswari_aroh: [ 0, 2, 5, 7, 9, 0 ],
aswari_avaroh: [ 0, 2, 4, 3, 5, 7, 9, 10 ],
jonpuri_aroh: [ 0, 2, 5, 7, 8, 10 ],
jonpuri_avaroh: [ 0, 2, 3, 5, 7, 8, 10 ],
durbai_kandra: [ 0, 2, 3, 5, 7, 8, 10 ],
desi_aroh: [ 0, 2, 5, 7, 10 ],
desi_avaroh: [ 0, 1, 3, 5, 7, 8, 10 ],
gandhari_aroh: [ 0, 2, 5, 7, 10 ],
gandhari_avaroh: [ 0, 1, 3, 5, 7, 9, 10 ],
khut_aroh: [ 0, 3, 5, 7, 8, 10 ],
khut_avaroh: [ 0, 1, 3, 5, 7, 8, 9, 10 ],
jeelaf_aroh: [ 0, 3, 5, 7, 8, 11 ],
jeelaf_avaroh: [ 0, 2, 4, 5, 7, 9, 10 ],
gopika_basant_aroh: [ 0, 3, 5, 7, 9, 11 ],
gopika_basant_avaroh: [ 0, 4, 5, 7, 9, 11 ],
abheeri_aroh: [ 0, 3, 5, 7, 10 ],
abheeri_avaroh: [ 0, 1, 3, 5, 7, 8, 10 ]

);



//--drum machine playing the above scales
Routine.run{
	var win, popScale, popVersion, butSteps;
	var buf, clk, main, order= (0..11), mark= false.dup(12);
	var hang= Condition.new;
	s.bootSync(hang);
	SynthDef("playbuf-segment", {|out= 0, bufnum= 0, offset= 0.0, length= 0.5, rate= 1.0|
		var e= EnvGen.kr(Env.linen(0.005, length, 0.01), doneAction: 2);
		var z= PlayBuf.ar(1, bufnum, BufRateScale.ir(bufnum)*rate, 1, BufFrames.ir(bufnum)*offset);
		Out.ar(out, Pan2.ar(z*e));
	}).send(s);
	s.sync(hang);
	buf= Buffer.readChannel(s, path, channels:[0]);	//force mono
	clk= TempoClock(160/60);
	s.sync(hang);
	{
		win= GUI.window.new("scale->beat2", Rect(200, 500, 270, 200));
		GUI.numberBox.new(win, Rect(30, 10, 40, 20)).value_(clk.tempo*60)
			.action_{|x| clk.tempo_(x.value/60)};
		GUI.staticText.new(win, Rect(80, 10, 90, 20)).string_("bpm");
		popVersion= GUI.popUpMenu.new(win, Rect(10, 50, 180, 20))
			.items_(#["version1-glued", "version2-timed"]);
		popScale= GUI.popUpMenu.new(win, Rect(10, 90, 180, 20))
			.items_(z.keys.asArray)
			.action_{|x|
				mark= false.dup(12);
				z[x.items[x.value]].do{|y| mark= mark.put(y, true)};
				butSteps.do{|x, i|
					if(mark[i], {
						x.value= x.value%12+12;
					}, {
						x.value= x.value%12;
					});
				};
			}
			.valueAction_(1);
		butSteps= {|i|
			GUI.button.new(win, Rect(i*20+10, 140, 20, 20))
				.states_(
					{|j| [order[j].asString, Color.black, Color.clear]}.dup(12)++
					{|j| [order[j].asString, Color.black, Color.grey]}.dup(12)++
					{|j| [order[j].asString, Color.white, Color.grey]}.dup(12)
				)
				.value_(order[i])
				.action_{|x, mod|
					if(mod&131072==131072, {
						if(x.value<=12, {
							x.value= x.value-1%12+12;
						}, {
							x.value= x.value-1%12;
						});
					}, {
						if(x.value==12, {x.value= 0});
						if(x.value==24, {x.value= 12});
					});
					mark= mark.put(i, x.value>=12);
					order= order.put(i, x.value%12);
				}
		}.dup(12);
		GUI.popUpMenu.new(win, Rect(130, 10, 110, 20))
			.items_(#[
				"-order-",
				"shuffle order",
				"randomize order",
				"default order",
				"set all to 0",
				"set all to 4",
				"set all to 8",
				"toggle 3 and 7",
				"shift left",
				"shift right",
				"invert",
				"transpose up",
				"transpose down"
			])
			.action_{|x|
				switch(x.value,
					1, {order= order.scramble},
					2, {order= {12.rand}.dup(12)},
					3, {order= (0..11)},
					4, {order= 0.dup(12)},
					5, {order= 4.dup(12)},
					6, {order= 8.dup(12)},
					7, {order= {|i| #[3, 7][i%2]}.dup(12)},
					8, {order= order.rotate(1)},
					9, {order= order.rotate(-1)},
					10, {order= order.invert},
					11, {order= order+1%12},
					12, {order= order-1%12}
				);
				butSteps.do{|x, i|
					if(mark[i], {
						x.value_(order[i]+12);
					}, {
						x.value_(order[i]);
					});
				};
				x.value= 0;
			};
		GUI.staticText.new(win, Rect(20, 165, 250, 20))
			.string_("click to increase index, shift-click to mark");
		win.front;
		win.onClose_{
			main.stop;
			buf.free;
		};
		CmdPeriod.doOnce{
			if(win.isClosed.not, {win.close});
			buf.free;
		};
		
		//--main loop
		main= Routine({
			inf.do{|i|
				var delta, index, candidates;
				delta= clk.beatDur*beats/12;
				butSteps.do{|x| if(x.value>=24, {x.value= x.value-12})};
				if(mark.any{|x| x}, {
					index= i%12;
					if(popVersion.value==0, {		//version1 disregard pauses
						candidates= [];
						mark.do{|x, j| if(x, {candidates= candidates.add(j)})};
						index= candidates.wrapAt(i);
					});
					if(mark[index], {
						Synth.grain('playbuf-segment', [
							\bufnum, buf.bufnum,
							\offset, order[index]/12,
							\length, delta,
							\rate, clk.tempo*60/tempo
						]);
						butSteps[index].value= butSteps[index].value+12;
						win.refresh;
					});
				});
				delta.wait;
			};
		}).play(AppClock);
	}.defer;
};
)



/redFrik

Link to this Page