IF3Si/scd/snd_lines.scd

360 lines
12 KiB
Plaintext

/*
This file is part of "Interface Fractures III - Silicon".
Copyright (c) 2015 Luka Prinčič, All rights reserved.
This program is free software distributed under
GNU General Public Licence. See COPYING for more info.
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
snd_lines.scd - deals with converting spectral lines
of silicon into sound in time...
********************************************************** */
(
// FUNCTION procLines: process lines and store/return List --------------------------------------------------------
~procLinesFunc = { // process lines, return na array
arg location = PathName(thisProcess.nowExecutingPath).pathOnly +/+ "../dev/silicon_lines.txt";
var siLines = FileReader.read(path: location, skipBlanks:true, skipEmptyLines:true);
var intensity, minutes, seconds, freq1, freq2, midi1, midi2, red, green, blue;
var threshold = 0;
var linewidth = 3;
var spectrumheight = 750;
var colorpenlen = 40;
var siLinesData, processItem;
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] ];
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;
};
// FUNCTION: display linesData list in a view/window
~viewLinesFunc = {
arg siLinesData = ~siLinesData; // all we need is a List of data
var intensity, minutes, seconds, freq1, freq2, midi1, midi2, red, green, blue;
var layer, alpha;
// some drawing variables
var threshold = 0;
var linewidth = 3;
var spectrumheight = 750;
var colorpenlen = 40;
var alphamin = 10;
var peny, penx;
var color;
var time, time_end = 60*37+5;
// View/Window starts here
var w = Window("TempSpectre", Rect(600, 5, width:560, height:spectrumheight));
postln(~siLinesData);
w.view.background_(Color.black);
w.drawFunc = {
Pen.smoothing_(false);
Pen.translate(0,0);
Pen.fillColor = Color.white;
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)));
Pen.stroke; // draw the path
}); // end of siLinesData.do
}; // end of drawFunc{}
w.refresh;
w.front;
}; // end of viewLines function
)
// process lines, store to a List
~siLinesData = ~procLinesFunc.value;
// sort 2D
~siLinesData = ~siLinesData.sortBy(0);
(
// display table of all data to post window
~siLinesData.do({ |item, i|
post(i + "");
item.do({ |value, i|
post(i);
post(":");
post(value);
post(" ");
});
post("\n");
});
)
// show a window/view with lines - score
~viewLinesFunc.value;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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
Out.ar(0, sig); // output
postln("\n~~~ adding SynthDef: siliconSynth ...");
}).add;
// -----------------------------------------------------------------------------
postln("~~~ loading mainTimeline routine");
~mainTimeline = Routine({
var delta, playhead, frequency, amp, step=0,
nextdelta, nextplayhead, nextfrequency, nextamp,
frequency_alt, nextfrequency_alt;
while {
step < siLines.size;
} {
// exposition
frequency = siLines[step][0].asFloat.linexp(3900, 7200, 16000, 40);
frequency_alt = siLines[step][0].asFloat.linexp(3900, 7200, 40, 16000);
nextfrequency = siLines[step+1][0].asFloat.linexp(3900, 7200, 16000, 40);
nextfrequency_alt = siLines[step+1][0].asFloat.linexp(3900, 7200, 40, 16000);
nextplayhead = siLines[step+1][0].asFloat.linlin(3905.52, 7193.9, 0, (60*37+5));
playhead = siLines[step][0].asFloat.linlin(3905.52, 7193.9, 0, (60*37+5));
delta = nextplayhead - playhead;
amp = siLines[step][1].asInt * 0.001;
nextamp = siLines[step+1][1].asInt * 0.001;
nextdelta = siLines[step+2][0].asFloat.linlin(3905.52, 7193.9, 0, (60*37+5)) - nextplayhead;
//action::documentation
post("\n~" + step + "| ");
post((playhead/60).round(1));
post(":");
post((playhead%60).round(1));
post(" | ");
post(siLines[step][0]);
post( "nm | " );
post(frequency.round(1));
post("Hz | ");
post(frequency_alt.round(1));
post("Hz | ");
post(amp.ampdb.round(1));
post("dB \\ ");
post(delta.round(1));
postln("s");
post(" ");
post(delta.round(1));
post("s / ");
post(nextfrequency.round(1));
post("Hz | ");
post(nextfrequency_alt.round(1));
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;
*/