// kijjaz's digital tape verion 0.4 alpha /* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ class kjzdtWrite { float tape[(second/samp) $ int]; 0.0 => float position; 1.0 => float speed; 6.0 => float spread; 0 => int recording; Gain input => blackhole; Event Estart; Event Estop; int i; int N; spork ~ writingMachine(); spork ~ checkStop(); fun void rec() { Estart.broadcast(); } fun void stop() { Estop.broadcast(); } fun void newTape(int s) { new float[s] @=> tape; } fun void newTape(dur s) { new float[(s / samp) $ int] @=> tape; } fun void writingMachine() { while(true) { Estart => now; 1 => recording; Math.ceil((spread / (speed*speed + 1) + 1)) $ int => N; while (recording == 1) { for(0 => i; i < N; i++) { input.last() / (((i-N/2) * (i-N/2)) $ float / spread + 1) / (speed*speed+1) +=> tape[((position + i - N/2 + tape.cap()) % tape.cap()) $ int]; } samp => now; speed +=> position; while(position < 0) tape.cap() +=> position; while(position > tape.cap() - 1) tape.cap() -=> position; } } } fun void checkStop() { while(true) { Estop => now; 0 => recording; } } } class kjzdtSimpleRead { float tape[1]; 0.0 => float position; 1.0 => float speed; 0.0 => float startPosition; 0.0 => float stopPosition; 0 => int looping; 0 => int playing; Impulse output; Event Estart; Event Estop; spork ~ readingMachine(); fun void play() { Estart.broadcast(); } fun void stop() { Estop.broadcast(); } fun void setTape(float newTape[]) { newTape @=> tape; } fun void readingMachine() { while(true) { Estart => now; 1 => playing; while(playing == 1) { tape[((position + .5) $ int + tape.cap()) % tape.cap()] => output.next; samp => now; speed +=> position; while(position < 0) tape.cap() +=> position; while(position > tape.cap() - 1) tape.cap() -=> position; if (position > stopPosition) { if (looping == 1) startPosition => position; else 0 => playing; } } } } fun void checkStop() { while(true) { Estop => now; 0 => playing; } } } // test code kjzdtWrite A; kjzdtSimpleRead B; A.newTape(5::second); ms => now; // wait a bit SinOsc s => A.input; // start to record from a sound source s.freq(2200); .1 => s.gain; A.rec(); // start recording 500::ms => now; // record for 1 ms A.stop(); // stop recording s =< A.input; // stop recording from the source for now B.setTape(A.tape); B.output => Gain feedback => A.input; // record back from the same tape .2 => feedback.gain; <<< "hear out the output from the grain processing", "" >>>; B.output => dac; B.tape.cap() - 1 => B.stopPosition; for(int i; i < 2000; i++) { Math.pow(Std.rand2f(0, 1), 2) * (A.tape.cap() - 1) => A.position; Math.pow(Std.rand2f(0, 1), 2) * (A.tape.cap() - 1) => B.position; A.rec(); B.play(); Std.rand2f(.25, 4) => A.speed; Std.rand2f(1, 30)::ms => now; A.stop(); B.stop(); } second => now; <<< "play the result and loop", "" >>>; 1 => B.looping; 0 => B.position; B.play(); hour => now;