mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Add .sc as a SuperCollider file extension
This commit is contained in:
		| @@ -2299,6 +2299,7 @@ SuperCollider: | |||||||
|   lexer: Text only |   lexer: Text only | ||||||
|   extensions: |   extensions: | ||||||
|   - .scd |   - .scd | ||||||
|  |   - .sc | ||||||
|  |  | ||||||
| Swift: | Swift: | ||||||
|   type: programming |   type: programming | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								samples/SuperCollider/WarpPreset.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								samples/SuperCollider/WarpPreset.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | WarpPreset { | ||||||
|  | 	*new {|path| | ||||||
|  | 		if(path.notNil) { | ||||||
|  | 			^Object.readArchive(path); | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		^super.new.init(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	init { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	save { | ||||||
|  | 		Dialog.savePanel({|path| | ||||||
|  | 			this.writeArchive(path); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										286
									
								
								samples/SuperCollider/WarpTate.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								samples/SuperCollider/WarpTate.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,286 @@ | |||||||
|  | WarpTate { | ||||||
|  | 	classvar <numSections = 8; | ||||||
|  | 	// classvar <sectionDur = 3 * 60; | ||||||
|  | 	classvar <sectionDur = 60; | ||||||
|  |  | ||||||
|  | 	var <sensorKeys; | ||||||
|  | 	var <clock; | ||||||
|  | 	var <tempo; | ||||||
|  | 	var <>tempoChannel; | ||||||
|  | 	var <>tempoControl; | ||||||
|  | 	var <out; | ||||||
|  | 	var <tracks; | ||||||
|  | 	var <>sections; | ||||||
|  | 	var <availableControls; | ||||||
|  | 	var <controls; | ||||||
|  | 	var <sensorVals; | ||||||
|  | 	var <sensorPrevs; | ||||||
|  | 	var <sensorMins; | ||||||
|  | 	var <sensorMaxs; | ||||||
|  | 	var <>sensorMinAdj; | ||||||
|  | 	var <>sensorMaxAdj; | ||||||
|  | 	var <doAdjusts; | ||||||
|  | 	var <playRout; | ||||||
|  |  | ||||||
|  | 	*new { | ||||||
|  | 		^super.new.init; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	init { | ||||||
|  | 		tempo = 120; | ||||||
|  | 		tempoChannel = 15; | ||||||
|  | 		tempoControl = 3; | ||||||
|  | 		clock = TempoClock.default | ||||||
|  | 			.tempo_(2) | ||||||
|  | 			.permanent_(true); | ||||||
|  |  | ||||||
|  | 		MIDIClient.init; | ||||||
|  | 		out = MIDIOut.newByName("IAC Driver", "Bus 1"); | ||||||
|  | 		out.latency = 0; | ||||||
|  |  | ||||||
|  | 		tracks = IdentityDictionary[]; | ||||||
|  | 		sections = Array.newClear(WarpTate.numSections); | ||||||
|  | 		// sections is a List of IdentityDictionary to be mapped to | ||||||
|  | 		// WarpTrack settings var | ||||||
|  | 		// e.g. List[IdentityDictionary[ | ||||||
|  | 		//	 			'303_1' -> IdentityDictionary['notes' -> List[42]], | ||||||
|  | 		// 				'808_1'	-> IdentityDictionary['notes' -> List[24]] | ||||||
|  | 		// 			] | ||||||
|  | 		// 		] | ||||||
|  | 		sensorKeys = ['303a', '303b', '808a', '808b']; | ||||||
|  |  | ||||||
|  | 		// channel 16 reserved for tempo changes | ||||||
|  | 		availableControls = 15.collect {|channel| | ||||||
|  | 			(0..120).reject({|item, i| | ||||||
|  | 				[ 0, 1, 2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 64, 65, 66, 67, 68, | ||||||
|  | 				69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 84, 91, 92, 93, 94, | ||||||
|  | 				95, 96, 97, 98, 99, 100, 102 ].includes(item) | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		controls = (0..127).collect { IdentityDictionary[] }; | ||||||
|  |  | ||||||
|  | 		this.addOSCdefs(); | ||||||
|  |  | ||||||
|  | 		CmdPeriod.add({this.stop}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tempo_ {|argTempo| | ||||||
|  | 		if(argTempo >= 50 && argTempo <= 177) { | ||||||
|  | 			tempo = argTempo; | ||||||
|  | 			clock.tempo = tempo / 60; | ||||||
|  |  | ||||||
|  | 			out.control(tempoChannel, tempoControl, tempo - 50); | ||||||
|  | 		} { | ||||||
|  | 			"Tempo out of Logic's range :(".postln; | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	addTrack {|trackKey, channel, type| | ||||||
|  | 		tracks[trackKey] = WarpTrack(this, trackKey, channel, type); | ||||||
|  | 		^tracks[trackKey]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	loadTrack {|preset, checkAvailable| | ||||||
|  | 		var track = WarpTrack.load(this, preset, checkAvailable), | ||||||
|  | 			trackKey = track.settings['key']; | ||||||
|  |  | ||||||
|  | 		tracks[trackKey] = track; | ||||||
|  | 		^tracks[trackKey]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	readTrack {|path| | ||||||
|  | 		var track = WarpTrack.read(this, path), | ||||||
|  | 			trackKey = track.settings['key']; | ||||||
|  |  | ||||||
|  | 		tracks[trackKey] = track; | ||||||
|  | 		^tracks[trackKey]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	removeTrack {|trackKey| | ||||||
|  | 		tracks[trackKey].allOff(); | ||||||
|  | 		tracks[trackKey] = nil; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	removeAllTracks { | ||||||
|  | 		tracks = IdentityDictionary[]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	on {|trackKey, note| | ||||||
|  | 		tracks[trackKey].on(note); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	off {|trackKey, note| | ||||||
|  | 		tracks[trackKey].off(note); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hit {|trackKey, note=60, vel=127, dur=1| | ||||||
|  | 		tracks[trackKey].hit(note, vel, dur); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	noteOn {|midiChannel, note, vel| | ||||||
|  | 		out.noteOn(midiChannel, note, vel); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	noteOff {|midiChannel, note, vel| | ||||||
|  | 		out.noteOff(midiChannel, note, vel); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	control {|midiChannel, num, val| | ||||||
|  | 		out.control(midiChannel, num, val); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	isControlAvailable {|channel, controlNum| | ||||||
|  | 		^controls[channel].keys.includes(controlNum.asSymbol).not; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setControl {|channel, num, key| | ||||||
|  | 		controls[channel][num.asSymbol] = key; | ||||||
|  | 		availableControls[channel].remove(num); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	assign {|trackKey, paramKey, controlNum, learn=false| | ||||||
|  | 		var channel = tracks[trackKey].settings['midiChannel']; | ||||||
|  |  | ||||||
|  | 		if(controlNum.notNil && this.isControlAvailable(channel, controlNum)) { | ||||||
|  | 			tracks[trackKey].assign(paramKey, controlNum, learn); | ||||||
|  | 			availableControls[channel].removeAt(0); | ||||||
|  |  | ||||||
|  | 		} { | ||||||
|  | 			if(availableControls[channel].size > 0) { | ||||||
|  | 				tracks[trackKey].assign(paramKey, availableControls[channel][0], learn); | ||||||
|  | 				availableControls[channel].removeAt(0); | ||||||
|  | 			} { | ||||||
|  | 				"no controls left!".postln; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		"Don't forget to turn off MIDI learn".postln | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setParam {|trackKey, paramKey, val| | ||||||
|  | 		var track, param; | ||||||
|  |  | ||||||
|  | 		if((track = tracks[trackKey]).notNil) { | ||||||
|  | 			if(track.params[paramKey].notNil) { | ||||||
|  | 				track.setParam(paramKey, val); | ||||||
|  | 			} { | ||||||
|  | 				"paramKey doesn't exist".postln; | ||||||
|  | 			}; | ||||||
|  | 		} { | ||||||
|  | 			"track key doesn't exist".postln; | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// sec takes IdentityDictionarys of WarpTrack settings | ||||||
|  | 	addSection {|index, tempo=120, presets| | ||||||
|  | 		// Add section with tempo | ||||||
|  | 		sections[index] = IdentityDictionary[ | ||||||
|  | 			'tempo' 	-> tempo, | ||||||
|  | 			'tracks'	-> presets | ||||||
|  | 		]; | ||||||
|  |  | ||||||
|  | 		presets.do {|preset, i| | ||||||
|  | 			// create track if there ain't one with this key | ||||||
|  | 			if(tracks.includesKey(preset['key']).not) { | ||||||
|  | 				this.loadTrack(preset, true); | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			// store the preset | ||||||
|  | 			// sections[index]['tracks'][preset['key']] = preset; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		^sections; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	play { | ||||||
|  |  | ||||||
|  | 		if(sections.any {|item, i| item.notNil; }) { | ||||||
|  | 			playRout = Routine { | ||||||
|  | 				inf.do {|i| | ||||||
|  | 					sections.do {|section| | ||||||
|  | 						if(section.notNil) { | ||||||
|  | 							if(i !== 0) { | ||||||
|  | 								tracks.do {|track| | ||||||
|  | 									track.allOff(); | ||||||
|  | 								}; | ||||||
|  | 								this.removeAllTracks(); | ||||||
|  | 							}; | ||||||
|  |  | ||||||
|  | 							this.tempo = section['tempo']; | ||||||
|  |  | ||||||
|  | 							section['tracks'].do {|track, i| | ||||||
|  | 								var newTrack = this.loadTrack(track, false); | ||||||
|  | 								newTrack.play(); | ||||||
|  | 							}; | ||||||
|  | 							sectionDur.wait; | ||||||
|  | 						}; | ||||||
|  | 					}; | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 			clock.playNextBar(playRout); | ||||||
|  | 		} { | ||||||
|  | 			"no sections added!".postln; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	stop { | ||||||
|  | 		playRout.stop; | ||||||
|  |  | ||||||
|  | 		tracks.do {|track| | ||||||
|  | 			track.allOff(); | ||||||
|  | 			out.allNotesOff(track.settings['midiChannel']); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	addOSCdefs { | ||||||
|  | 		sensorVals = 0!sensorKeys.size; | ||||||
|  | 		sensorPrevs = 0!sensorKeys.size; | ||||||
|  | 		sensorMins = 9999!sensorKeys.size; | ||||||
|  | 		sensorMaxs = 0!sensorKeys.size; | ||||||
|  | 		sensorMinAdj = sensorMinAdj ?? { 0.005 }; | ||||||
|  | 		sensorMaxAdj = sensorMaxAdj ?? { 0.01 }; | ||||||
|  | 		doAdjusts = false!sensorKeys.size; | ||||||
|  |  | ||||||
|  | 		sensorKeys.do {|sensorKey, i| | ||||||
|  | 			OSCdef(("sensor_" ++ sensorKey).asSymbol, {|msg, time, addr, recvPort| | ||||||
|  | 				var val = msg[1]; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 				sensorPrevs[i] = sensorVals[i]; | ||||||
|  | 				sensorVals[i] = val; | ||||||
|  |  | ||||||
|  | 				if(doAdjusts[i]) { | ||||||
|  | 					sensorMins[i] = min(val, sensorMins[i]); | ||||||
|  | 					sensorMaxs[i] = max(val, sensorMaxs[i]); | ||||||
|  |  | ||||||
|  | 					if(val < sensorMaxs[i]) { | ||||||
|  | 						sensorMaxs[i] = sensorMaxs[i] - sensorMaxAdj; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					if(val > sensorMins[i]) { | ||||||
|  | 						sensorMins[i] = sensorMins[i] + sensorMinAdj; | ||||||
|  | 					}; | ||||||
|  | 				} { | ||||||
|  | 					val = val.clip(sensorMins[i], sensorMaxs[i]); | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 				tracks.do {|track, j| | ||||||
|  | 					if(track.settings['sensorFuncs'].includesKey(sensorKey)) { | ||||||
|  | 						track.sensor( | ||||||
|  | 							sensorKey, | ||||||
|  | 							val.linlin( | ||||||
|  | 								sensorMins[i], | ||||||
|  | 								sensorMaxs[i], | ||||||
|  | 								127, | ||||||
|  | 								0 | ||||||
|  | 							) | ||||||
|  | 						); | ||||||
|  | 					}; | ||||||
|  | 				} | ||||||
|  | 			}, ("/prox/" ++ sensorKey).asSymbol); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										263
									
								
								samples/SuperCollider/WarpTrack.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								samples/SuperCollider/WarpTrack.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,263 @@ | |||||||
|  | WarpTrack { | ||||||
|  | 	classvar <defaults; | ||||||
|  |  | ||||||
|  | 	var <parent; | ||||||
|  | 	var <settings; | ||||||
|  |  | ||||||
|  | 	*initClass { | ||||||
|  | 		defaults['303_1'] = defaults['303'].copy; | ||||||
|  | 		defaults['303_1']['paramControls'].putPairs([ | ||||||
|  | 			'Bus 1', 46, | ||||||
|  | 			'Bus 2', 45, | ||||||
|  | 			'Bus 3', 48, | ||||||
|  | 			'echovol', 47 | ||||||
|  | 		]); | ||||||
|  | 		defaults['303_1']['params'].putPairs([ | ||||||
|  | 			'Bus 1', 0, | ||||||
|  | 			'Bus 2', 0, | ||||||
|  | 			'Bus 3', 0, | ||||||
|  | 			'echovol', 0 | ||||||
|  | 		]); | ||||||
|  |  | ||||||
|  | 		defaults['303_2'] = defaults['303_1'].copy; | ||||||
|  | 		defaults['303_2']['paramControls'].putPairs([ | ||||||
|  | 		]); | ||||||
|  | 		defaults['303_2']['params'].putPairs([ | ||||||
|  | 		]); | ||||||
|  |  | ||||||
|  | 		defaults['808_1'] = defaults['808'].copy; | ||||||
|  | 		defaults['808_1']['paramControls'].putPairs([ | ||||||
|  | 			'bitcrusher', 88, | ||||||
|  | 			'Send 1', 89, | ||||||
|  | 			'Send 2', 90, | ||||||
|  | 			'Send 3', 101 | ||||||
|  | 		]); | ||||||
|  | 		defaults['808_1']['params'].putPairs([ | ||||||
|  | 			'bitcrusher', 0, | ||||||
|  | 			'Send 1', 0, | ||||||
|  | 			'Send 2', 0, | ||||||
|  | 			'Send 3', 0 | ||||||
|  | 		]); | ||||||
|  |  | ||||||
|  | 		defaults['808_2'] = defaults['808_1'].copy; | ||||||
|  | 		defaults['808_2']['paramControls'].putPairs([]); | ||||||
|  | 		defaults['808_2']['params'].putPairs([]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	*new {|argParent, argKey, argMidiChannel, argType| | ||||||
|  | 		^super.new.init(argParent, argKey, argMidiChannel, argType); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	*read {|argParent, path| | ||||||
|  | 		^super.new.init(argParent).readPreset(path); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	*load {|argParent, preset, checkAvailable| | ||||||
|  | 		^super.new.init(argParent).loadPreset(preset, checkAvailable); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	init {|argParent, argKey, argMidiChannel, argType| | ||||||
|  | 		parent = argParent; | ||||||
|  |  | ||||||
|  | 		settings = IdentityDictionary[ | ||||||
|  | 			'key'			-> argKey, | ||||||
|  | 			'midiChannel'	-> argMidiChannel, | ||||||
|  | 			'notes'			-> Set[], | ||||||
|  | 			'params'		-> IdentityDictionary[], | ||||||
|  | 			'paramControls'	-> IdentityDictionary[], | ||||||
|  | 			'patternTrack'	-> true, | ||||||
|  | 			'sensorFuncs'	-> IdentityDictionary[] | ||||||
|  | 		]; | ||||||
|  |  | ||||||
|  | 		if(argType.notNil) { | ||||||
|  | 			settings['type'] = argType; | ||||||
|  | 			if(WarpTrack.defaults.keys.includes(argType)) { | ||||||
|  | 				['paramControls', 'params'].do {|key, i| | ||||||
|  | 					settings[key] = WarpTrack.defaults[argType][key]; | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			this.initParams(); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	on {|note| | ||||||
|  | 		var clock = parent.clock; | ||||||
|  | 		var sub = 1 / (parent.clock.tempo * 16); // one sub division | ||||||
|  |  | ||||||
|  | 		clock.schedAbs(clock.nextBar - sub, { | ||||||
|  | 			if(settings['patternTrack']) { | ||||||
|  | 				this.allOff(); | ||||||
|  | 			} { | ||||||
|  | 				this.off(note); | ||||||
|  | 			}; | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		parent.clock.playNextBar({ | ||||||
|  | 			settings['notes'].add(note); | ||||||
|  | 			parent.noteOn(settings['midiChannel'], note, 127); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	off {|note| | ||||||
|  | 		// settings['notes'].remove(note); | ||||||
|  | 		parent.noteOff(settings['midiChannel'], note, 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hit {|note=60, vel=127, dur=1, quant=0| | ||||||
|  | 		{ | ||||||
|  | 			parent.noteOn(settings['midiChannel'], note, vel); | ||||||
|  | 			dur.wait; | ||||||
|  | 			parent.noteOff(settings['midiChannel'], note, vel); | ||||||
|  | 		}.fork(parent.clock, quant:quant); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	allOff { | ||||||
|  | 		settings['notes'].do {|note, i| | ||||||
|  | 			this.off(note); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	assign {|paramKey, num, learn=false, init=true, checkAvailable=true| | ||||||
|  | 		if(num.notNil) { | ||||||
|  | 			this.assignAll(IdentityDictionary[paramKey -> num], learn, init, checkAvailable); | ||||||
|  | 		} { | ||||||
|  | 			parent.assign(settings['key'], paramKey, nil, learn); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	assignAll {|paramControls, learn=false, init=true, checkAvailable=true| | ||||||
|  | 		var action = { | ||||||
|  | 			var channel = settings['midiChannel']; | ||||||
|  |  | ||||||
|  | 			paramControls.keysValuesDo { |paramKey, num| | ||||||
|  | 				if(checkAvailable.not || | ||||||
|  | 					(checkAvailable && parent.isControlAvailable(channel, num))) { | ||||||
|  | 					settings['paramControls'][paramKey] = num; | ||||||
|  | 					if(init) { | ||||||
|  | 						settings['params'][paramKey] = 0; | ||||||
|  | 					}; | ||||||
|  | 					parent.setControl(channel, num, paramKey); | ||||||
|  | 					if(learn) { | ||||||
|  | 						parent.control(channel, num, 127); | ||||||
|  | 						0.05.wait; | ||||||
|  | 						parent.control(channel, num, 0); | ||||||
|  | 					}; | ||||||
|  | 					paramKey ++ " assigned to controlNum " ++ num; | ||||||
|  | 				} { | ||||||
|  | 					("this controlNum " ++ num ++ " is already assigned!").postln; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		if(learn) { | ||||||
|  | 			action.fork; | ||||||
|  | 		} { | ||||||
|  | 			action.(); | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	initParams { | ||||||
|  | 		settings['params'].keysValuesDo { |key, value| | ||||||
|  | 			this.setParam(key, value); | ||||||
|  | 		}; | ||||||
|  | 		settings['paramControls'].keysValuesDo { |key, value| | ||||||
|  | 			parent.setControl(settings['midiChannel'], value, key); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setParam {|paramKey, val, quant| | ||||||
|  | 		var func = { | ||||||
|  | 			parent.control( | ||||||
|  | 				settings['midiChannel'], | ||||||
|  | 				settings['paramControls'][paramKey], | ||||||
|  | 				val | ||||||
|  | 			); | ||||||
|  |  | ||||||
|  | 			settings['params'][paramKey] = val; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		if(quant.notNil) { | ||||||
|  | 			{ | ||||||
|  | 				func.(); | ||||||
|  | 			}.fork(parent.clock, quant:quant); | ||||||
|  | 		} { | ||||||
|  | 			func.(); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	readPreset {|path, checkAvailable=true| | ||||||
|  | 		this.loadPreset(Object.readArchive(path), checkAvailable); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	loadPreset {|preset, checkAvailable=true| | ||||||
|  | 		// copy all settings except notes and paramControls | ||||||
|  | 		preset.keys.reject({|settingKey, i| | ||||||
|  | 			['notes', 'paramControls'].includes(settingKey); | ||||||
|  | 		}).do {|presetKey, i| | ||||||
|  | 			settings[presetKey] = preset[presetKey]; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		// copy notes if it's a patternTrack | ||||||
|  | 		if(preset['patternTrack']) { | ||||||
|  | 			settings['notes'] = preset['notes']; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		// assign all without learn or init | ||||||
|  | 		this.assignAll( | ||||||
|  | 			preset['paramControls'], | ||||||
|  | 			false, | ||||||
|  | 			false, | ||||||
|  | 			checkAvailable | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  | 		this.initParams(); | ||||||
|  |  | ||||||
|  | 		// if(settings['notes'].size > 0) { | ||||||
|  | 		// 	this.on(settings['notes'].asArray[0]); | ||||||
|  | 		// }; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sensor {|sensorKey, val| | ||||||
|  | 		settings['sensorFuncs'][sensorKey].do {|func, i| | ||||||
|  | 			func.(this, val); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	addFunc {|sensorKey, funcKey, func| | ||||||
|  | 		if(parent.sensorKeys.includes(sensorKey)) { | ||||||
|  | 			if(settings['sensorFuncs'].includesKey(sensorKey).not) { | ||||||
|  | 				settings['sensorFuncs'][sensorKey] = IdentityDictionary[]; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			settings['sensorFuncs'][sensorKey][funcKey] = func; | ||||||
|  | 		} { | ||||||
|  | 			"parent doesn't have that sensor key".postln; | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	removeFunc {|sensorKey, funcKey| | ||||||
|  | 		settings['sensorFuncs'][sensorKey].removeAt(funcKey); | ||||||
|  |  | ||||||
|  | 		if(settings['sensorFuncs'][sensorKey].isEmpty) { | ||||||
|  | 			settings['sensorFuncs'].removeAt(sensorKey); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	availableControls { | ||||||
|  | 		^parent.availableControls[settings['midiChannel']].copy; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	save { | ||||||
|  | 		Dialog.savePanel({|path| | ||||||
|  | 			settings.writeArchive(path); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	play { | ||||||
|  | 		if(settings['patternTrack'] && settings['notes'].notEmpty) { | ||||||
|  | 			this.on(settings['notes'].choose); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										127
									
								
								samples/SuperCollider/WarpUtil.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								samples/SuperCollider/WarpUtil.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | |||||||
|  | WarpUtil { | ||||||
|  | 	var <>parent; | ||||||
|  | 	var <curSensor; | ||||||
|  |  | ||||||
|  | 	var <win; | ||||||
|  | 	var <texts; | ||||||
|  | 	var <sensorSlider; | ||||||
|  | 	var <sliders; | ||||||
|  | 	var <updateRout; | ||||||
|  |  | ||||||
|  | 	*new {|argParent| | ||||||
|  | 		^super.new.init(argParent); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	init {|argParent| | ||||||
|  | 		parent = argParent; | ||||||
|  | 		texts = IdentityDictionary[]; | ||||||
|  |  | ||||||
|  | 		this.makeView(); | ||||||
|  | 		this.startUpdate(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	calibrate { | ||||||
|  | 		{ | ||||||
|  | 			parent.doAdjusts.size.do {|i| | ||||||
|  | 				parent.sensorMaxs[i] = 0; | ||||||
|  | 				parent.sensorMins[i] = 9999; | ||||||
|  | 				parent.doAdjusts[i] = true; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			sliders.do {|slider, i| | ||||||
|  | 				if(parent.sensorKeys[i] !== curSensor) { | ||||||
|  | 					slider.valueAction_(0); | ||||||
|  | 					0.1.wait; | ||||||
|  | 					slider.valueAction_(1); | ||||||
|  | 				}; | ||||||
|  | 			} | ||||||
|  | 		}.fork(AppClock); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	stopCalibrate { | ||||||
|  | 		parent.doAdjusts.size.do {|i| | ||||||
|  | 			parent.doAdjusts[i] = false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	makeView { | ||||||
|  | 		var width = 370; | ||||||
|  |  | ||||||
|  | 		if(win.notNil) { | ||||||
|  | 			win.close; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		win = Window("Sensor Inspector", Rect(256, 10, width, 424)).front; | ||||||
|  | 		win.view.addFlowLayout; | ||||||
|  |  | ||||||
|  | 		['sensorVals', 'sensorPrevs', 'sensorMins', 'sensorMaxs'].do {|label, i| | ||||||
|  | 			StaticText(win, (width * 0.5)@20) | ||||||
|  | 				.string_(label.asString); | ||||||
|  |  | ||||||
|  | 			win.view.decorator.nextLine; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 			texts[label] = StaticText(win, (width / 2)@40); | ||||||
|  |  | ||||||
|  | 			if(curSensor.notNil) { | ||||||
|  | 				texts[label].string_( | ||||||
|  | 					"\t" ++ parent.perform(label).at( | ||||||
|  | 						parent.sensorKeys.indexOf(curSensor) | ||||||
|  | 					); | ||||||
|  | 				); | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			win.view.decorator.nextLine; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sensorSlider = EZSlider(win, 280@20, label: curSensor.asString); | ||||||
|  |  | ||||||
|  | 		sliders = parent.sensorKeys.collect { |sensorKey, i| | ||||||
|  | 			EZSlider(win, 280@20, label: sensorKey.asString) | ||||||
|  | 				.action_({|ez| | ||||||
|  | 					NetAddr.localAddr.sendMsg( | ||||||
|  | 						"/prox/" ++ sensorKey, | ||||||
|  | 						ez.value * 100 | ||||||
|  | 					); | ||||||
|  | 				}); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	startUpdate { | ||||||
|  | 		updateRout = Routine { | ||||||
|  | 			inf.do {|i| | ||||||
|  | 				var index; | ||||||
|  |  | ||||||
|  | 				if(curSensor.notNil) { | ||||||
|  | 					index = parent.sensorKeys.indexOf(curSensor); | ||||||
|  |  | ||||||
|  | 					['sensorVals', 'sensorPrevs', 'sensorMins', | ||||||
|  | 						'sensorMaxs'].do {|label, i| | ||||||
|  |  | ||||||
|  | 							texts[label] | ||||||
|  | 							.string_("\t" ++ parent.perform(label)[index]); | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					sensorSlider.value = parent.sensorVals[index].linlin( | ||||||
|  | 						parent.sensorMins[index], | ||||||
|  | 						parent.sensorMaxs[index], | ||||||
|  | 						0, | ||||||
|  | 						1 | ||||||
|  | 					); | ||||||
|  | 				}; | ||||||
|  | 				0.05.wait; | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		updateRout.play(AppClock); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	stopUpdate { | ||||||
|  | 		updateRout.stop(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	curSensor_ {|argCurSensor| | ||||||
|  | 		curSensor = argCurSensor; | ||||||
|  | 		this.makeView(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user