UNPKG

@thi.ng/dsp-io-wav

Version:

WAV file format generation

81 lines (80 loc) 2.12 kB
import { f32u16, f32u24, f32u32, f32u8 } from "@thi.ng/binary/float"; import { assert } from "@thi.ng/errors/assert"; import { asBytes, bytes, u16, u24, u32, u8 } from "@thi.ng/transducers-binary/bytes"; import { comp } from "@thi.ng/transducers/comp"; import { concat } from "@thi.ng/transducers/concat"; import { iterator } from "@thi.ng/transducers/iterator"; import { map } from "@thi.ng/transducers/map"; import { reduce } from "@thi.ng/transducers/reduce"; import { take } from "@thi.ng/transducers/take"; const HEADER_SIZE = 44; const CONVERTERS = { 8: (x) => u8(f32u8(x)), 16: (x) => u16(f32u16(x), true), 24: (x) => u24(f32u24(x), true), 32: (x) => u32(f32u32(x), true) }; const wavHeader = (spec) => { const bytesPerSample = spec.bits >> 3; const blockAlign = spec.channels * bytesPerSample; const dataLength = spec.length * blockAlign; return [ u32(1380533830, false), // 'RIFF' u32(dataLength + HEADER_SIZE - 8, true), // riff len u32(1463899717, false), // 'WAVE' u32(1718449184, false), // 'fmt ' u32(16, true), // fmt len, u16(1, true), // audio format id u16(spec.channels, true), u32(spec.sampleRate, true), u32(spec.sampleRate * blockAlign, true), // byte rate u16(blockAlign, true), u16(spec.bits, true), u32(1684108385, false), // 'data' u32(dataLength, true) ]; }; const wavByteArray = (spec, src) => { const convert = CONVERTERS[spec.bits]; assert(!!convert, `unsupported bits/sample: ${spec.bits}`); return reduce( bytes(), new Uint8Array( HEADER_SIZE + spec.length * spec.channels * (spec.bits >> 3) ), concat( wavHeader(spec), iterator(comp(take(spec.length * spec.channels), map(convert)), src) ) ); }; const wavBytes = (spec, src) => { const convert = CONVERTERS[spec.bits]; assert(!!convert, `unsupported bits/sample: ${spec.bits}`); return asBytes( concat( wavHeader(spec), iterator(comp(take(spec.length * spec.channels), map(convert)), src) ) ); }; export { wavByteArray, wavBytes, wavHeader };