// Repo URL: https://github.com/srikumarks/steller
// Demo URL: http://sriku.org/demos/steller_explorer
//
// Code goes here. To evaluate a line, position cursor on
// it and press "Alt-Enter". To evaluate a selection,
// select code and press "Alt-Enter".
//
// Methods of the canvas 2d context can simply be called
// without the "context." object prefix.
//
// Math functions can be used without the "Math." prefix.
//
// For CSS colors, the function rgba(r,g,b,a) is available
// and better suited for use with Animations.
//
// A steller Scheduler instance is now running and its
// methods such as play(), track(), etc. are also available
// without an object prefix.
//
// All the models in the 'models' property of the
// steller Scheduler are also available unprefixed.
// Code goes here. To evaluate a line, position cursor on
// it and press "Alt-Enter". To evaluate a selection,
// select code and press "Alt-Enter".
//
// Methods of the canvas 2d context can simply be called
// without the "context." object prefix.
//
// Math functions can be used without the "Math." prefix.
//
// For CSS colors, the function rgba(r,g,b,a) is available
// and better suited for use with Animations.
//
// A steller Scheduler instance is now running and its
// methods such as play(), track(), etc. are also available
// without an object prefix.
//
// All the models in the 'models' property of the
// steller Scheduler are also available unprefixed.
// Make a parameter that we'll animate.
pos = Param({min: 0.0, max: 1.0, value: 0.0});
xpos = 100;
// The draw function will draw a box at the position given
// by `pos`.
draw = function (clock) {
clearRect(0, 0, canvas.width, canvas.height);
fillStyle = 'blue';
fillRect(xpos, canvas.height * pos.valueOf(), 20, 20);
};
// Start the draw loop.
play(loop(frame(draw)));
// Make a chime model instance and connect it to
// the audio destination.
ch = chime().connect();
// Play a looping pattern and insert a sync object
// at the start of the loop so that we can sync events
// to that.
s = sync();
play(loop(track([
s,
ch.note(72,0.5),
ch.note(79,0.5),
ch.note(84,0.5)
])));
// Run the line below to play a note exactly at
// the start of the above loop.
s.play(ch.note(96,0.5));
// Run the line below to start animating the
// rectangle's position exactly at the start of
// the above note loop.
s.play(loop(track([
fire(function () { xpos = canvas.width * (0.15 + random() * 0.75); }),
anim(pos, 1.5, pos.spec.min, pos.spec.max)
])));
// Reminder: Alt-Enter on a line will evaluate that
// line. If some text is selected, then that will
// be evaluated.
//
// Select all of the text below and hit Alt-Enter
// to run this example.
//
// After evaluating code, positioning cursor within
// a name assigned to a Param will pop up a slider
// to change its value.
// Note: Demonstrating simple temporal recursion to
// produce a sequence of random notes. No visuals,
// only sound.
ch = chime().connect(); // Chime instr connected to destination.
speed = Param({min:0.1, max:5.0, value:1.5, mapping:'log'});
pitch = Param({min:60, max:96, value:72});
durations = [0.25, 0.5, 0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 1.0];
random_duration = function () {
return durations[floor(random() * durations.length)] / speed.value;
};
penta = [0, 2, 4, 7, 9, 12, 14, 16, 19, 21, 24];
penta1 = [0, 2, 4, 7, 9, 12];
major = [0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23, 24];
minor = [0, 2, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 21, 22, 24];
maya = [0, 1, 4, 5, 7, 8, 11, 12];
scale = major;
random_note = dynamic(function (clock) {
return track([
ch.note(pitch.value + scale[floor(scale.length * random())], random_duration()),
random_note
]);
});
play(random_note);
// Reminder: Alt-Enter on a line will evaluate that line.
// If some text is selected, then that will be evaluated.
//
// Select all of the text below and hit Alt-Enter to run
// this example.
//
// This is a simple random note player with some
// synchronized visuals.
ch = chime().connect(); // Chime model connected to destination.
// Choose one from an array at random
choose = function (arr) {
return arr[floor(arr.length * random())];
};
speed = Param({min:0.1, max:5.0, value:1.5, mapping:'log'});
pitch = Param({min:60, max:96, value:72});
durations = [0.25, 0.5, 0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 1.0];
canvas.style.backgroundColor = 'black';
// The draw function will draw a box at the position
// determined by n (note number) and d (duration).
draw = function (n, d) {
return function (clock, t1r, t2r, start) {
fillStyle = rgba(255,255,255,exp(-2*(t1r - start)/d));
fillRect(16 + 24 * n, 32, 24, 128);
};
};
// Clear the frame as the first step in every draw cycle.
play(loop(frame(function (clock) {
clearRect(0, 0, canvas.width, canvas.height);
})));
noteWithVisual = dynamic(function (clock) {
var n = choose(scale);
var d = choose(durations);
var ds = d / speed.value; // Speed-adjusted decay duration.
return track([
spawn(frames(5*ds, draw(n, 2*ds))),
ch.note(pitch.value + n, d)
]);
});
penta = [0, 2, 4, 7, 9, 12, 14, 16, 19, 21, 24];
penta1 = [0, 2, 4, 7, 9, 12];
major = [0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23, 24];
minor = [0, 2, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 21, 22, 24];
maya = [0, 1, 4, 5, 7, 8, 11, 12];
scale = maya;
// Directly control the clock's rate using the speed
// parameter. Notice that there is very little delay in
// response when you change the speed, even if a long note.
// has been just scheduled. Position the text cursor
// within the "speed" variable name to control it.
play(track([rate(speed), loop(noteWithVisual)]));
// Simple audio-in/audio-out copying ScriptProcessor.
// Illustrates the two-buffer delay imposed by a
// ScriptProcessor node in Chrome and Safari.
//
// Change buffer length to vary the delay amount!!
jsn = audioContext.createScriptProcessor(4096, 1, 1);
jsn.onaudioprocess = function (event) {
var inb = event.inputBuffer.getChannelData(0);
var outb = event.outputBuffer.getChannelData(0);
outb.set(inb, 0);
};
ch = chime(); // Instantiate a "chime" instrument.
// ch -> jsn -> destination
ch.connect(jsn);
jsn.connect(audioContext.destination);
// ch -> destination
ch.connect(audioContext.destination);
// You'll hear an echo when you play this.
play(ch.note(72,1.0));