async function playFreddie() {
let freddie = [[500, 1], [1000, 40], [1500, 5], [2000, 10], [2500, 10], [3000, 15], [3500, 10], [4000, 5]]
// Play frequencies with their respective volumes, with vibrato depth of 2% and speed of 7 Hz
await playFrequencies(500, 3, freddie, 2, 7, 0.2);
}
async function playFrequencies(baseFrequency, duration, frequencyVolumeArray, vibratoDepthPercent = 2, vibratoSpeed = 7, maxRandomness = 0.2) {
// Create AudioContext
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let pitchRatio = baseFrequency / frequencyVolumeArray[0][0];
console.log('pitchRatio', pitchRatio)
// Create a list of promises
let promises = frequencyVolumeArray.map((freqVol) => {
// Extract the frequency and volume
let frequency = freqVol[0];
let volume = freqVol[1] / 100; // Convert percentage to decimal
// Create oscillator for the frequency
let oscillator = audioCtx.createOscillator();
oscillator.frequency.value = pitchRatio * frequency; // Set base frequency
// Create a GainNode to control the volume
let gainNode = audioCtx.createGain();
gainNode.gain.value = volume;
// Create vibrato oscillator and gain
let vibrato = audioCtx.createOscillator();
let vGain = audioCtx.createGain();
// Connect the vibrato to the main oscillator frequency
vibrato.connect(vGain);
vGain.connect(oscillator.frequency);
// Connect the oscillator to the gain node
oscillator.connect(gainNode);
// Connect the gain node to the output destination
gainNode.connect(audioCtx.destination);
// Function to update vibrato parameters
const updateVibrato = () => {
let randomDepthVariation = (Math.random() * 2 - 1) * maxRandomness; // -5% to +5%
let randomSpeedVariation = (Math.random() * 2 - 1) * maxRandomness; // -5% to +5%
let adjustedVibratoDepth = vibratoDepthPercent * (1 + randomDepthVariation);
let adjustedVibratoSpeed = vibratoSpeed * (1 + randomSpeedVariation);
vibrato.frequency.value = adjustedVibratoSpeed; // Vibrato frequency
vGain.gain.value = frequency * (adjustedVibratoDepth / 100); // Vibrato depth
};
// Start the oscillator and vibrato
oscillator.start();
vibrato.start();
// Update vibrato parameters every 0.5 seconds
let vibratoInterval = setInterval(updateVibrato, 500);
// Return a promise that resolves after the sound finishes
return new Promise((resolve) => {
setTimeout(function () {
clearInterval(vibratoInterval);
resolve();
}, duration * 1000);
});
});
// Wait for all sounds to finish
await Promise.all(promises);
// Close the AudioContext
audioCtx.close();
}