Public
Edited
Apr 25, 2023
1 fork
6 stars
Insert cell
md`# Audio waveform with brush`
Insert cell
Insert cell
normalizedChart
Insert cell
Insert cell
audiobuffer = await fetch(wav)
.then(response => response.arrayBuffer())
.then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer))
Insert cell
audiobuffer.duration
Insert cell
samples = 300;
Insert cell
blockSize = Math.floor(rawData.length / samples);
Insert cell
audiobuffer
Insert cell
rawData = audiobuffer.getChannelData(0);
Insert cell
Insert cell
Insert cell
selection
Insert cell
Insert cell
Insert cell
Insert cell
sample = playSample(selection[0],selection[1])
Insert cell
sample.length
Insert cell
audioContext = new (window.AudioContext || window.webkitAudioContext)();
Insert cell
import {chart as normalizedChart, selectionEnd as selection}
with {normalizedData as data}
from "@cpietsch/bar-chart-on-simple-array"
Insert cell
import {fileInput} from "@mbostock/file-input"
Insert cell
sample.getChannelData(0)
Insert cell
sampleBlob = {
var bufferLength = sample.getChannelData(0).length; //
var dataLength = sample.length * bufferLength;
var headerLength = 44;
var wav = new Uint8Array( headerLength + dataLength );
var view = new DataView( wav.buffer );
var recordedBuffers = sample.getChannelData(0);
var bitDepth = 16;
var bytesPerSample = bitDepth / 8;

view.setUint32( 0, 1380533830, false ); // RIFF identifier 'RIFF'
view.setUint32( 4, 36 + dataLength, true ); // file length minus RIFF identifier length and file description length
view.setUint32( 8, 1463899717, false ); // RIFF type 'WAVE'
view.setUint32( 12, 1718449184, false ); // format chunk identifier 'fmt '
view.setUint32( 16, 16, true ); // format chunk length
view.setUint16( 20, 1, true ); // sample format (raw)
view.setUint16( 22, sample.numberOfChannels, true ); // channel count
view.setUint32( 24, sample.sampleRate, true ); // sample rate
view.setUint32( 28, sample.sampleRate * bytesPerSample * sample.numberOfChannels, true ); // byte rate (sample rate * block align)
view.setUint16( 32, bytesPerSample * sample.numberOfChannels, true ); // block align (channel count * bytes per sample)
view.setUint16( 34, bitDepth, true ); // bits per sample
view.setUint32( 36, 1684108385, false); // data chunk identifier 'data'
view.setUint32( 40, dataLength, true ); // data chunk length

for (var i = 0; i < recordedBuffers.length; i++ ) {
wav.set( recordedBuffers[i], i * bufferLength + headerLength );
}

return new Blob([wav.buffer], {type:"audio/wav"});
}
Insert cell
sampleBlob.size
Insert cell
blobUrl = URL.createObjectURL(sampleBlob);
Insert cell
html`<audio id="wavSource"
src="${blobUrl}"
type="audio/wav" controls>
</audio>`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more