Link to Website: https://grizzly-invented-felidae.glitch.me/
Group:
- Wasif
- Jingyao
Chipmunk Rap Machine
Words to describe
Overview
We decided to write our own version of auto-rap. We modulated the pitch of the sound added in repeat intervals.
The main challenge of the song was how to sequence the sound to play randomly on repeat at different intervals by jumping consistently.
We hadn't anticipated the complications in identifying detailed aspects of the song and certain audio sections and using them to make a more intelligent autorap instead of a completely random one.
Things That Can Be Improevd
- Add Fade In & Fade Out
- Detect Chunks of Sound to remix randomly
- Detect Chunks of sound and select areas to reuse as chorus
- Allow user to choose the song
Algorithm
We are using a recursion function to ensure that the jumping of the soundtrack occurs at random intervals up to 30 times in order to give an automatically rap quality feel to it. Its easier to write the function this way because we can leverage setTimeout instead of having to figure out and manually manage the time in the draw() function
// P5.js Code
let mic, recorder, soundFile, rapbeat;
let state = 0; // mousePress will increment from Record, to Stop, to Play
function preload() {
soundFormats('mp3', 'ogg');
rapbeat = loadSound(random([
'https://cdn.glitch.com/d5d28577-4422-4167-a2c4-4288d4ba55ff%2Frap_beat.mp3?v=1606316795031'
]));
}
function setup() {
createCanvas(400, 400);
background(200);
fill(0);
// create an audio in
mic = new p5.AudioIn();
// users must manually enable their browser microphone for recording to work properly!
mic.start();
// create a sound recorder
recorder = new p5.SoundRecorder();
// connect the mic to the recorder
recorder.setInput(mic);
// create an empty sound file that we will use to playback the recording
soundFile = new p5.SoundFile();
recordButton = createButton("Record");
recordButton.position(19, 19);
recordButton.mousePressed(record);
playButton = createButton("Remix");
playButton.position(345, 19);
playButton.mousePressed(remix);
}
function draw() {
background(240);
if (state === 0) {
if (soundFile === undefined || soundFile.duration() > 10) {
text("Click to record.", 20, 50);
} else {
text("Try recording a longer sound?", 20, 50);
}
} else {
background(255, 0, 0);
text("Recording now.", 20, 50);
}
}
function record() {
getAudioContext().resume();
if (state === 0 && mic.enabled) {
// Tell recorder to record to a p5.SoundFile which we will use for playback
recordButton.html("Stop");
recorder.record(soundFile);
state++;
} else if (state === 1) {
recordButton.html("Record");
recorder.stop(); // stop recorder, and send the result to soundFile
background(0, 255, 0);
state--;
}
}
function play() {
soundFile.play();
}
function remix() {
// Jump randomly every n seconds and play
rapbeat.play();
// soundFile.loop();
remixRecursion(1)
}
function remixRecursion(counter) {
let times = 30;
if (counter > times) {
soundFile.stop();
rapbeat.stop();
return
}
// Code to remix the song
let notes = [1, 1.125, 1.25, 1.334, 1.5, 1.667, 1.875, 2];
let f = random(notes); // Pitch to adjust to
let n = Math.round(random(1, 3)); // Duration for which to play
let duration = Math.round(soundFile.duration())
let jumpTo = Math.floor(random(duration))
soundFile.rate(f);
soundFile.stop();
soundFile.play();
soundFile.jump(jumpTo)
console.log(duration, n, jumpTo)
// Call this function again, n seconds later
setTimeout(() => remixRecursion(counter + 1), n * 1000)
}