mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 02:43:48 +02:00
Small adjustments
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user