ICM - Sound - Chimpunk Rapbox

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)
}