-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(poc): Added render and download button to the scheduled-sequenci…
…ng demo
- Loading branch information
1 parent
ca925c9
commit 096cfa7
Showing
5 changed files
with
148 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* global Blob, URL */ | ||
|
||
/* | ||
function floatTo16BitPCM(output, offset, input) { | ||
for (let i = 0; i < input.length; i++, offset += 2) { | ||
let s = Math.max(-1, Math.min(1, input[i])); | ||
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); | ||
} | ||
} | ||
function writeString(view, offset, string) { | ||
for (let i = 0; i < string.length; i++) { | ||
view.setUint8(offset + i, string.charCodeAt(i)); | ||
} | ||
} | ||
function encodeWAV(samples) { | ||
let buffer = new ArrayBuffer(44 + samples.length * 2); | ||
let view = new DataView(buffer); | ||
// RIFF identifier | ||
writeString(view, 0, 'RIFF'); | ||
// RIFF chunk length | ||
view.setUint32(4, 36 + samples.length * 2, true); | ||
// RIFF type | ||
writeString(view, 8, 'WAVE'); | ||
// format chunk identifier | ||
writeString(view, 12, 'fmt '); | ||
// format chunk length | ||
view.setUint32(16, 16, true); | ||
// sample format (raw) | ||
view.setUint16(20, 1, true); | ||
// channel count | ||
view.setUint16(22, numChannels, true); | ||
// sample rate | ||
view.setUint32(24, sampleRate, true); | ||
// byte rate (sample rate * block align) | ||
view.setUint32(28, sampleRate * 4, true); | ||
// block align (channel count * bytes per sample) | ||
view.setUint16(32, numChannels * 2, true); | ||
// bits per sample | ||
view.setUint16(34, 16, true); | ||
// data chunk identifier | ||
writeString(view, 36, 'data'); | ||
// data chunk length | ||
view.setUint32(40, samples.length * 2, true); | ||
floatTo16BitPCM(view, 44, samples); | ||
return view; | ||
} | ||
*/ | ||
|
||
// Convert an AudioBuffer to a Blob using WAVE representation | ||
const bufferToWave = (abuffer, len) => { | ||
const numOfChan = abuffer.numberOfChannels | ||
|
||
const length = len * numOfChan * 2 + 44 | ||
|
||
const buffer = new ArrayBuffer(length) | ||
|
||
const view = new DataView(buffer) | ||
|
||
const channels = []; let i; let sample | ||
|
||
let offset = 0 | ||
|
||
let pos = 0 | ||
|
||
// write WAVE header | ||
setUint32(0x46464952) // "RIFF" | ||
setUint32(length - 8) // file length - 8 | ||
setUint32(0x45564157) // "WAVE" | ||
|
||
setUint32(0x20746d66) // "fmt " chunk | ||
setUint32(16) // length = 16 | ||
setUint16(1) // PCM (uncompressed) | ||
setUint16(numOfChan) | ||
setUint32(abuffer.sampleRate) | ||
setUint32(abuffer.sampleRate * 2 * numOfChan) // avg. bytes/sec | ||
setUint16(numOfChan * 2) // block-align | ||
setUint16(16) // 16-bit (hardcoded in this demo) | ||
|
||
setUint32(0x61746164) // "data" - chunk | ||
setUint32(length - pos - 4) // chunk length | ||
|
||
// write interleaved data | ||
for (i = 0; i < abuffer.numberOfChannels; i++) { channels.push(abuffer.getChannelData(i)) } | ||
|
||
while (pos < length) { | ||
for (i = 0; i < numOfChan; i++) { // interleave channels | ||
sample = Math.max(-1, Math.min(1, channels[i][offset])) // clamp | ||
sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767) | 0 // scale to 16-bit signed int | ||
view.setInt16(pos, sample, true) // write 16-bit sample | ||
pos += 2 | ||
} | ||
offset++ // next source sample | ||
} | ||
|
||
// create Blob | ||
return new Blob([buffer], { type: 'audio/wav' }) | ||
|
||
function setUint16 (data) { | ||
view.setUint16(pos, data, true) | ||
pos += 2 | ||
} | ||
|
||
function setUint32 (data) { | ||
view.setUint32(pos, data, true) | ||
pos += 4 | ||
} | ||
} | ||
|
||
const forceDownload = (blob, filename = 'output.wav') => { | ||
const url = URL.createObjectURL(blob) | ||
const link = document.createElement('a') | ||
document.body.appendChild(link) | ||
link.style = 'display:none' | ||
link.href = url | ||
link.download = filename | ||
link.click() | ||
URL.revokeObjectURL(url) | ||
document.body.removeChild(link) | ||
} | ||
|
||
const makeDownload = (abuffer, totalSamples, filename) => { | ||
forceDownload(bufferToWave(abuffer, totalSamples), `${filename}-${Date.now()}.wav`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters