xxxxxxxxxx
275
let isAudioRecording = false;
let soundRecorder, soundFile;
let isMarkovChainProcessed = false;
let recordButton;
let isRecording = false;
let recordedNotes = [];
let recordingStartTime;
let isPlayingBack = false;
let playbackStartTime;
let osc;
let keyStates = {};
let notes = {
'A': 261.63, // C
'W': 277.18, // C#
'S': 293.66, // D
'E': 311.13, // D#
'D': 329.63, // E
'F': 349.23, // F
'T': 369.99, // F#
'G': 392.00, // G
'Y': 415.30, // G#
'H': 440.00, // A
'U': 466.16, // A#
'J': 493.88, // B
'K': 523.25 // C (next octave)
};
function setup() {
createCanvas(400, 400);
osc = new p5.Oscillator();
osc.setType('sine');
osc.amp(0);
osc.start();
soundRecorder = new p5.SoundRecorder();
soundRecorder.setInput(osc);
soundFile = new p5.SoundFile();
recordButton = createButton('Record');
recordButton.mousePressed(startRecording);
playButton = createButton('Play');
playButton.mousePressed(startPlayback);
exportAudioButton = createButton('Export Audio');
exportAudioButton.mousePressed(exportAudio);
let markovButton = createButton("Markov Chain");
markovButton.mousePressed(applyMarkovChain);
for (let key in notes) {
keyStates[key] = false;
}
}
function draw() {
background(220);
drawPianoKeys();
if (isPlayingBack) {
playbackRecordedNotes();
}
}
function drawPianoKeys() {
// White keys
let whiteKeys = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K'];
for (let i = 0; i < whiteKeys.length; i++) {
let key = whiteKeys[i];
fill(keyStates[key] ? 'orange' : 'white'); // Change color on key press
rect(20 + 40 * i, 100, 40, 160);
}
// Black keys
let blackKeys = ['W', 'E', 'T', 'Y', 'U'];
let blackKeyOffsets = [30, 70, 150, 190, 230];
for (let i = 0; i < blackKeys.length; i++) {
let key = blackKeys[i];
fill(keyStates[key] ? 'orange' : 'black'); // Change color on key press
rect(blackKeyOffsets[i] + 20, 100, 20, 100);
}
}
function startRecording() {
if (!isRecording) {
recordedNotes = [];
isRecording = true;
recordingStartTime = millis();
soundRecorder.record(soundFile);
}
}
function keyPressed() {
let freq = notes[key.toUpperCase()];
if (freq) {
keyStates[key.toUpperCase()] = true;
osc.freq(freq);
osc.amp(0.5, 0.1);
if (isRecording) {
recordedNotes.push({
note: key.toUpperCase(),
startTime: millis(),
freq: freq
});
}
}
}
function keyReleased() {
let freq = notes[key.toUpperCase()];
if (freq) {
keyStates[key.toUpperCase()] = false;
osc.amp(0, 0.1);
if (isRecording) {
let lastNote = recordedNotes[recordedNotes.length - 1];
if (lastNote.freq === freq) {
lastNote.duration = millis() - lastNote.startTime;
}
}
}
}
function startPlayback() {
if (!isPlayingBack && recordedNotes.length > 0) {
playbackStartTime = millis();
isPlayingBack = true;
for (let note of recordedNotes) {
note.isPlaying = false;
}
// If audio recording logic is present, start recording
// startRecordingAudio(); // Uncomment this if necessary
}
}
function playbackRecordedNotes() {
let currentTime = millis() - playbackStartTime;
for (let i = 0; i < recordedNotes.length; i++) {
let note = recordedNotes[i];
let noteStart = note.startTime - recordingStartTime;
let noteEnd = noteStart + note.duration;
if (currentTime >= noteStart && currentTime < noteEnd) {
if (!note.isPlaying) {
console.log("Playing note", note.note, "Frequency", note.freq); // Debugging
osc.freq(note.freq);
osc.amp(0.5, 0.1);
note.isPlaying = true;
}
} else if (note.isPlaying) {
osc.amp(0, 0.1);
note.isPlaying = false;
}
}
}
function exportAudio() {
if (!isAudioRecording) {
// Start recording
soundRecorder.record(soundFile);
isAudioRecording = true;
// Start playback
startPlayback();
// Set a timeout to stop recording after playback is complete
let totalPlaybackDuration = 0;
for (let i = 0; i < recordedNotes.length; i++) {
totalPlaybackDuration += recordedNotes[i].duration;
}
setTimeout(function() {
soundRecorder.stop();
if (soundFile.duration() > 0) {
soundFile.save('mySound', 'wav');
} else {
console.log('No audio was recorded.');
}
isAudioRecording = false;
}, totalPlaybackDuration);
}
}
function generateMarkovChain() {
let markovModel = {};
for (let i = 0; i < recordedNotes.length - 1; i++) {
let currentNote = recordedNotes[i].note;
let nextNote = recordedNotes[i + 1].note;
if (!markovModel[currentNote]) {
markovModel[currentNote] = {};
}
if (!markovModel[currentNote][nextNote]) {
markovModel[currentNote][nextNote] = 0;
}
markovModel[currentNote][nextNote]++;
}
// Convert counts to probabilities
for (let note in markovModel) {
let total = 0;
let transitions = markovModel[note];
for (let target in transitions) {
total += transitions[target];
}
for (let target in transitions) {
transitions[target] /= total;
}
}
return markovModel;
}
function applyMarkovChain() {
let markovModel = generateMarkovChain();
let newSequence = [];
let currentNoteName = recordedNotes[0].note; // Start from the first note
let cumulativeTime = 0;
for (let i = 0; i < recordedNotes.length - 1; i++) {
let currentNoteFreq = notes[currentNoteName];
newSequence.push({
note: currentNoteName,
freq: currentNoteFreq,
startTime: cumulativeTime,
duration: recordedNotes[i].duration
});
cumulativeTime += recordedNotes[i].duration;
if (markovModel[currentNoteName]) {
let nextNotes = markovModel[currentNoteName];
let nextNote = chooseNextNote(nextNotes);
currentNoteName = nextNote;
}
}
// Add the last note
let lastNoteFreq = notes[currentNoteName];
newSequence.push({
note: currentNoteName,
freq: lastNoteFreq,
startTime: cumulativeTime,
duration: recordedNotes[recordedNotes.length - 1].duration
});
recordedNotes = newSequence;
isMarkovChainProcessed = true;
// Start playback of the new sequence
startPlayback();
}
function chooseNextNote(noteOptions) {
let total = 0;
let accumulator = 0;
let rand = Math.random();
for (let note in noteOptions) {
total += noteOptions[note];
}
for (let note in noteOptions) {
accumulator += noteOptions[note] / total;
if (rand < accumulator) {
return note;
}
}
return null; // Fallback in case of an error
}