In collaboration with Anvay Kantak
It all comes down to this final assignment. I am glad that we were able to deploy a large portion of the concepts and materials we learned this semester into this sketch. The initial idea was to play with audio, more specifically the microphone input. But instead of the record and loop method where the recording and playback happens in two separate states, we wanted to hear live audio feedback of our voice. This was because we wanted to apply audio effects on top of the mic and to allow the user to adjust these effects in real time. Therefore, the first, and later proven to be the most difficult challenge became how to hear the mic audio in real time.
We first took the logic behind the record and loop mic sketch and tried to make the recorded audio playback with a one second delay in an attempt to imitate a live audio feedback. However, this proved fruitless because not only was the resulting audio quality undesirable, the loop began picking up too much ambient static noises, creating a chaotic echo chamber effect that rendered the sketch unusable.
let mic;
let count;
let recorder;
let sound1;
let sound2;
let state = 0;
function setup() {
frameRate(60);
createCanvas(400, 400);
// Set up mic
mic = new p5.AudioIn();
// Set up recorder
recorder = new p5.SoundRecorder();
// Connect mic to recorder
recorder.setInput(mic);
// Turn on mic
mic.start();
// Display instructions
textAlign(CENTER, CENTER);
background("green");
text("Press any key to record.", width / 2, height / 2);
}
function draw() {
count = frameCount;
background(220, 0, 0);
if (count == 60) {
state = 1;
}
if (state == 1) {
sound1 = new p5.SoundFile();
recorder.record(sound1);
state++;
} else if (state == 2 && count % 120 == 0) {
recorder.stop();
sound1.play();
state++;
} else if (state == 3) {
sound2 = new p5.SoundFile();
recorder.record(sound2);
state++;
} else if (state == 4 && count % 60 == 0) {
recorder.stop();
sound2.play();
state = 1;
}
}
Attempt at live mic feedback using record and mic logic with 1 second delay
They say the answer is often right under our nose and in this case, it couldn’t have been more true. In the end, all we needed to add to our code was a simple mic.connect( ) to connected the output from the mic to the system’s default speaker in order to hear our voice in real time. Along the road we realized that in order for this method to work, the user must be wearing headphones, much like how recording studios operate. Therefore, after figuring out the mic live feedback portion, the rest of the sketch was pretty smooth sailing.
For the first part of the sketch , we created a “recording studio” using different audio effects and giving them sliders so users can control and tune their voices to their liking. After the tuning is done, users hit a key to initiate the instrumental playback as lyrics begin to display on screen. Then it is time to sing!
Whenever the user decides they’re done singing their masterpiece, they simply have to hit a key to save that recording to their computer and they effectively have a memoir to keep for themselves!
let mic;
let recorder;
let reverbslider;
let lowfreqslider;
let highpassslider;
let distortionslider;
let delayslider;
let micvolumeslider;
let songvolumeslider;
let song;
let songvolume;
let recordedsong;
let state = 1;
let count;
function preload() {
song = loadSound("instrumental1.mp3");
reverb = new p5.Reverb();
lowPass = new p5.LowPass();
highpass = new p5.HighPass();
distort = new p5.Distortion();
delay = new p5.Delay();
}
function setup() {
createCanvas(600, 600);
background(100, 10, 140);
frameRate(30);
mic = new p5.AudioIn();
mic.start();
mic.connect();
mic.amp(0.2);
recorder = new p5.SoundRecorder();
//recorder.setInput(mic);
fill("white");
// micvolumeslider = createSlider(0, 1, 0.2, 0.01);
// micvolumeslider.position(width / 2, height / 8 - 15);
// micvolumeslider.style("width", "160px");
// text("Mic Volume", width / 4, height / 8);
reverbslider = createSlider(0, 1, 0, 0.01);
reverbslider.position(width / 2, (2 * height) / 8 - 15);
reverbslider.style("width", "160px");
text("Reverb", width / 4, (2 * height) / 8);
lowfreqslider = createSlider(10, 22050, 10);
lowfreqslider.position(width / 2, (3 * height) / 8 - 15);
lowfreqslider.style("width", "160px");
text("Lowfreq Filter", width / 4, (3 * height) / 8);
highpassslider = createSlider(10, 22050, 10);
highpassslider.position(width / 2, (4 * height) / 8 - 15);
highpassslider.style("width", "160px");
text("Highfreq Filter", width / 4, (4 * height) / 8);
distortionslider = createSlider(0, 1, 0, 0.01);
distortionslider.position(width / 2, (5 * height) / 8 - 15);
distortionslider.style("width", "160px");
text("Distortion", width / 4, (5 * height) / 8);
delayslider = createSlider(0, 0.5, 0, 0.01);
delayslider.position(width / 2, (6 * height) / 8 - 15);
delayslider.style("width", "160px");
text("Delay", width / 4, (6 * height) / 8);
// songvolumeslider = createSlider(0, 1, 1, 0.01);
// songvolumeslider.position(width / 2, (7 * height) / 8 - 15);
// songvolumeslider.style("width", "160px");
// text("Song Volume", width / 4, (7 * height) / 8);
textSize(20);
textAlign(CENTER);
text("Press any key to play track!", width / 2, (8 * height) / 8 - 20);
textSize(25);
text("Karaoke for One", width / 2, 37);
reverb.process(mic, 10);
lowPass.process(mic);
highpass.process(mic);
distort.process(mic, 0.1, "2x");
delay.process(mic, "", 0.5);
recordedsong = new p5.SoundFile();
}
function draw() {
reverb.drywet(reverbslider.value());
lowPass.freq(lowfreqslider.value());
highpass.freq(highpassslider.value());
distort.drywet(distortionslider.value());
delay.delayTime(delayslider.value());
// mic.amp(micvolumeslider.value());
// song.amp(songvolumeslider.value());
getLyrics();
}
function keyPressed() {
userStartAudio();
count = frameCount;
//state %=2;
console.log(state);
if (state === 1) {
song.play();
recorder.record(recordedsong);
fill("white");
createCanvas(600, 600);
background(220, 0, 55);
textSize(20);
textAlign(CENTER);
text("Recording! Press any key to STOP recording.", width / 2, 50);
// micvolumeslider.hide();
reverbslider.hide();
lowfreqslider.hide();
highpassslider.hide();
distortionslider.hide();
delayslider.hide();
// songvolumeslider.hide();
console.log(count);
text("I Want It That Way",width/2,550);
textSize(15)
text("Backstreet Boys", width/2, 570);
state++;
} else if (state === 2) {
recorder.stop();
song.stop();
mic.disconnect();
state++;
createCanvas(600, 600);
background(0, 160, 111);
textSize(20);
textAlign(CENTER);
text("Press any key to SAVE recording.", width / 2, height / 2);
} else if (state === 3) {
save(recordedsong, "i want it that way cover");
state = 1;
}
}
function getLyrics() {
textSize(14);
if (frameCount === count + 285) text("You are my fire.", width / 2 - 50, 100);
if (frameCount === count + 420) text("The one desire.", width / 2 + 50, 100);
if (frameCount === count + 570)
text("Believe when I say.", width / 2 - 60, 120);
if (frameCount === count + 720)
text("I want it that way.", width / 2 + 60, 120);
if (frameCount === count + 855)
text("But we are two worlds apart.", width / 2 - 85, 140);
if (frameCount === count + 1050)
text("Can't reach to your heart", width / 2 + 85, 140);
if (frameCount === count + 1200) text("When you say...", width / 2 - 75, 160);
if (frameCount === count + 1290)
text("That I want it that way", width / 2 + 75, 160);
if (frameCount === count + 1410)
text("[CHORUS] Tell me why ain't nothin' but a heartache", width / 2, 180);
if (frameCount === count + 1560)
text("Tell me why, ain't nothin' but a mistake", width / 2, 200);
if (frameCount === count + 1730)
text("Tell me why, I never wanna hear you say", width / 2, 220);
if (frameCount === count + 1890) text("I want it that way", width / 2, 240);
if (frameCount === count + 2010) text("Am I your fire?", width / 2 - 50, 270);
if (frameCount === count + 2160) text("Your one desire", width / 2 + 50, 270);
if (frameCount === count + 2280)
text("Yes, I know it's too late.", width / 2 - 70, 290);
if (frameCount === count + 2460)
text("But I want it that way", width / 2 + 70, 290);
if (frameCount === count + 2580) text("[CHORUS]", width / 2, 310);
if (frameCount === count + 3180)
text("Now I can see that we've fallen apart.", width / 2 - 120, 330);
if (frameCount === count + 3330)
text("From the way that it used to be, yeah", width / 2 + 120, 330);
if (frameCount === count + 3480)
text("No matter the distance, I want you to know", width / 2 - 120, 350);
if (frameCount === count + 3600)
text("That deep down inside of me", width / 2 + 120, 350);
if (frameCount === count + 3750)
text("You are my fire.", width / 2 - 50, 370);
if (frameCount === count + 3900) text("The one desire.", width / 2 + 50, 370);
if (frameCount === count + 4050)
text("You are (you are, you are, you are)", width / 2, 390);
if (frameCount === count + 4290)
text("Don't wanna hear you say", width / 2, 410);
if (frameCount === count + 4350)
text("Ain't nothin' but a heartache", width / 2, 430);
if (frameCount === count + 4500)
text(
"Ain't nothin' but a mistake (don't wanna hear you say)",
width / 2,
450
);
if (frameCount === count + 4650)
text("I never wanna hear you say (oh, yeah)", width / 2, 470);
if (frameCount === count + 4830) text("I want it that way", width / 2, 490);
if (frameCount === count + 4920) text("[CHORUS]", width / 2, 520);
if (frameCount === count + 5490) text("[CHORUS]", width / 2, 540);
if (frameCount === count + 6090)
text("'Cause I want it that way", width / 2, 560);
}
Final sketch code