xxxxxxxxxx
147
// Global variable to store the classifier
let classifier;
// Label (start by showing listening)
let label = "listening";
// Teachable Machine model URL
let soundModel = 'https://teachablemachine.withgoogle.com/models/FEeaNINgu/';
// Knob variables
let d = 500;
let targetRotation = 0;
let currentRotation = 0;
let rotationProgress = 0;
let isOn = false;
let knobOpacity = 0.7;
// Cooldown variables
let lastActionTime = 0;
const GLOBAL_COOLDOWN = 700; // 1 second global cooldown for all actions
let isOnCooldown = false;
// Rotation animation
let rotationAnimationStart = 0;
const ROTATION_DURATION = 500; // milliseconds for rotation animation
function preload() {
classifier = ml5.soundClassifier(soundModel + "model.json", modelReady);
}
// p5.js setup function
function setup() {
// Set canvas size to fill the entire screen
createCanvas(windowWidth, windowHeight);
noCursor(); // Optional: hide the default cursor
// Attach the canvas to the #sketch-container div
let canvas = createCanvas(windowWidth, windowHeight);
// Smooth animation setup
angleMode(DEGREES);
}
// p5.js draw function
function draw() {
background(20, 25, 35); // Deep dark background
// Check and reset cooldown
if (isOnCooldown && millis() - lastActionTime > GLOBAL_COOLDOWN) {
isOnCooldown = false;
}
// Animate rotation with Bezier curve
if (rotationProgress < 1) {
rotationProgress = (millis() - rotationAnimationStart) / ROTATION_DURATION;
rotationProgress = constrain(rotationProgress, 0, 1);
// Bezier curve for smoother rotation (easing)
let t = bezierPoint(0, 0.1, 0.9, 1, rotationProgress);
currentRotation = lerp(currentRotation, targetRotation, t);
}
// Draw knob
drawKnob();
}
// --------------------------------------------------------- KNOB
// Function to draw the knob
function drawKnob() {
push();
// Knob positioning
translate(width / 2, height / 2);
//------------------------------------------------------ Circle
fill(isOn ? color(255, 100, 100) : color(48, 106, 253));
ellipse(0, 0, d, d);
//------------------------------------------------------ Line Indicator
// Rotation indicator
push();
rotate(currentRotation);
strokeWeight(5);
stroke(255, 255, 255, 0.5 * 255);
strokeCap(ROUND);
line(0, d/2-40, 0, d/2 -120);
pop();
pop();
}
// Callback function when the model is ready
function modelReady() {
classifier.classify(gotResult);
}
// The model recognizing a sound will trigger this event
function gotResult(error, results) {
if (error) {
console.error(error);
return;
}
// Check global cooldown
if (isOnCooldown) {
return;
}
// The results are in an array ordered by confidence.
label = results[0].label;
// console.log(results);
// Rotate when 'Class 2' is detected
if (results[0].label === "Twist") {
if (results[0].confidence < 0.8) return
targetRotation += 45;
rotationProgress = 0;
rotationAnimationStart = millis();
// Activate global cooldown
isOnCooldown = true;
lastActionTime = millis();
}
// Toggle on/off when 'Class 3' is detected
if (results[0].label === "Tap") {
if (results[0].confidence < 0.8) return
isOn = !isOn;
knobOpacity = isOn ? 1 : 0.3;
// Activate global cooldown
isOnCooldown = true;
lastActionTime = millis();
}
}
// Function to handle window resizing
function windowResized() {
// Resize canvas when window is resized
resizeCanvas(windowWidth, windowHeight);
}