class Oscillator { float speed; //in milliseconds int spawnMillis; int pauseMillis; int beatCount = 0; int[] possibleModes; int mode; //int function; //function to be called by bang-oscillators float position; // between 0 and TWO_PI float value; // is returned, constrained between "low" and "high" float low = -1.0; float high = 1.0; float minBPM, maxBPM; boolean playing, pause, valInvert; Oscillator(float bpm_, int[] osciModes_) { minBPM = 2; maxBPM = 5; bpm(bpm_); possibleModes = osciModes_; mode = possibleModes[int(random(possibleModes.length))]; play(); } void amplitude(float low_, float high_) { low = low_; high = high_; } void frequency(float hertz_) { speed = 1000/hertz_; } void bpm(float bpm_) { speed = int(60 / bpm_ * 1000); } void play() { if (pause) { float pauseTime = millis() - pauseMillis; spawnMillis += pauseTime; pause = false; } else if (!playing) { spawnMillis = millis(); } playing = true; } void pause() { if (playing) { pauseMillis = millis(); pause = true; playing = false; } } void stop() { beatCount = 0; playing = false; value = 0; } boolean beat = false; void update() { if (playing) { while (millis() - spawnMillis > speed*beatCount) { beat = true; beatCount++; if (random(1) > .5) { mode = possibleModes[int(random(possibleModes.length))]; bpm(random(minBPM, maxBPM)); } } float millisToBeat = millis() - spawnMillis - (speed*beatCount); position = map(-millisToBeat, speed, 0, 0, TWO_PI); //position in time between last beat and next beat switch(mode) { case(SINE): value = sin(position); break; case(SAWTOOTH): value = ((position % TWO_PI)-PI)/PI; break; case(SAWTOOTHINVERSE): value = (((position % TWO_PI)-PI)/PI)*-1; break; case(SQUAR): value = sin(position > PI ? 1 : -1); break; case(TRIANG): value = position-PI < 0 ? ((position % TWO_PI)-PI)/PI : (((position % TWO_PI)-PI)/PI)*-1; value+=0.5; value*=2; if (value == 3.0) value = -1; break; case(TAN): value = tan(position); break; case(TANINVERSE): value = tan(position)*-1; break; case(RAMP): value = sin(position) > 0 ? ((position % TWO_PI)-PI)/PI : 0; value+=0.5; value*=2; if (value == 3.0) value = -1; break; case(RAMPINVERSE): value = sin(position) > 0 ? ((position % TWO_PI)-PI)/PI : 0; value+=0.5; value*=2; if (value == 3.0) value = -1; value = value*-1; break; case(RAMPUPDOWN): if (sin(position) <= -1.6666666666) value = -1.6666666666; else if (sin(position) < 1.6666666666 && sin(position) > -1.6666666666) value = sin(position); else if (sin(position) >= 1.6666666666) value = 1.6666666666; value *= 1.5; break; case(RANDOM): //value = random(-1,1); break; default: break; } if (mode != RANDOM) { value = constrain(value, -1.0, 1.0); value = map(value, -1.0, 1.0, low, high); } else if (beat && mode == RANDOM) { beat = false; value = random(low, high); } } } }