diff --git a/files/en-us/web/api/audiobuffersourcenode/loop/index.md b/files/en-us/web/api/audiobuffersourcenode/loop/index.md index 40197bf111b0513..a26e3db9ff21396 100644 --- a/files/en-us/web/api/audiobuffersourcenode/loop/index.md +++ b/files/en-us/web/api/audiobuffersourcenode/loop/index.md @@ -27,51 +27,79 @@ is reached, playback continues at the time specified by ## Examples -In this example, the {{domxref("BaseAudioContext/decodeAudioData", "AudioContext.decodeAudioData()")}} function is used to -decode an audio track and put it into an {{domxref("AudioBufferSourceNode")}}. Buttons -are provided to play and stop the audio playback, and a slider control is used to change -the `playbackRate` property value on the fly. When the audio is played, it -loops. +### Setting `loop` -> **Note:** You can [run the full example live](https://mdn.github.io/webaudio-examples/decode-audio-data/) (or [view the source](https://github.com/mdn/webaudio-examples/blob/master/decode-audio-data/index.html).) +In this example, when the user presses "Play", we load an audio track, decode it, and put it into an {{domxref("AudioBufferSourceNode")}}. -```js -function getData() { - source = audioCtx.createBufferSource(); - request = new XMLHttpRequest(); - - request.open("GET", "viper.ogg", true); - - request.responseType = "arraybuffer"; +The example then sets the `loop` property to `true`, so the track loops, and plays the track. - request.onload = () => { - const audioData = request.response; +The user can set the `loopStart` and and `loopEnd` properties using [range controls](/en-US/docs/Web/HTML/Element/input/range). - audioCtx.decodeAudioData( - audioData, - (buffer) => { - myBuffer = buffer; - source.buffer = myBuffer; - source.playbackRate.value = playbackControl.value; - source.connect(audioCtx.destination); - source.loop = true; - }, +> **Note:** You can [run the full example live](https://mdn.github.io/webaudio-examples/audio-buffer-source-node/loop/) (or [view the source](https://github.com/mdn/webaudio-examples/tree/main/audio-buffer-source-node/loop).) - (e) => console.error(`Error with decoding audio data: ${e.err}`), - ); - }; - - request.send(); +```js +let audioCtx; +let buffer; +let source; + +const play = document.getElementById("play"); +const stop = document.getElementById("stop"); + +const loopstartControl = document.getElementById("loopstart-control"); +const loopstartValue = document.getElementById("loopstart-value"); + +const loopendControl = document.getElementById("loopend-control"); +const loopendValue = document.getElementById("loopend-value"); + +async function loadAudio() { + try { + // Load an audio file + const response = await fetch("rnb-lofi-melody-loop.wav"); + // Decode it + buffer = await audioCtx.decodeAudioData(await response.arrayBuffer()); + const max = Math.floor(buffer.duration); + loopstartControl.setAttribute("max", max); + loopendControl.setAttribute("max", max); + } catch (err) { + console.error(`Unable to fetch the audio file. Error: ${err.message}`); + } } -// wire up buttons to stop and play audio, and range slider control - -play.onclick = () => { - getData(); - source.start(0); - play.setAttribute("disabled", "disabled"); - playbackControl.removeAttribute("disabled"); -}; +play.addEventListener("click", async () => { + if (!audioCtx) { + audioCtx = new AudioContext(); + await loadAudio(); + } + source = audioCtx.createBufferSource(); + source.buffer = buffer; + source.connect(audioCtx.destination); + source.loop = true; + source.loopStart = loopstartControl.value; + source.loopEnd = loopendControl.value; + source.start(); + play.disabled = true; + stop.disabled = false; + loopstartControl.disabled = false; + loopendControl.disabled = false; +}); + +stop.addEventListener("click", () => { + source.stop(); + play.disabled = false; + stop.disabled = true; + loopstartControl.disabled = true; + loopendControl.disabled = true; +}); + +loopstartControl.addEventListener("input", () => { + source.loopStart = loopstartControl.value; + loopstartValue.textContent = loopstartControl.value; +}); + +loopendControl.addEventListener("input", () => { + source.loopEnd = loopendControl.value; + loopendValue.textContent = loopendControl.value; +}); ``` ## Specifications diff --git a/files/en-us/web/api/audiobuffersourcenode/loopend/index.md b/files/en-us/web/api/audiobuffersourcenode/loopend/index.md index 4ad2071341271b6..16cd9d37404236d 100644 --- a/files/en-us/web/api/audiobuffersourcenode/loopend/index.md +++ b/files/en-us/web/api/audiobuffersourcenode/loopend/index.md @@ -27,65 +27,79 @@ The default value is 0. ## Examples -In this example, the {{domxref("BaseAudioContext/decodeAudioData", "AudioContext.decodeAudioData()")}} function is used to -decode an audio track and put it into an {{domxref("AudioBufferSourceNode")}}. Buttons -are provided to play and stop the audio playback, and slider controls are used to change -the `playbackRate`, `loopStart` and `loopEnd` -properties on the fly. +### Setting `loopEnd` -When the audio is played to the end, it loops, but you can control how long the loops -last by altering `loopStart` and `loopEnd`. For example, if you -set their values to 20 and 25, respectively, then begin playback, the sound will play -normally until it reaches the 25 second mark. Then the current play position will loop -back to the 20 second mark and continue playing until the 25 second mark, ad infinitum -(or at least until {{domxref("AudioScheduledSourceNode/stop", "stop()")}} is called). +In this example, when the user presses "Play", we load an audio track, decode it, and put it into an {{domxref("AudioBufferSourceNode")}}. -> **Note:** For a full working example, see [this code running live](https://mdn.github.io/webaudio-examples/decode-audio-data/), or [view the source](https://github.com/mdn/webaudio-examples/tree/master/decode-audio-data). +The example then sets the `loop` property to `true`, so the track loops, and plays the track. -```js -function getData() { - source = audioCtx.createBufferSource(); - request = new XMLHttpRequest(); - - request.open("GET", "viper.ogg", true); - - request.responseType = "arraybuffer"; - - request.onload = () => { - const audioData = request.response; - - audioCtx.decodeAudioData( - audioData, - (buffer) => { - myBuffer = buffer; - songLength = buffer.duration; - source.buffer = myBuffer; - source.playbackRate.value = playbackControl.value; - source.connect(audioCtx.destination); - source.loop = true; +The user can set the `loopStart` and and `loopEnd` properties using [range controls](/en-US/docs/Web/HTML/Element/input/range). - loopstartControl.setAttribute("max", Math.floor(songLength)); - loopendControl.setAttribute("max", Math.floor(songLength)); - }, +> **Note:** You can [run the full example live](https://mdn.github.io/webaudio-examples/audio-buffer-source-node/loop/) (or [view the source](https://github.com/mdn/webaudio-examples/tree/main/audio-buffer-source-node/loop).) - (e) => console.error(`Error with decoding audio data: ${e.err}`), - ); - }; - - request.send(); +```js +let audioCtx; +let buffer; +let source; + +const play = document.getElementById("play"); +const stop = document.getElementById("stop"); + +const loopstartControl = document.getElementById("loopstart-control"); +const loopstartValue = document.getElementById("loopstart-value"); + +const loopendControl = document.getElementById("loopend-control"); +const loopendValue = document.getElementById("loopend-value"); + +async function loadAudio() { + try { + // Load an audio file + const response = await fetch("rnb-lofi-melody-loop.wav"); + // Decode it + buffer = await audioCtx.decodeAudioData(await response.arrayBuffer()); + const max = Math.floor(buffer.duration); + loopstartControl.setAttribute("max", max); + loopendControl.setAttribute("max", max); + } catch (err) { + console.error(`Unable to fetch the audio file. Error: ${err.message}`); + } } -// … - -loopstartControl.oninput = () => { +play.addEventListener("click", async () => { + if (!audioCtx) { + audioCtx = new AudioContext(); + await loadAudio(); + } + source = audioCtx.createBufferSource(); + source.buffer = buffer; + source.connect(audioCtx.destination); + source.loop = true; + source.loopStart = loopstartControl.value; + source.loopEnd = loopendControl.value; + source.start(); + play.disabled = true; + stop.disabled = false; + loopstartControl.disabled = false; + loopendControl.disabled = false; +}); + +stop.addEventListener("click", () => { + source.stop(); + play.disabled = false; + stop.disabled = true; + loopstartControl.disabled = true; + loopendControl.disabled = true; +}); + +loopstartControl.addEventListener("input", () => { source.loopStart = loopstartControl.value; - loopstartValue.innerHTML = loopstartControl.value; -}; + loopstartValue.textContent = loopstartControl.value; +}); -loopendControl.oninput = () => { +loopendControl.addEventListener("input", () => { source.loopEnd = loopendControl.value; - loopendValue.innerHTML = loopendControl.value; -}; + loopendValue.textContent = loopendControl.value; +}); ``` ## Specifications diff --git a/files/en-us/web/api/audiobuffersourcenode/loopstart/index.md b/files/en-us/web/api/audiobuffersourcenode/loopstart/index.md index 71b4a8677ff781d..4a43b516cc81c4d 100644 --- a/files/en-us/web/api/audiobuffersourcenode/loopstart/index.md +++ b/files/en-us/web/api/audiobuffersourcenode/loopstart/index.md @@ -22,62 +22,79 @@ which each loop should begin during playback. This value is only used when the ## Examples -In this example, the {{domxref("BaseAudioContext/decodeAudioData", "AudioContext.decodeAudioData()")}} function is used to -decode an audio track and put it into an {{domxref("AudioBufferSourceNode")}}. Buttons -are provided to play and stop the audio playback, and slider controls are used to change -the `playbackRate`, `loopStart`, and `loopEnd` -properties on the fly. +### Setting `loopStart` -When the audio is played to the end, it loops, but you can control how long the loops -last by altering `loopStart` and `loopEnd`. For example, if you -set their values to 20 and 25, respectively, the audio will start to loop between 20 and -25 seconds in to the track. +In this example, when the user presses "Play", we load an audio track, decode it, and put it into an {{domxref("AudioBufferSourceNode")}}. -> **Note:** For a full working example, see [this code running live](https://mdn.github.io/webaudio-examples/decode-audio-data/), or [view the source](https://github.com/mdn/webaudio-examples/tree/master/decode-audio-data). +The example then sets the `loop` property to `true`, so the track loops, and plays the track. -```js -function getData() { - source = audioCtx.createBufferSource(); - request = new XMLHttpRequest(); - - request.open("GET", "viper.ogg", true); - request.responseType = "arraybuffer"; - - request.onload = () => { - const audioData = request.response; - - audioCtx.decodeAudioData( - audioData, - (buffer) => { - myBuffer = buffer; - songLength = buffer.duration; - source.buffer = myBuffer; - source.playbackRate.value = playbackControl.value; - source.connect(audioCtx.destination); - source.loop = true; - - loopstartControl.setAttribute("max", Math.floor(songLength)); - loopendControl.setAttribute("max", Math.floor(songLength)); - }, +The user can set the `loopStart` and and `loopEnd` properties using [range controls](/en-US/docs/Web/HTML/Element/input/range). - (e) => console.error(`Error with decoding audio data: ${e.err}`), - ); - }; +> **Note:** You can [run the full example live](https://mdn.github.io/webaudio-examples/audio-buffer-source-node/loop/) (or [view the source](https://github.com/mdn/webaudio-examples/tree/main/audio-buffer-source-node/loop).) - request.send(); +```js +let audioCtx; +let buffer; +let source; + +const play = document.getElementById("play"); +const stop = document.getElementById("stop"); + +const loopstartControl = document.getElementById("loopstart-control"); +const loopstartValue = document.getElementById("loopstart-value"); + +const loopendControl = document.getElementById("loopend-control"); +const loopendValue = document.getElementById("loopend-value"); + +async function loadAudio() { + try { + // Load an audio file + const response = await fetch("rnb-lofi-melody-loop.wav"); + // Decode it + buffer = await audioCtx.decodeAudioData(await response.arrayBuffer()); + const max = Math.floor(buffer.duration); + loopstartControl.setAttribute("max", max); + loopendControl.setAttribute("max", max); + } catch (err) { + console.error(`Unable to fetch the audio file. Error: ${err.message}`); + } } -// … - -loopstartControl.oninput = () => { +play.addEventListener("click", async () => { + if (!audioCtx) { + audioCtx = new AudioContext(); + await loadAudio(); + } + source = audioCtx.createBufferSource(); + source.buffer = buffer; + source.connect(audioCtx.destination); + source.loop = true; + source.loopStart = loopstartControl.value; + source.loopEnd = loopendControl.value; + source.start(); + play.disabled = true; + stop.disabled = false; + loopstartControl.disabled = false; + loopendControl.disabled = false; +}); + +stop.addEventListener("click", () => { + source.stop(); + play.disabled = false; + stop.disabled = true; + loopstartControl.disabled = true; + loopendControl.disabled = true; +}); + +loopstartControl.addEventListener("input", () => { source.loopStart = loopstartControl.value; - loopstartValue.innerHTML = loopstartControl.value; -}; + loopstartValue.textContent = loopstartControl.value; +}); -loopendControl.oninput = () => { +loopendControl.addEventListener("input", () => { source.loopEnd = loopendControl.value; - loopendValue.innerHTML = loopendControl.value; -}; + loopendValue.textContent = loopendControl.value; +}); ``` ## Specifications diff --git a/files/en-us/web/api/audiobuffersourcenode/playbackrate/index.md b/files/en-us/web/api/audiobuffersourcenode/playbackrate/index.md index 92cc72ba1751194..645aa97232e8c57 100644 --- a/files/en-us/web/api/audiobuffersourcenode/playbackrate/index.md +++ b/files/en-us/web/api/audiobuffersourcenode/playbackrate/index.md @@ -33,71 +33,64 @@ second). Let's see what a few values of `playbackRate` do: ## Examples -In this example, the {{domxref("BaseAudioContext/decodeAudioData", "AudioContext.decodeAudioData()")}} function is used to -decode an audio track, and put it into an {{domxref("AudioBufferSourceNode")}}. Buttons -are provided to play and stop the audio playback, and a slider control is used to change -the `playbackRate` property value on the fly. - -> **Note:** You can [run the example live](https://mdn.github.io/webaudio-examples/decode-audio-data/) (or [view the source](https://github.com/mdn/webaudio-examples/tree/master/decode-audio-data)). Play the song and alter the playback rate for some fun results. - -```html - -1.0 -``` - -```js -function getData() { - source = audioCtx.createBufferSource(); - request = new XMLHttpRequest(); - - request.open("GET", "viper.ogg", true); +### Setting `playbackRate` - request.responseType = "arraybuffer"; +In this example, when the user presses "Play", we load an audio track, decode it, and put it into an {{domxref("AudioBufferSourceNode")}}. - request.onload = () => { - const audioData = request.response; +The example then sets the `loop` property to `true`, so the track loops, and plays the track. - audioCtx.decodeAudioData( - audioData, - (buffer) => { - myBuffer = buffer; - source.buffer = myBuffer; - source.playbackRate.value = playbackControl.value; - source.connect(audioCtx.destination); - source.loop = true; - }, +The user can set the `playbackRate` property using a [range control](/en-US/docs/Web/HTML/Element/input/range). - (e) => console.error(`Error with decoding audio data: ${e.err}`), - ); - }; +> **Note:** You can [run the full example live](https://mdn.github.io/webaudio-examples/audio-buffer-source-node/playbackrate/) (or [view the source](https://github.com/mdn/webaudio-examples/tree/main/audio-buffer-source-node/playbackrate).) - request.send(); +```js +let audioCtx; +let buffer; +let source; + +const play = document.getElementById("play"); +const stop = document.getElementById("stop"); + +const playbackControl = document.getElementById("playback-rate-control"); +const playbackValue = document.getElementById("playback-rate-value"); + +async function loadAudio() { + try { + // Load an audio file + const response = await fetch("rnb-lofi-melody-loop.wav"); + // Decode it + buffer = await audioCtx.decodeAudioData(await response.arrayBuffer()); + } catch (err) { + console.error(`Unable to fetch the audio file. Error: ${err.message}`); + } } -// wire up buttons to stop and play audio, and range slider control - -play.onclick = () => { - getData(); - source.start(0); - play.setAttribute("disabled", "disabled"); - playbackControl.removeAttribute("disabled"); -}; - -stop.onclick = () => { - source.stop(0); - play.removeAttribute("disabled"); - playbackControl.setAttribute("disabled", "disabled"); -}; +play.addEventListener("click", async () => { + if (!audioCtx) { + audioCtx = new AudioContext(); + await loadAudio(); + } + source = audioCtx.createBufferSource(); + source.buffer = buffer; + source.connect(audioCtx.destination); + source.loop = true; + source.playbackRate.value = playbackControl.value; + source.start(); + play.disabled = true; + stop.disabled = false; + playbackControl.disabled = false; +}); + +stop.addEventListener("click", () => { + source.stop(); + play.disabled = false; + stop.disabled = true; + playbackControl.disabled = true; +}); playbackControl.oninput = () => { source.playbackRate.value = playbackControl.value; - playbackValue.innerHTML = playbackControl.value; + playbackValue.textContent = playbackControl.value; }; ```