xxxxxxxxxx
268
let pressed = [];
let frequencies = [];
let forces = [];
let force_mult;
let spread_mult;
let distortion_mult;
let synth;
let playbutton;
let force_type;
let decay_rate;
let keyWidth;
let start_key;
function createNoteTable() {
const frequencies = [];
for (let i=0; i< 128; i++) {
frequencies[i] =
{
frequency: Math.pow(2, (i - 69) / 12) * 440,
frequency: 0,
position: 0,
position_change: 0,
}
forces[i] = {
position: 0,
frequency: 0
};
}
console.log(frequencies);
return frequencies;
}
function playMidiFile(jsonFile){
console.log("Playing file", jsonFile);
loadJSON(jsonFile, (data) =>{
console.log(data);
let notes = data.tracks[0].notes;
notes.forEach((note) => {
console.log(note);
let velocity = map(note.velocity, 0, 1, 0, 127);
// pressed.push(note.midi);
playSynth(note.midi, velocity, Tone.now() + note.time);
})
}, (error) =>{
console.log(error);
})
}
function success (midi) {
// console.log('Got midi access!', midi);
var inputs = midi.inputs.values();
// console.log("Midi input size", midi.inputs.size);
if(midi.inputs.size == 0){
console.log("No MIDI device found");
createP('MIDI device not connected. Connect and refresh').style("color", "red").style("font-size","24px").style("font-weight","800").position(350, 250);
}
audioContext = new AudioContext();
// console.log(inputs);
for (var input = inputs.next();
input && !input.done;
input = inputs.next()) {
// each time there is a midi message call the onMIDIMessage function
input.value.onmidimessage = onMIDIMessage;
}
}
function onMIDIMessage (message) {
// console.log(message.data);
if(message.data[0] == 144){
// console.log(`PRESS ${message.data[1]} with ${message.data[2]}`);
pressed.push(message.data[1]);
playSynth(message.data[1], message.data[2]);
}
if(message.data[0] == 128){
// console.log(`OFF ${message.data[1]} at ${pressed.indexOf(message.data[1])} position`);
let index = pressed.indexOf(message.data[1]);
if (index > -1) {
pressed.splice(index, 1);
}
}
redraw();
}
function onKeyPress (message) {
// console.log(message.data);
if(message.data[0] == 144){
// console.log(`PRESS ${message.data[1]} with ${message.data[2]}`);
pressed.push(message.data[1]);
playSynth(message.data[1], message.data[2]);
}
if(message.data[0] == 128){
// console.log(`OFF ${message.data[1]} at ${pressed.indexOf(message.data[1])} position`);
let index = pressed.indexOf(message.data[1]);
if (index > -1) {
pressed.splice(index, 1);
}
}
redraw();
}
function failure () {
console.error('No access to your midi devices.')
createP('MIDI device not connected. Connect and refresh').style("color", "red").style("font-size","24px").style("font-weight","800").position(350, 250);
}
function setup() {
createCanvas(windowWidth, windowHeight);
if (navigator.requestMIDIAccess) {
navigator.requestMIDIAccess()
.then(success, failure);
}
frequencies = createNoteTable();
synth = new Tone.PolySynth().toDestination();
rectMode(CENTER);
createP('Made with').position(450, 700);
createA('https://p5js.org/', 'p5*js','_blank').position(530, 716);
createP('and').position(570, 700);
createA('https://tonejs.github.io/', 'tone.js','_blank').position(600, 716);
createP('!! Work In Progress !! But feel free to test and hack').style("color", "red").position(450, 20);
createP('By').position(500, 750);
createA('https://allwinwilliams.com/', 'Allwin Williams','_blank').position(520, 764);
createP('Would love to hear feedbacks from you!!').position(450, 800);
force_mult = createSlider(0, 2, 1, 0.01);
force_mult.position(100, 600);
force_mult.size(80);
spread_mult = createSlider(1, 10, 1, 1);
spread_mult.position(300, 600);
spread_mult.size(80);
smooth_mult = createSlider(8, 256, 128, 8);
smooth_mult.position(500, 600);
smooth_mult.size(80);
decay_rate = createSlider(0.4, 0.99, 0.8, 0.001);
decay_rate.position(700, 600);
decay_rate.size(80);
// playbutton = createButton("Play Bach [X-Don't touch-X]", 200, 100);
// playbutton.position(1000, 100);
// playbutton.size(80);
// // playbutton.hide();
// playbutton.mousePressed(() => {
// playMidiFile("bach.json");
// });
myRadio = createRadio();
myRadio.position(900, 600);
myRadio.size(400);
// Add a few color options.
myRadio.option('Retract');
myRadio.option('Contract');
myRadio.option('Bulge');
myRadio.option('Cluster');
// Choose a default option.
myRadio.selected('Retract');
// noLoop();
frameRate(5);
}
function windowResized(){
resizeCanvas(windowWidth, windowHeight);
}
function draw() {
background(220);
noStroke();
fill("black");
textSize(24);
text("Dynamically tuning", 500, 100);
textSize(12);
text("Exploring tuning systems. Can they be fluidic and dynamic?", 450, 150);
translate(100, 300);
text("force", 10, 300);
text("spread", 200, 300);
text("smooth", 400, 300);
text("decay rate", 600, 300);
text("type", 800, 300);
translate(-50, 0);
keyWidth = 10;
let decayvalue = decay_rate.value();
start_key = 21;
let end_key = 109;
for(let i=start_key; i<end_key;i++)
{
forces[i].position *= decayvalue;
let forceMovement = forces[i].position * force_mult.value()
if(pressed.indexOf(i) != -1){
fill("red");
} else{
fill("white");
}
let x = (keyWidth * (i - start_key) * 1.4);
rect(x, 0, keyWidth, 100);
fill("blue");
stroke(0);
strokeWeight(2);
line(x + forceMovement, 50, x + forceMovement, 200 + abs(forceMovement));
noStroke();
}
}
function playSynth(pitch, velocity, time = Tone.now()) {
userStartAudio();
let weight = map(velocity, 0, 127, 2, 16);
let spread = map(velocity, 0, 127, 5, 12) * spread_mult.value();
spread = floor(spread);
let functype = myRadio.value();
for(let i = 0; i <= 127; i++){
if(functype == "Cluster"){
// try to make a sin wave where same frequency in different octave are getting focused
forces[i].position += sin(i+pitch*PI/4) * weight * force_mult.value();
}
}
for(let i = pitch - spread; i <= pitch + spread; i++){
let distance = i - pitch;
distance = map(distance, - spread, spread, -1, 1);
if(functype == "Retract"){
// Maving the frequencies move away from the pressed keys
forces[i].position += tan(distance) * weight * force_mult.value();
}
else if(functype == "Contract"){
// Maving the frequencies closed to the pressed keys
forces[i].position += cos(distance + PI/2) * weight * force_mult.value();
}
else if(functype == "Bulge"){
// Makes the frequencies around the keys pressed to bulge
forces[i].position += cos(distance + PI/4) * weight * force_mult.value();
}
}
let x = (keyWidth * (pitch - start_key) * 1.4);
let frequency = frequencies[pitch].position + forces[pitch].position * force_mult.value();
synth.triggerAttackRelease(frequency, weight * 0.06 * decay_rate.value(), time, velocity/smooth_mult.value());
}