// kijjaz's digital tape verion 0.1 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; 2.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 * Std.fabs(speed) + 1)) $ int => N; while (recording == 1) { for(0 => i; i < N; i++) { input.last() / (i * i * spread * spread + 1) +=> tape[((position + i - N/2 + tape.cap()) % tape.cap() + .5) $ 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(880); .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 .5 => feedback.gain; <<< "hear out the output from the grain processing", "" >>>; B.output => dac; B.tape.cap() - 1 => B.stopPosition; for(int i; i < 1000; i++) { Std.rand2f(0, A.tape.cap() - 1) => A.position; Std.rand2f(0, B.tape.cap() / 6) => B.position; A.rec(); B.play(); Std.rand2f(.25, 2) => A.speed; Std.rand2f(1, 50)::ms => now; A.stop(); B.stop(); } <<< "play the result and loop", "" >>>; 1 => B.looping; 0 => B.position; B.play(); hour => now;