Small adjustments

This commit is contained in:
Vanilagy
2025-06-06 15:12:10 +02:00
parent c600b60ee0
commit 470cef60f2
3 changed files with 28 additions and 26 deletions
+2
View File
@@ -249,6 +249,8 @@ const runAudioIterator = async () => {
return; return;
} }
// To play back audio, we loop over all audio chunks (typically very short) of the file and play them at the correct
// timestamp. The result is a continuous, uninteruppted audio signal.
for await (const { buffer, timestamp } of audioBufferIterator!) { for await (const { buffer, timestamp } of audioBufferIterator!) {
const node = audioContext!.createBufferSource(); const node = audioContext!.createBufferSource();
node.buffer = buffer; node.buffer = buffer;
+1 -1
View File
@@ -39,7 +39,7 @@
<div class="w-full max-w-80 h-2 rounded-full bg-zinc-200 dark:bg-zinc-750 overflow-hidden" id="progress-bar-container" style="display: none;"> <div class="w-full max-w-80 h-2 rounded-full bg-zinc-200 dark:bg-zinc-750 overflow-hidden" id="progress-bar-container" style="display: none;">
<div class="h-full bg-emerald-500 w-0" id="progress-bar"></div> <div class="h-full bg-emerald-500 w-0" id="progress-bar"></div>
</div> </div>
<p class="text-xs font-medium mt-1" id="progress-text" style="display: none;"></p> <p class="text-xs font-medium mt-1 tabular-nums" id="progress-text" style="display: none;"></p>
<video controls class="rounded-md" id="result-video" style="display: none;"></video> <video controls class="rounded-md" id="result-video" style="display: none;"></video>
<p class="text-xs font-medium mt-1" id="video-info" style="display: none;"></p> <p class="text-xs font-medium mt-1" id="video-info" style="display: none;"></p>
@@ -27,11 +27,11 @@ const renderCanvas = new OffscreenCanvas(1280, 720);
const renderCtx = renderCanvas.getContext('2d', { alpha: false })!; const renderCtx = renderCanvas.getContext('2d', { alpha: false })!;
// Stuff we need for rendering audio // Stuff we need for rendering audio
let offlineAudioContext: OfflineAudioContext; let audioContext: OfflineAudioContext;
let offlineGlobalGainNode: GainNode; let globalGainNode: GainNode;
let offlineDryGain: GainNode; let dryGain: GainNode;
let offlineWetGain: GainNode; let wetGain: GainNode;
let offlineReverbConvolver: ConvolverNode; let reverbConvolver: ConvolverNode;
// Scales are defined as semitone offsets from A440 // Scales are defined as semitone offsets from A440
const scaleProgression = [ const scaleProgression = [
@@ -156,7 +156,7 @@ const generateVideo = async () => {
if (audioBufferSource) { if (audioBufferSource) {
// Let's render the audio. Ideally, the audio is rendered before the video (or concurrently to it), but for // Let's render the audio. Ideally, the audio is rendered before the video (or concurrently to it), but for
// simplicity, we're rendering it after we've cranked through all frames. // simplicity, we're rendering it after we've cranked through all frames.
const audioBuffer = await offlineAudioContext.startRendering(); const audioBuffer = await audioContext.startRendering();
await audioBufferSource.add(audioBuffer); await audioBufferSource.add(audioBuffer);
audioBufferSource.close(); audioBufferSource.close();
} }
@@ -197,25 +197,25 @@ const generateVideo = async () => {
/** === SCENE SIMULATION LOGIC === */ /** === SCENE SIMULATION LOGIC === */
const initScene = (duration: number) => { const initScene = (duration: number) => {
offlineAudioContext = new OfflineAudioContext(numberOfChannels, duration * sampleRate, sampleRate); audioContext = new OfflineAudioContext(numberOfChannels, duration * sampleRate, sampleRate);
// Create reverb effect // Create reverb effect
offlineReverbConvolver = offlineAudioContext.createConvolver(); reverbConvolver = audioContext.createConvolver();
offlineReverbConvolver.buffer = createReverbImpulse(5); reverbConvolver.buffer = createReverbImpulse(5);
offlineGlobalGainNode = offlineAudioContext.createGain(); globalGainNode = audioContext.createGain();
offlineDryGain = offlineAudioContext.createGain(); dryGain = audioContext.createGain();
offlineWetGain = offlineAudioContext.createGain(); wetGain = audioContext.createGain();
offlineGlobalGainNode.connect(offlineDryGain); globalGainNode.connect(dryGain);
offlineGlobalGainNode.connect(offlineReverbConvolver); globalGainNode.connect(reverbConvolver);
offlineReverbConvolver.connect(offlineWetGain); reverbConvolver.connect(wetGain);
offlineDryGain.connect(offlineAudioContext.destination); dryGain.connect(audioContext.destination);
offlineWetGain.connect(offlineAudioContext.destination); wetGain.connect(audioContext.destination);
offlineGlobalGainNode.gain.setValueAtTime(0.8, 0); globalGainNode.gain.setValueAtTime(0.8, 0);
offlineDryGain.gain.setValueAtTime(0.5, 0); dryGain.gain.setValueAtTime(0.5, 0);
offlineWetGain.gain.setValueAtTime(0.5, 0); wetGain.gain.setValueAtTime(0.5, 0);
// Let's init the balls // Let's init the balls
const numBalls = Number(ballsSlider.value); const numBalls = Number(ballsSlider.value);
@@ -440,16 +440,16 @@ class Ball {
} }
scheduleSound(currentTime: number) { scheduleSound(currentTime: number) {
const oscillator = offlineAudioContext.createOscillator(); const oscillator = audioContext.createOscillator();
const gainNode = offlineAudioContext.createGain(); const gainNode = audioContext.createGain();
const pannerNode = offlineAudioContext.createStereoPanner(); const pannerNode = audioContext.createStereoPanner();
// Calculate pan based on x position // Calculate pan based on x position
const panValue = ((this.x / renderCanvas.width) - 0.5) * Math.SQRT2; const panValue = ((this.x / renderCanvas.width) - 0.5) * Math.SQRT2;
oscillator.connect(gainNode); oscillator.connect(gainNode);
gainNode.connect(pannerNode); gainNode.connect(pannerNode);
pannerNode.connect(offlineGlobalGainNode); pannerNode.connect(globalGainNode);
const frequency = getFrequencyFromScaleIndex(this.scaleIndex); const frequency = getFrequencyFromScaleIndex(this.scaleIndex);
oscillator.frequency.setValueAtTime(frequency, currentTime); oscillator.frequency.setValueAtTime(frequency, currentTime);
@@ -492,7 +492,7 @@ const getFrequencyFromScaleIndex = (scaleIndex: number) => {
const createReverbImpulse = (duration: number) => { const createReverbImpulse = (duration: number) => {
const length = sampleRate * duration; const length = sampleRate * duration;
const impulse = offlineAudioContext.createBuffer(numberOfChannels, length, sampleRate); const impulse = audioContext.createBuffer(numberOfChannels, length, sampleRate);
for (let channel = 0; channel < 2; channel++) { for (let channel = 0; channel < 2; channel++) {
const channelData = impulse.getChannelData(channel); const channelData = impulse.getChannelData(channel);