/** *

Countdown

*

by Benito

*

A countdown to… something. With incessant ticking and eerie wind.

*

Not the most interactive piece I've ever done, but it's kind of pleasant.

* *

Pressing keys will trigger certain notes either in the bass or melody, and may trigger short patterns within the next beat.

*/ import net.beadsproject.beads.core.*; import net.beadsproject.beads.data.*; import net.beadsproject.beads.events.*; import net.beadsproject.beads.ugens.*; AudioContext ac; long diff, target; double secs; int currframe = 0; Panner leftp, rightp, centerp, extrap, halfleftp; Envelope tick, windfreq, windgain, windpan; int plan = 0; int cuednote = 0, cuedbass = 0, cuedplan = -1; int passedsecs = 0; int startfull = 25; float[] thescale = {1, 9f/8, 6f/5, 5f/4, 45f/32, 1.5, 27f/16, 7f/8}; void setup() { size(600, 400); frameRate(60); Calendar c = Calendar.getInstance(); c.set(2012, Calendar.DECEMBER, 21, 0, 0, 0); target = c.getTimeInMillis(); ac = new AudioContext(256); tick = new Envelope(ac, 0); leftp = new Panner(ac, -.9); rightp = new Panner(ac, .9); centerp = new Panner(ac, 0); centerp.addInput(tick); extrap = new Panner(ac, .6); halfleftp = new Panner(ac, -.6); windfreq = new Envelope(ac, 440); windpan = new Envelope(ac, .1); windgain = new Envelope(ac, 0); RandomPWM windpwm = new RandomPWM(ac, RandomPWM.RAMPED_NOISE, 1000, 5000, 1); Noise n = new Noise(ac); BiquadFilter windbf = new BiquadFilter(ac, 1, BiquadFilter.BP_PEAK); windbf.addInput(n); windbf.setFrequency(windfreq).setQ(25); Function wind = new Function(windbf, windpwm, windgain) { public float calculate() { return (.6 + x[1] * .2) * x[2] * x[0]; } }; Panner windp = new Panner(ac, windpan); windp.addInput(wind); Gain mg = new Gain(ac, 2, .3); mg.addInput(leftp); mg.addInput(rightp); mg.addInput(centerp); mg.addInput(extrap); mg.addInput(halfleftp); mg.addInput(windp); ac.out.addInput(mg); Bead ticker = new Bead() { int currtick = 1; int lastparts = 0; int modder = 48; int mainnote = 0; int secondnote = 0; int passedsecs = 0; boolean endo = false; public void messageReceived(Bead mess) { diff = target - System.currentTimeMillis(); int parts = (int)(((diff % 1000) + 1000) % 1000); secs = diff / 1000; if(diff < 5000 && endo == false) { endo = true; Envelope freq = new Envelope(ac, 50); freq.addSegment(49, 4000); freq.addSegment(48, 1200); freq.addSegment(43, 2000); freq.addSegment(42, 1000); freq.addSegment(35, 12000); WavePlayer w = new WavePlayer(ac, freq, Buffer.SQUARE); Envelope env = new Envelope(ac, 0); Gain g = new Gain(ac, 1, env); g.addInput(w); env.addSegment(.5, 10); env.addSegment(.5, 7000); env.addSegment(0, 12000); env.addSegment(0, 200, new KillTrigger(g)); centerp.addInput(g); } if(parts > lastparts) { currtick = 0; passedsecs++; plan = 0; if(passedsecs > startfull) { if(cuedplan >= 0) { plan = cuedplan; cuedplan = -1; } else { if(passedsecs % 7 == 0) plan++; if(passedsecs % 5 == 0) plan = plan + 2; } } if(cuednote > 0) { mainnote = cuednote; secondnote = mainnote + 5; cuednote = 0; } else { mainnote = (int)random(14, 32); secondnote = mainnote + (int)random(4, 6); } } lastparts = parts; //tick if(currtick == 24 || currtick == 0) { float lev = min(max(((float)passedsecs - 4) / 14, 0), 1); if(currtick > 0) lev *= .5; tick.clear(); tick.addSegment(lev, .2); tick.addSegment(lev * -.2, .3); tick.addSegment(lev * .3, .3); tick.addSegment(lev * -.5, .3); tick.addSegment(lev * .25, .3); tick.addSegment(lev * -.15, .3); tick.addSegment(lev * .1, .3); tick.addSegment(lev * -.05, .3); tick.addSegment(lev * 0, .3); } // extra if(currtick == 36 && passedsecs > 16) { if(cuedbass > -1) { ding(cuedbass, 1000, extrap); cuedbass = -1; } else { ding((int)random(0, 18), 1000, extrap); } } if(passedsecs > startfull) { if(currtick == 0) { ding(mainnote, 1000, centerp); } else { if(plan == 1 && currtick == 24) { ding(secondnote, 1200, halfleftp); } else if (plan == 2) { if(currtick == 16) { ding(secondnote, 1000, leftp); } else if(currtick == 32) { ding(secondnote, 2000, rightp); } } else if (plan == 3) { if(currtick == 12) { ding(secondnote, 1000, leftp); } else if(currtick == 24) { ding(secondnote, 1000, rightp); } else if(currtick == 36) { ding(secondnote, 2000, leftp); } } } } currtick++; } }; Clock clock = new Clock(ac, 1000f / 48); clock.setTicksPerBeat(1); clock.addMessageListener(ticker); ac.out.addDependent(clock); ac.start(); PFont font = loadFont("Aharoni-Bold-48.vlw"); textFont(font); textAlign(RIGHT, CENTER); } void draw() { background(0); diff = target - System.currentTimeMillis(); secs = (double)((double)diff / 1000); int mills = (int)(Math.abs(diff) % 1000); long isecs = (long)Math.abs(secs); int mins = (int)(isecs / 60); isecs %= 60; int hours = mins / 60; mins %= 60; String tim = ""; if(diff < 0) tim += "+"; tim += hours + ":"; if(mins < 10) tim += "0"; tim += mins + ":"; if(isecs < 10) tim += "0"; tim += isecs + "."; if(mills < 10) tim += "0"; if(mills < 100) tim += "0"; tim += mills; if(diff < 0) { fill(255, 0, 0); } else if(hours < 1 && mills >= 500) { fill(100, 20, 20); } else { fill(255); } text(tim, 481, height * .7); float h = (float)mills / 1000; float x, y; int xb = 400; int yb = 270; switch(plan) { case 2: if(h < .333) { x = xb + (h / .333) * 57; y = yb - (h / .333) * 100; } else if(h < .667) { x = xb + 57 - ((h - .334) / .333) * 114; y = yb - 100; } else { x = xb - ((1 - h) / .333) * 57; y = yb - ((1 - h) / .333) * 100; } break; case 3: if(h < .25) { x = xb + (h / .25) * 57; y = yb - (h / .25) * 100; } else if(h < .5) { x = xb + 57 - ((h - .25) / .25) * 114; y = yb - 100; } else if(h < .75) { x = xb - 57 + ((h - .5) / .25) * 114; y = yb - 100; } else { x = xb + ((1 - h) / .25) * 57; y = yb - ((1 - h) / .25) * 100; } break; default: x = xb; y = yb - (int)(h * (1 - h) * 400); break; } int w = (int)max((60 * h * (h - 1) + 5), 0); int ht = 16 - (int)(1.5 * w); w += 16; //h = h * (1 - h) * 4; ellipseMode(CENTER); ellipse((int)x, (int)y, w, ht); } void ding(int note, float dur, UGen target) { float freq = 54 * pow(2, note / thescale.length) * thescale[note % thescale.length] + 1; //println(freq); Envelope env = new Envelope(ac, 0); Envelope freqEnv = new Envelope(ac, freq * 1.1 + 10); freqEnv.addSegment(freq, 80, .5, null); WavePlayer w = new WavePlayer(ac, freqEnv, Buffer.SINE); Gain g = new Gain(ac, 1, env); g.addInput(w); env.addSegment(.5, 10); env.addSegment(0, dur, .5, null); env.addSegment(0, 100, new KillTrigger(g)); target.addInput(g); } void mouseMoved() { windfreq.clear(); int note = ((height - mouseY) / 18) + 25; float freq = 81 * pow(2, note / thescale.length) * thescale[note % thescale.length] + 1; windfreq.clear(); windfreq.addSegment(freq, 1000, .5, null); windpan.clear(); windpan.addSegment((float)mouseX / width * 2 - 1, 500); } void mouseClicked() { windgain.clear(); float v = windgain.getValue(); windgain.addSegment(.5 * (1 + .6 / (.6 + v)), 500); windgain.addSegment(0, 8300); } void keyPressed() { int n = key % 36; if(n < 18) { cuedbass = n; } else { cuednote = n - 4; } int p = key % 8; if(p > 3) p = 0; cuedplan = p; if(key == ESC) key = 0; }