xxxxxxxxxx
340
//visual
var n = 40;
var d0 = 100;
var d;
var phase = 0;
var frame; //instance of Frame class controlled by hihat
var rectTrails; //number of rect trails controlled by hihatSlider
var kickSlider;
var bpmSlider;
var hihatSlider;
var randomizeButton;
var playButton;
var play = false;
var notes = ""; //for printing randomized notes
var bpm = 120;
Tone.Transport.bpm.value = bpm;
var q = 5; //Q of MonoSynth filter env
var decay = 0.1; //decay of MonoSynth flter env
//hihat sample
var hihat = new Tone.Player("hats-2.wav");
hihat.volume.value = -15;
var reverb = new Tone.JCReverb(0).connect(Tone.Master);
hihat.chain(reverb);
//kickdrum generated by MembraneSynth
var kick = new Tone.MembraneSynth({
"pitchDecay": 0.05,
"octaves": 5,
"oscillator": {
"type": "sine"
},
"envelope": {
"attack": 0.001,
"decay": 0.4,
"sustain": 0.01,
"release": 1.4,
"attackCurve": "exponential"
}
});
var kickFilter = new Tone.Filter({
"type": "highpass",
"frequency": 0, //frequency controlled by kickslider
"rolloff": -24,
"Q": 1,
"gain": 0
}).toMaster();
kick.connect(kickFilter);
//top synth line
var synth = new Tone.MonoSynth({
"oscillator": {
"type": "sawtooth"
},
"filter": {
"Q": q, //resonance at the cutoff frequency
"type": "lowpass",
"rolloff": -24
},
"envelope": {
"attack": 0.0001,
"decay": 0.2,
"sustain": 0.5,
"release": 0.5
},
"filterEnvelope": {
"attack": 0.001,
"decay": decay, //0.2 - 2s
"sustain": 0,
"min": 200,
"max": 2000
}
})
var synthComp = new Tone.Compressor(-80, 1000).toMaster(); //threshold, ratio
synth.connect(synthComp);
//for randomizing
var synthNotesSet = ["C2", "C#2", "D2", "D#2", "E2", "F2", "F#2",
"G2", "G#2", "A2", "A#2", "B2", "C3", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
//for initializing
var timeNotes = [
["0:0:0", "Bb2"],
["0:0:1", 0],
["0:0:2", "A2"],
["0:0:3", "A2"],
["0:1:0", "G#2"],
["0:1:1", "G#2"],
["0:1:2", "G#2"],
["0:1:3", "F2"],
["0:2:0", 0],
["0:2:1", "F2"],
["0:2:2", "E2"],
["0:2:3", 0],
["0:3:0", 0],
["0:3:1", "F2"],
["0:3:2", "E2"],
["0:3:3", 0],
];
var fmSynth = new Tone.FMSynth({
"harmonicity": 5,
"modulationIndex": 10,
"detune": 0, //alter, 100 per half step
"oscillator": {
"type": "sine"
},
"envelope": {
"attack": 0.1,
"decay": 5,
"sustain": 100,
"release": 1
},
"modulation": {
"type": "square"
},
"modulationEnvelope": {
"attack": 0.5,
"decay": 1,
"sustain": 0.5,
"release": 0.5
}
});
var fmComp = new Tone.Compressor(-50, 1000).toMaster(); //threshold, ratio
fmSynth.connect(fmComp);
//option 1. hihat noiseSynth
// hihat = new Tone.NoiseSynth({
// "noise": {
// "type": "white"
// },
// "envelope": {
// "attack": 0.005,
// "decay": 0.01,
// "sustain": 0
// }
// }).toMaster();
//option 2. noise + amplitude envelope
// var hihatEnv = new Tone.AmplitudeEnvelope({
// "attack": 0,
// "decay": 0.01,
// "sustain": 0.002,
// "release": 0.0004
// });
// hihatEnv.toMaster();
// hihat = new Tone.Noise("white");
// hihat.connect(hihatEnv);
// hihat.start();
//Scheduling events:
var synthPart = new Tone.Part(function (time, notes) {
synth.triggerAttackRelease(notes, "16n", time);
}, timeNotes).start();
synthPart.loop = true;
synthPart.loopEnd = "1m";
var kickLoop = new Tone.Loop(function (time) {
kick.triggerAttackRelease("F1");
}, "4n").start();
var hihatEvent = new Tone.Event(playHihat);
hihatEvent.start("0:0:1");
hihatEvent.loop = true;
hihatEvent.loopEnd = "4n";
// var hihatPart = new Tone.Loop(function(time) {
// hihatEnv.triggerAttackRelease("16n");
// },"8n").start();
function setup() {
var cnv = createCanvas(windowWidth, windowHeight);
rectMode(CENTER);
frame = new Frame(400);
playButton = createButton('play/pause');
playButton.mousePressed(playStop);
playButton.position(0, 0)
randomizeButton = createButton('randomize');
randomizeButton.mousePressed(randomize);
randomizeButton.position(0, 20)
bpmSlider = createSlider(120, 140, 120);
bpmSlider.position(0, 80);
hihatSlider = createSlider(0, 50, 0);
hihatSlider.position(0, 120);
kickSlider = createSlider(0, 300, 0);
kickSlider.position(0, 160);
}
function draw() {
background(map(kickSlider.value(), 0, 300, 0, 255));
fill(255);
strokeWeight(1);
text(notes, 0, 54); //print randomized synth notes
text('BPM',0,80);
text('hihat',0,120);
text('kickfilter',0,160);
text("press 'a' for fmsynth", 0, 200);
text("mouse drag within square frame to change MonoSynth", 0 , 240);
Tone.Transport.bpm.value = bpmSlider.value();
kickFilter.frequency.value = kickSlider.value()
reverb.roomSize.value = hihatSlider.value() / 10;
frame.update();
frame.display();
//constrain mouseX & mouseY to frame
let frameXmin = width / 2 - 200;
let frameXmax = width / 2 + 200;
let frameYmin = height / 2 - 200;
let frameYmax = height / 2 + 200;
// rect(width/2,height/2,400,400); //reference frame
//change filter Q and delay when mouse dragged inside the frame
if (mouseIsPressed && mouseX > frameXmin && mouseX < frameXmax && mouseY > frameYmin && mouseY < frameYmax) {
synth.filterEnvelope.decay = map(mouseX, frameXmin, frameXmax, 0, 5); //mouseX to control decay value;
synth.filter.Q.value = map(mouseY, frameYmin, frameYmax, 0, 10); // mouseY to control Q value;
}
if (play == true) {
//if playing:
//scale circle by kickLoop progress:
// d = d0 + d0 / 10 * sin(bpm / 120 * millis() / 80); //eyeballed values(out of synch, but more organic)
let scaler = map(kickLoop.progress, 0, 1, 1, -1);
d = d0 + d0 / 10 * scaler;
//change circle density and size when mouse dragged inside the frame
if (mouseIsPressed && mouseX > frameXmin && mouseX < frameXmax && mouseY > frameYmin && mouseY < frameYmax) {
n = floor(map(mouseX, frameXmin, frameXmax, 40, 200)); //mouseX control circle density
d0 = map(mouseY, frameYmin, frameYmax, 100, 500); //mouseY control circle size
}
} else {
//if not playing, don't scale
d = d0;
}
noFill();
push();
translate(width / 2, height / 2);
//center reference ellipse(hidden):
noStroke();
ellipse(0, 0, d);
//repeating ellipse:
strokeWeight(1);
stroke(map(kickSlider.value(), 0, 250, 255, 0))
for (a = 0; a < 2 * PI; a = a + 2 * PI / n) {
ellipse(d / 2 * cos(a), d / 2 * sin(a), d);
}
pop();
//animate fmSynth line with fmSynth envelope:
//https://tonejs.github.io/examples/#funkyShape
for (i = 0; i < width; i++) {
stroke(map(kickSlider.value(), 0, 250, 255, 0))
strokeWeight(2);
var yDot = sin((i / 60) + phase) * fmSynth.envelope.value * 50;
point(i, height / 2 + yDot);
phase += 1;
}
}
//hihat frame
class Frame {
constructor(w) {
this.w = w
this.history = []; //to store size(squre width) history
}
update() {
this.w = 400 + this.w * hihatEvent.progress
this.history.push(this.w);
rectTrails = map(hihatSlider.value(),0,50,1,25);
if (this.history.length > rectTrails){
this.history.splice(0, 1);
}
}
display() {
noFill();
rect(width / 2, height / 2, this.w, this.w);
for (let i = 0; i < rectTrails; i++) {
let alpha = map(rectTrails,0,50,0,255);
stroke(map(kickSlider.value(), 0, 300, 255, 0),alpha);
rect(width / 2, height / 2, this.history[i], this.history[i]);
}
}
}
//toggle play stop
function playStop() {
if (play == false) {
Tone.Transport.start();
} else {
Tone.Transport.stop();
}
play = !play;
}
//has to be after setup()
function playHihat() {
if (hihat.loaded) {
hihat.start();
}
}
function randomize() {
notes = ""; //clear previous printed notes array
for (i = 0; i < timeNotes.length; i++) {
synthPart._events[i].value = synthNotesSet[floor(random(synthNotesSet.length))];
notes += synthPart._events[i].value + " ";
}
}
//trigger fmSynth with randomized monoSynth notes
function keyPressed() {
if (keyCode == 65) { //key == 'a'
let fmNote = pickFmNote();
fmSynth.triggerAttackRelease(fmNote, "4n");
// fmSynth.triggerAttack("D1", "4n");
}
}
//generate random fmNote from MonoSynth notes excluding 0
function pickFmNote() {
let pos = floor(random(timeNotes.length));
if (synthPart._events[pos].value ==0) {
return pickFmNote();
} else {
return synthPart._events[pos].value;
}
}
// function keyRelease(){
// fmSynth.triggerRelease();
// }