Audio
Takeaways:
- Any memory accessed by Web Workers is in the
SharedArrayBuffer
. AudioBuffer::copyToChannel
must be given owned memory.- Cloning the memory – whether in Rust or JS – then calling
audio_buffer.copy_to_channel
in Rust still goes through aSharedArrayBuffer
. - Workaround: pass both the
AudioBuffer
and the bytes to JS, clone the memory, then callaudioBuffer.copyToChannel
in JS. - WASM: The user needs to interact with the page for audio to play.
- Github issue(s): amethyst#2195
Native
- 🎵 You want to play music.
- 🎶 You send music to the audio buffer.
- 🔊 Music plays.
WASM
-
🎵 You want to play music.
-
📜 You change your build script so
Worker
s can be initialized without a browserAudioContext
.// Before const lAudioContext = ( typeof AudioContext !== 'undefined' ? AudioContext : webkitAudioContext ); // After const lAudioContext = ( typeof AudioContext !== 'undefined' ? AudioContext : typeof webkitAudioContext !== 'undefined' ? webkitAudioContext : null );
-
📨 You send the
AudioBuffer
and the audio byte array (accessed throughSharedArrayBuffer
) to JS.#[wasm_bindgen] extern "C" { fn copy_audio_buffer(dest: &AudioBuffer, src: &[f32], channel: i32); }
-
📋 You clone the data.
There are 5 ways to "copy" data. Only one truely clones:
function make_standalone(src) { // These don't clone the data. var standalone = Float32Array.from(src); var standalone = new Float32Array(src); var standalone = src.slice(); var standalone = ArrayBuffer.transfer(src); // This one does. var standalone = [...src]; return standalone; }
-
🎶 You send music to the audio buffer.
function copy_audio_buffer(dest, src, channel) { // Turn the array view into owned memory. var standalone = [...src]; // Make it a Float32Array. var buffer = new Float32Array(standalone); // Copy the data. dest.copyToChannel(buffer, channel); }
-
🔇 Nothing plays, because you need a user interaction.
-
🖱️ You make the user click the canvas.
-
🔊 Music plays.. ..when the main thread returns.