IF3Si/scd/snd_lines.scd

451 lines
13 KiB
Plaintext
Raw Normal View History

2015-09-09 14:03:24 +02:00
/*
2015-09-09 15:13:45 +02:00
This file is part of "Interface Fractures III - Silicon".
2015-09-09 15:18:56 +02:00
Copyright (c) 2015 Luka Prinčič, All rights reserved.
2015-09-09 15:13:45 +02:00
This program is free software distributed under
GNU General Public Licence. See COPYING for more info.
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
2015-09-09 14:03:24 +02:00
snd_lines.scd - deals with converting spectral lines
of silicon into sound in time...
********************************************************** */
2015-09-09 16:06:49 +02:00
// function procLines: process lines and store/return List
2015-09-09 16:41:44 +02:00
postln("~~~ function ~procLinesFunc ...");
2015-09-09 15:13:45 +02:00
~procLinesFunc = { // process lines, return na array
arg location = PathName(thisProcess.nowExecutingPath).pathOnly +/+ "../dat/silicon_lines.txt";
2015-09-09 15:13:45 +02:00
var siLines = FileReader.read(path: location, skipBlanks:true, skipEmptyLines:true);
2015-09-09 14:03:24 +02:00
var intensity, minutes, seconds, freq1, freq2, midi1, midi2, red, green, blue;
2015-09-09 15:13:45 +02:00
var threshold = 0;
var linewidth = 3;
var spectrumheight = 750;
var colorpenlen = 40;
var siLinesData, processItem;
2015-09-09 14:03:24 +02:00
var colors = [ // these are taken from http://astro.u-strasbg.fr/~koppen/discharge/discharge.html
[ 3800.0, 0, 0, 0],
[ 4000.0, 150, 0, 150],
[ 4400.0, 120, 0, 255], // violet
[ 4500.0, 0, 0, 255], // blue
[ 4800.0, 0, 255, 255], // cyan
[ 5200.0, 0, 255, 0], // green
[ 5800.0, 255, 255, 0], // yellow
[ 6500.0, 255, 0, 0], // red
[ 7000.0, 80, 0, 0],
[ 7300.0, 0, 0, 0] ];
2015-09-09 15:13:45 +02:00
siLinesData = List.newClear(0);
processItem = { |item, i, reverse=false, layer=0, tscale=1, toffset=0|
if((item[1].asInt > threshold) && (item[0].asInt < 6741) && (item[0].asInt > 3950), {
var color;
var time, time_end = 60*37+5;
var alpha = item[1].asFloat.linlin(0, 1000, 0, 255);
intensity = item[1].asInt;
// time
if(reverse == false,
// then
{ time = (item[0].asFloat.linlin(3950, 6741, 0, time_end)); },
// else:
{ time = (item[0].asFloat.linlin(3950, 6741, time_end, 0)); } );
time = time * tscale ;
time = time + (toffset * time_end);
minutes = (time / 60).round(1);
seconds = (time % 60).round(1);
freq1 = item[0].asFloat.linexp(3900, 7200, 16000, 40 ).asInt;
freq2 = item[0].asFloat.linexp(3900, 7200, 40, 16000 ).asInt;
midi1 = item[0].asFloat.linlin(3900, 7200, 0, 12 ).round(0.01);
midi2 = item[0].asFloat.linlin(3900, 7200, 12, 0 ).round(0.01);
colors.do({ |colordb, i|
var thisboundary = colors[i][0];
if (i+1 < colors.size, {
var nextboundary = colors[i+1][0];
if ((item[0].asFloat > thisboundary) && (item[0].asFloat < nextboundary), {
var red = colors[i][1] + ( ( (colors[i+1][1] - colors[i][1]) / (colors[i+1][0] - colors[i][0]) )
* (item[0].asFloat - colors[i][0]) );
var green = colors[i][2] + ( ( (colors[i+1][2] - colors[i][2]) / (colors[i+1][0] - colors[i][0]) )
* (item[0].asFloat - colors[i][0]) );
var blue = colors[i][3] + ( ( (colors[i+1][3] - colors[i][3]) / (colors[i+1][0] - colors[i][0]) )
* (item[0].asFloat - colors[i][0]) );
var color = Color.new255(red.round(1),green.round(1),blue.round(1), alpha);
var colorHSV = color.asHSV;
// add line data as a List to the siLinesData List
siLinesData.add(List[
time, // [0]
layer, // [1]
item[0], // [2]
intensity, // [3]
freq1, freq2, // [4], [5]
midi1, midi2, // [6], [7]
// R, G, B, [8] [9] [10]
red.round(1), green.round(1), blue.round(1),
// H, S, V, Alpha [11][12][13][14]
(colorHSV[0] * 360).round(1), // hue
(colorHSV[1] * 100).round(1), // saturation
(colorHSV[2] * 100).round(1), // value
(colorHSV[3] * 100).round(1) // ALPHA
]); // end of siLinesData.add
}); // endif wavelength inside this boundary
}); // endif below last item (prevents error going beyond List's boundary)
}); // end colors.do
}); // endif threshold and inside min/max in the spectrum
}; // end of function processItem
// process lines four times with offsets and scales with golden ratios
siLines.do({ |item, i| processItem.value(item, i, layer:0); });
siLines.do({ | item, i| processItem.value(item, i, layer:1, reverse:true,
tscale:0.618); });
siLines.do({ | item, i| processItem.value(item, i, layer:1, reverse:true,
tscale: 0.618.squared, toffset:0.618); });
siLines.do({ | item, i| processItem.value(item, i, layer:2, reverse:false,
tscale: 0.618.cubed, toffset:(0.618.squared-0.618.cubed)+0.618); });
// return ?
siLinesData;
};
2015-09-24 09:28:56 +02:00
// evaluate: process lines, store to a List
2015-09-09 16:41:44 +02:00
postln("~~~ process lines, store to a list: ~siLinesData, sort ...");
2015-09-09 16:06:49 +02:00
~siLinesData = ~procLinesFunc.value;
// sort 2D
~siLinesData = ~siLinesData.sortBy(0);
2015-09-09 15:13:45 +02:00
// FUNCTION: display linesData list in a view/window
2015-09-09 16:41:44 +02:00
postln("~~~ function ~viewLinesFunc ...");
2015-09-09 15:13:45 +02:00
~viewLinesFunc = {
arg siLinesData = ~siLinesData; // all we need is a List of data
2015-09-09 16:41:44 +02:00
var intensity, layer, alpha, peny, penx, color, time, swin;
2015-09-09 14:03:24 +02:00
var threshold = 0;
var linewidth = 3;
var spectrumheight = 750;
var colorpenlen = 40;
2015-09-09 15:13:45 +02:00
var alphamin = 10;
2015-09-09 16:41:44 +02:00
var time_end = 60*37+5;
2015-09-09 15:13:45 +02:00
2015-09-09 16:41:44 +02:00
// View/Window starts here
swin = Window("TempSpectre", Rect(600, 5, width:560, height:spectrumheight));
swin.view.background_(Color.black);
swin.drawFunc = {
2015-09-09 14:03:24 +02:00
Pen.smoothing_(false);
Pen.translate(0,0);
Pen.fillColor = Color.white;
2015-09-09 15:13:45 +02:00
Pen.fillRect(Rect(colorpenlen * 3, 0, w.bounds.width - (colorpenlen * 3), spectrumheight));
siLinesData.do({ |ldata, i|
alpha = ldata[14].asFloat.linlin(0, 100, alphamin, 255);
layer = ldata[1].asInt;
spectrumheight = w.bounds.height;
intensity = ldata[3].asInt;
time = ldata[0];
color = Color.new255(ldata[8], ldata[9], ldata[10], alpha);
peny = time.linlin(0, time_end, 0, spectrumheight);
penx = 2 - layer * colorpenlen;
// colored lines on black
Pen.fillColor = color;
Pen.fillRect(Rect(penx, peny, colorpenlen, alpha.linlin(0,255,1,linewidth)));
// black/gray lines on white
Pen.fillColor = Color.black.alpha_(alpha.linlin(0,255,0,1));
Pen.fillRect(Rect( colorpenlen*3, peny,
w.bounds.width - (colorpenlen * 3) * intensity.linlin(0,1000,0,1),
alpha.linlin(0,255,1,linewidth)));
2015-09-09 14:03:24 +02:00
2015-09-09 15:13:45 +02:00
Pen.stroke; // draw the path
2015-09-09 14:03:24 +02:00
2015-09-09 15:13:45 +02:00
}); // end of siLinesData.do
}; // end of drawFunc{}
2015-09-09 16:41:44 +02:00
swin.refresh;
swin.front;
2015-09-09 15:13:45 +02:00
}; // end of viewLines function
2015-09-24 09:28:56 +02:00
// this could be bound to a button,
// or ideally expanded to an animated timeline
// and included in main window...:
2015-09-09 14:03:24 +02:00
2015-09-24 09:28:56 +02:00
// evaluate: show a window/view with lines - score
// ~viewLinesFunc.value;
2015-09-09 14:03:24 +02:00
2015-09-09 16:06:49 +02:00
2015-09-24 09:28:56 +02:00
2015-09-09 14:03:24 +02:00
~postLines = { // print data in post window, NICELY!
// display table of all data to post window
~siLinesData.do({ |item, i|
var minutes = (item[0]/60).asInt;
var seconds = (item[0]%60).asInt;
2015-09-24 09:28:56 +02:00
if (item[3].asInt > 199, {
// post("[");
// post(i.asString.padLeft(3));
// post("] ");
2015-09-24 09:28:56 +02:00
// time
if (minutes < 10, { minutes = "0" ++ minutes.asString;});
post(minutes);
post(":");
if (seconds < 10, { seconds = "0" ++ seconds.asString; });
post(seconds);
post(" ");
2015-09-24 09:28:56 +02:00
// wavelength
post(item[2]);
post("Å ");
2015-09-24 09:28:56 +02:00
// layer
post(item[1]);
post(" ");
2015-09-24 09:28:56 +02:00
// intensity
post(item[3].asString.padLeft(4));
post(" ");
// frequency
post(item[4].asString.padLeft(5));
post("Hz ");
post(item[5].asString.padLeft(5));
post("Hz ");
2015-09-24 09:28:56 +02:00
// midi/tone
post(item[6].asString.padLeft(5)); // midi1
post(" ");
post(item[7].asString.padLeft(5)); // midi2
post(" | ");
2015-09-24 09:28:56 +02:00
// RGB
post(item[8].asString.padLeft(3));
post(" ");
post(item[9].asString.padLeft(3));
post(" ");
post(item[10].asString.padLeft(3));
2015-09-24 09:28:56 +02:00
// HSV/B
// post(" | ");
// post(item[11].asString.padLeft(3));
// post(" ");
// post(item[12].asString.padLeft(3));
// post(" ");
// post(item[13].asString.padLeft(3));
post(" | ");
post(item[14] //.asString.padLeft(3)
);
/*
post(" |||");
item.do({ |value, i|
//post(i);
post(Char.tab);
post(value.asFloat.round(1));
post(" ");
});*/
post("\n");
});
2015-09-09 14:03:24 +02:00
});
};
2015-09-24 09:28:56 +02:00
// evaluate function
//~postLines.value;
2015-09-09 16:06:49 +02:00
2015-09-09 14:03:24 +02:00
2015-09-09 15:13:45 +02:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2015-09-09 14:03:24 +02:00
// move to sdefs.scd at one point? --------------------------------------------
SynthDef(\siliconSynth, { |freq = 440, amp = 0.2, attack = 1, release = 1|
var sig, env, frequency, amply;
frequency = [freq * 1.005, freq];
amply = amp * 0.3;
env = EnvGen.kr(Env.perc(attack, release, 1, [10, -10]), doneAction: 2); // ENVELOPE
sig // -----------------------------------------------------------------------------------------
= SinOsc.ar( freq: frequency, mul: amply * 0.9)
+ SinOsc.ar( freq: frequency * 0.5 * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply)
+ SinOsc.ar( freq: frequency * 0.25 * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply)
+ Saw.ar( freq: frequency * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply * 0.5)
+ Saw.ar( freq: frequency * 0.5 * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply * 0.5)
+ Saw.ar( freq: frequency * 0.25 * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply * 0.5)
+ Pulse.ar( freq: frequency * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply * 0.5)
+ Pulse.ar( freq: frequency * 0.5 * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply * 0.5)
+ Pulse.ar( freq: frequency * 0.24 * LFNoise1.kr(0.1).linlin(-1, 1, 0.998, 1.002), mul: amply * 0.5)
+ BPF.ar(BrownNoise.ar(), freq: frequency * LFNoise1.kr(0.01).linlin(-1, 1, 0.8, 1.2), rq: 0.1)
+ BPF.ar(WhiteNoise.ar(), freq: frequency * 0.5 * LFNoise1.kr(0.01).linlin(-1, 1, 0.8, 1.2), rq: 0.1)
+ BPF.ar(Crackle.ar(SinOsc.kr(0.1).linlin(-1, 1, 0.8, 2)), frequency * LFNoise1.kr(0.01).linlin(-1, 1, 0.8, 1.2), rq:0.1, mul:2)
+ BPF.ar(Crackle.ar(SinOsc.kr(0.1).linlin(-1, 1, 0.8, 2)), frequency * 0.5 * LFNoise1.kr(0.01).linlin(-1, 1, 0.8, 1.2), rq:0.1, mul:2)
; // -------------------------------------------------------------------------------------------
sig = sig * env; // envlope the final sound
2015-09-24 09:28:56 +02:00
Out.ar(2, sig); // output
2015-09-09 14:03:24 +02:00
postln("\n~~~ adding SynthDef: siliconSynth ...");
}).add;
// -----------------------------------------------------------------------------
postln("~~~ loading mainTimeline routine");
2015-09-09 16:41:44 +02:00
post(" ");
2015-09-09 14:03:24 +02:00
~mainTimeline = Routine({
2015-09-24 09:28:56 +02:00
//arg layer = 0;
2015-09-09 14:03:24 +02:00
var delta, playhead, frequency, amp, step=0,
nextdelta, nextplayhead, nextfrequency, nextamp,
frequency_alt, nextfrequency_alt, siLines;
2015-09-09 16:41:44 +02:00
siLines = ~siLinesData;
postln(siLines);
postln("debug");
2015-09-09 14:03:24 +02:00
while {
step < siLines.size;
2015-09-24 09:28:56 +02:00
//layer == siLines[step]
2015-09-09 14:03:24 +02:00
} {
// exposition
2015-09-09 17:53:40 +02:00
frequency = siLines[step][4].asFloat;
frequency_alt = siLines[step][5].asFloat;
playhead = siLines[step][0].asFloat;
nextfrequency = siLines[step+1][4].asFloat;
nextfrequency_alt = siLines[step+1][5].asFloat;
nextplayhead = siLines[step+1][0].asFloat;
2015-09-09 14:03:24 +02:00
delta = nextplayhead - playhead;
2015-09-09 17:53:40 +02:00
amp = siLines[step][3].asInt * 0.001;
nextamp = siLines[step+1][3].asInt * 0.001;
nextdelta = siLines[step+2][0].asFloat - nextplayhead;
2015-09-09 14:03:24 +02:00
//action::documentation
2015-09-09 20:13:15 +02:00
post("\n~" + step.asString.padLeft(3));
2015-09-09 19:23:55 +02:00
post("|");
2015-09-09 17:53:40 +02:00
post(siLines[step][1]);
2015-09-09 19:23:55 +02:00
post("| ");
2015-09-09 20:14:30 +02:00
post((playhead/60).round(1).asString.padLeft(2));
2015-09-09 14:03:24 +02:00
post(":");
post((playhead%60).round(1).asString.padLeft(2));
2015-09-09 14:03:24 +02:00
post(" | ");
2015-09-09 19:23:55 +02:00
// post(siLines[step][2]);
// post( "nm | " );
2015-09-09 20:13:15 +02:00
post(frequency.round(1).asString.padLeft(5));
2015-09-09 14:03:24 +02:00
post("Hz | ");
2015-09-09 20:13:15 +02:00
post(frequency_alt.round(1).asString.padLeft(5));
2015-09-09 14:03:24 +02:00
post("Hz | ");
post(amp.ampdb.round(1));
post("dB \\ ");
post(delta.round(1));
postln("s");
2015-09-09 19:23:55 +02:00
post(" |");
post(siLines[step+1][1]);
2015-09-09 17:53:40 +02:00
post("| ");
2015-09-09 14:03:24 +02:00
post(delta.round(1));
post("s / ");
2015-09-09 20:13:15 +02:00
post(nextfrequency.round(1).asString.padLeft(5));
2015-09-09 14:03:24 +02:00
post("Hz | ");
2015-09-09 20:13:15 +02:00
post(nextfrequency_alt.round(1).asString.padLeft(5));
2015-09-09 14:03:24 +02:00
post("Hz | ");
post(nextamp.ampdb.round(1));
post("dB \\ ");
post(nextdelta.round(1));
postln("s");
Synth(\siliconSynth, [
freq: nextfrequency,
amp: nextamp,
attack: delta,
release: nextdelta
]);
Synth(\siliconSynth, [
freq: nextfrequency_alt,
amp: nextamp,
attack: delta,
release: nextdelta
]);
// epilogue
step = step + 1;
delta.yield;
}
});
TempoClock.default.tempo = 1; // beats/sec /BPS
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEBUG
//~siLines = FileReader.read(path:"../dev/silicon_lines.txt", skipBlanks:true, skipEmptyLines:true);
//~siLines[124][0].postln;
//siLines.size.postln;
//r.next;
//r.stop;
// if (siLines[step-1].notNil, {
// playhead = siLines[step-1][0].asFloat.linlin(3900, 7200, 0, (60*37+5)); // at the end these are seconds!
// }, { playhead = 0 });
// nextdelta = siLines[step][0].asFloat.linlin(3900, 7200, 0, (60*37+5)) - playhead;
// delta = playhead - prevplayhead;
// prevplayhead = playhead;
/*
post("t:" + item[0].asFloat.linlin(3900, 7200, 0, 12 ).asStringPrec(5) + Char.tab ); // tone
post("t:" + item[0].asFloat.linlin(3900, 7200, 12, 0 ).asStringPrec(5) ); // tone reverse
//{SinOsc.ar((item[0].asFloat.linlin(3900, 7200, 0, 12)+60).midicps, mul:item[1].asInt * 0.000005)}.play;
/*{LFPar.ar((
item[0].asFloat.linlin(3900, 7200, 0, 12)
+ ( ( (i+1) % 1) * 12) + 60).midicps,
mul:(item[1].asInt.linlin(0, 1000, 0.0, 0.5) + item[1].asInt.linexp(0, 1000, 0.01, 0.5)) * [i%2,abs(i%2-1)] * 0.05)}.play;
*/
//{SinOsc.ar(item[0].asFloat.linexp(3900, 7200, 20000, 40 ).asInt, mul:item[1].asInt * 0.000005)}.play;
{SinOsc.ar(item[0].asFloat.linexp(3900, 7200, 20000, 40).asInt, mul:item[1].asInt * 0.00005)}.play;
*/