@audio/decode 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2018 Dmitry Ivanov <df.creative@gmail.com>
3
+
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21
+ OR OTHER DEALINGS IN THE SOFTWARE.
22
+
@@ -0,0 +1,52 @@
1
+ export interface AudioData {
2
+ channelData: Float32Array[];
3
+ sampleRate: number;
4
+ }
5
+
6
+ export interface StreamDecoder {
7
+ /** Feed a chunk of encoded audio data, or call empty to flush + free. */
8
+ (chunk?: Uint8Array): Promise<AudioData>;
9
+ /** Flush without freeing. */
10
+ flush(): Promise<AudioData>;
11
+ /** Free resources without flushing. */
12
+ free(): void;
13
+ }
14
+
15
+ type Format = 'mp3' | 'flac' | 'opus' | 'oga' | 'm4a' | 'wav' | 'qoa' | 'aac' | 'aiff' | 'caf' | 'webm' | 'amr' | 'wma';
16
+
17
+ interface FormatDecoder {
18
+ /** Create a decoder instance. */
19
+ (): Promise<StreamDecoder>;
20
+ }
21
+
22
+ /** Whole-file decode: auto-detects format. Accepts raw bytes or any source that materializes to bytes (Blob/File/Response). */
23
+ declare function decode(buf: ArrayBuffer | Uint8Array | Blob | Response): Promise<AudioData>;
24
+ /** Chunked decode from stream or async iterable. */
25
+ declare function decode(
26
+ source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,
27
+ format: Format
28
+ ): AsyncGenerator<AudioData>;
29
+
30
+ declare namespace decode {
31
+ export const mp3: FormatDecoder;
32
+ export const flac: FormatDecoder;
33
+ export const opus: FormatDecoder;
34
+ export const oga: FormatDecoder;
35
+ export const m4a: FormatDecoder;
36
+ export const wav: FormatDecoder;
37
+ export const qoa: FormatDecoder;
38
+ export const aac: FormatDecoder;
39
+ export const aiff: FormatDecoder;
40
+ export const caf: FormatDecoder;
41
+ export const webm: FormatDecoder;
42
+ export const amr: FormatDecoder;
43
+ export const wma: FormatDecoder;
44
+ }
45
+
46
+ export default decode;
47
+
48
+ /** Chunked decode from stream or async iterable. */
49
+ export function decodeChunked(
50
+ source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,
51
+ format: Format
52
+ ): AsyncGenerator<AudioData>;
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Audio decoder: whole-file, streaming, chunked
3
+ * @module audio-decode
4
+ *
5
+ * let { channelData, sampleRate } = await decode(buf)
6
+ *
7
+ * for await (let pcm of decode.mp3(source)) { ... }
8
+ *
9
+ * let dec = await decode.mp3()
10
+ * let { channelData, sampleRate } = await dec(chunk)
11
+ * await dec() // close
12
+ */
13
+
14
+ import getType from 'audio-type';
15
+
16
+ const EMPTY = Object.freeze({ channelData: Object.freeze([]), sampleRate: 0 })
17
+
18
+ /**
19
+ * Decode audio.
20
+ * 1 arg: whole-file — auto-detects format, returns Promise<AudioData>
21
+ * 2 args: chunked — streams from ReadableStream/AsyncIterable, returns AsyncGenerator<AudioData>
22
+ */
23
+ export default function decode(src, format) {
24
+ if (format) return decodeChunked(src, format)
25
+ return decodeWhole(src)
26
+ }
27
+
28
+ async function decodeWhole(src) {
29
+ // Blob / File / Response — anything that materializes to an ArrayBuffer
30
+ if (src && typeof src.arrayBuffer === 'function') src = await src.arrayBuffer()
31
+ if (!src || typeof src === 'string' || !(src.buffer || src.byteLength || src.length))
32
+ throw TypeError('Expected ArrayBuffer, Uint8Array, Buffer, Blob, File, or Response')
33
+ let buf = new Uint8Array(src)
34
+
35
+ let type = getType(buf)
36
+ if (!type) throw Error('Unknown audio format')
37
+ if (!decode[type]) throw Error('No decoder for ' + type)
38
+
39
+ let dec = await decode[type]()
40
+ try {
41
+ let result = await dec(buf)
42
+ let flushed = await dec()
43
+ return merge(result, flushed)
44
+ } catch (e) { dec.free(); throw e }
45
+ }
46
+
47
+ /**
48
+ * Decode a ReadableStream or async iterable of encoded audio chunks.
49
+ * @param {ReadableStream|AsyncIterable} source
50
+ * @param {string} format - codec name
51
+ * @returns {AsyncGenerator<{channelData: Float32Array[], sampleRate: number}>}
52
+ */
53
+ export async function* decodeChunked(source, format) {
54
+ if (!decode[format]) throw Error('No decoder for ' + format)
55
+ let dec = await decode[format]()
56
+ try {
57
+ if (source.getReader) {
58
+ let reader = source.getReader()
59
+ while (true) {
60
+ let { done, value } = await reader.read()
61
+ if (done) break
62
+ let result = await dec(value instanceof Uint8Array ? value : new Uint8Array(value))
63
+ if (result.channelData.length) yield result
64
+ }
65
+ } else {
66
+ for await (let chunk of source) {
67
+ let result = await dec(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk))
68
+ if (result.channelData.length) yield result
69
+ }
70
+ }
71
+ let flushed = await dec()
72
+ if (flushed.channelData.length) yield flushed
73
+ } finally {
74
+ dec.free()
75
+ }
76
+ }
77
+
78
+ // --- format registration ---
79
+
80
+ function reg(name, load) {
81
+ decode[name] = fmt(name, async () => {
82
+ let mod = await load()
83
+ // @audio/* packages export { decoder, default }
84
+ if (mod.decoder) {
85
+ let codec = await mod.decoder()
86
+ return streamDecoder(
87
+ chunk => codec.decode(chunk),
88
+ codec.flush ? () => codec.flush() : null,
89
+ codec.free ? () => codec.free() : null
90
+ )
91
+ }
92
+ // wasm-audio-decoders export class with .ready
93
+ let init = mod.default || mod
94
+ let codec = typeof init === 'function' ? await init() : init
95
+ if (codec.ready) await codec.ready
96
+ return streamDecoder(
97
+ chunk => codec.decode(chunk),
98
+ codec.flush ? () => codec.flush() : null,
99
+ codec.free ? () => codec.free() : null
100
+ )
101
+ })
102
+ }
103
+
104
+ function fmt(name, init) {
105
+ let fn = (src) => {
106
+ if (!src) return init()
107
+ // async iterable / ReadableStream → streaming decode
108
+ if (src[Symbol.asyncIterator] || src.getReader) return decodeChunked(src, name)
109
+ // buffer → whole-file decode
110
+ console.warn('decode.' + name + '(data) is deprecated, use decode(data)')
111
+ return (async () => {
112
+ let dec = await init()
113
+ try {
114
+ let result = await dec(src instanceof Uint8Array ? src : new Uint8Array(src.buffer || src))
115
+ let flushed = await dec()
116
+ return merge(result, flushed)
117
+ } catch (e) { dec.free(); throw e }
118
+ })()
119
+ }
120
+ return fn
121
+ }
122
+
123
+ // --- codecs ---
124
+
125
+ reg('mp3', () => import('@audio/decode-mp3'))
126
+ reg('flac', () => import('@audio/decode-flac'))
127
+ reg('opus', () => import('@audio/decode-opus'))
128
+ reg('oga', () => import('@audio/decode-vorbis'))
129
+
130
+ reg('m4a', () => import('@audio/decode-aac'))
131
+
132
+ reg('wav', () => import('@audio/decode-wav'))
133
+ reg('qoa', () => import('@audio/decode-qoa'))
134
+
135
+ reg('aac', () => import('@audio/decode-aac'))
136
+ reg('aiff', () => import('@audio/decode-aiff'))
137
+ reg('caf', () => import('@audio/decode-caf'))
138
+ reg('webm', () => import('@audio/decode-webm'))
139
+ reg('amr', () => import('@audio/decode-amr'))
140
+ reg('wma', () => import('@audio/decode-wma'))
141
+
142
+ /**
143
+ * StreamDecoder — a callable function:
144
+ * dec(chunk) — decode data, returns { channelData, sampleRate }
145
+ * dec() — end of stream: flush remaining samples + free resources
146
+ * dec.flush() — flush without freeing
147
+ * dec.free() — release resources without flushing
148
+ */
149
+ function streamDecoder(onDecode, onFlush, onFree) {
150
+ let done = false
151
+ let fn = async (chunk) => {
152
+ if (chunk) {
153
+ if (done) throw Error('Decoder already freed')
154
+ try { return norm(await onDecode(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk))) }
155
+ catch (e) { done = true; onFree?.(); throw e }
156
+ }
157
+ // null/undefined = end of stream
158
+ if (done) return EMPTY
159
+ done = true
160
+ try {
161
+ let result = onFlush ? norm(await onFlush()) : EMPTY
162
+ onFree?.()
163
+ return result
164
+ } catch (e) { onFree?.(); throw e }
165
+ }
166
+ fn.flush = async () => {
167
+ if (done) return EMPTY
168
+ return onFlush ? norm(await onFlush()) : EMPTY
169
+ }
170
+ fn.free = () => {
171
+ if (done) return
172
+ done = true
173
+ onFree?.()
174
+ }
175
+ return fn
176
+ }
177
+
178
+ // extract { channelData, sampleRate } from codec result
179
+ function norm(r) {
180
+ if (!r?.channelData?.length) return EMPTY
181
+ let { channelData, sampleRate, samplesDecoded } = r
182
+ if (samplesDecoded != null && samplesDecoded < channelData[0].length)
183
+ channelData = channelData.map(ch => ch.subarray(0, samplesDecoded))
184
+ if (!channelData[0]?.length) return EMPTY
185
+ // collapse duplicate stereo to mono (some decoders always output 2ch for mono sources)
186
+ if (channelData.length === 2) {
187
+ let a = channelData[0], b = channelData[1], same = true
188
+ for (let i = 0; i < a.length; i += 37) { if (a[i] !== b[i]) { same = false; break } }
189
+ if (same) channelData = [a]
190
+ }
191
+ return { channelData, sampleRate }
192
+ }
193
+
194
+ // merge two decode results
195
+ function merge(a, b) {
196
+ if (!b?.channelData?.length) return a
197
+ if (!a?.channelData?.length) return b
198
+ let ach = a.channelData.length, bch = b.channelData.length
199
+ let ch = Math.max(ach, bch)
200
+ return {
201
+ channelData: Array.from({ length: ch }, (_, i) => {
202
+ let ac = a.channelData[i % ach], bc = b.channelData[i % bch]
203
+ let merged = new Float32Array(ac.length + bc.length)
204
+ merged.set(ac)
205
+ merged.set(bc, ac.length)
206
+ return merged
207
+ }),
208
+ sampleRate: a.sampleRate
209
+ }
210
+ }
package/meta.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Meta parsers — re-export from codec packages.
3
+ * @module audio-decode/meta
4
+ *
5
+ * import { wav, mp3, flac, oga, opus, m4a } from 'audio-decode/meta'
6
+ * let result = wav(bytes) // { meta, sampleRate, markers, regions } | null
7
+ */
8
+
9
+ export { parseMeta as wav } from '@audio/decode-wav/meta'
10
+ export { parseMeta as mp3, parseId3v2 } from '@audio/decode-mp3/meta'
11
+ export { parseMeta as flac } from '@audio/decode-flac/meta'
12
+ export { parseMeta as oga } from '@audio/decode-vorbis/meta'
13
+ export { parseMeta as opus } from '@audio/decode-opus/meta'
14
+ export { parseMeta as m4a } from '@audio/decode-aac/meta'
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@audio/decode",
3
+ "version": "3.11.0",
4
+ "description": "Decode audio data in node or browser",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "audio-decode.js",
8
+ "types": "audio-decode.d.ts",
9
+ "files": [
10
+ "audio-decode.js",
11
+ "audio-decode.d.ts",
12
+ "stream.js",
13
+ "stream.d.ts",
14
+ "meta.js",
15
+ "test.html"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "browser": "./audio-decode.js",
20
+ "node": "./audio-decode.js",
21
+ "default": "./audio-decode.js"
22
+ },
23
+ "./stream": "./stream.js",
24
+ "./meta": "./meta.js",
25
+ "./package.json": "./package.json"
26
+ },
27
+ "workspaces": [
28
+ "packages/*"
29
+ ],
30
+ "dependencies": {
31
+ "@audio/decode-aac": "^1.2.0",
32
+ "@audio/decode-aiff": "^1.1.3",
33
+ "@audio/decode-amr": "^1.0.0",
34
+ "@audio/decode-caf": "^1.2.0",
35
+ "@audio/decode-flac": "^1.1.0",
36
+ "@audio/decode-mp3": "^1.1.0",
37
+ "@audio/decode-opus": "^1.1.0",
38
+ "@audio/decode-qoa": "^1.0.0",
39
+ "@audio/decode-vorbis": "^1.1.0",
40
+ "@audio/decode-wav": "^1.3.0",
41
+ "@audio/decode-webm": "^1.0.0",
42
+ "@audio/decode-wma": "^1.0.0",
43
+ "audio-type": "^2.4.0"
44
+ },
45
+ "devDependencies": {
46
+ "audio-lena": "^3.0.0",
47
+ "base64-arraybuffer": "^1.0.2",
48
+ "esbuild": "^0.28.0",
49
+ "playwright": "^1.58.0",
50
+ "tst": "^9.2.2"
51
+ },
52
+ "scripts": {
53
+ "test": "node test.js",
54
+ "test:browser": "node test.browser.js",
55
+ "test:all": "node test.js && node test.browser.js",
56
+ "publish:all": "for d in packages/* .; do [ -f \"$d/package.json\" ] || continue; id=$(node -p \"require('./'+'$d'+'/package.json').name+'@'+require('./'+'$d'+'/package.json').version\"); npm view \"$id\" version >/dev/null 2>&1 && echo \"skip $id\" || (cd \"$d\" && npm publish); done"
57
+ },
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "git+https://github.com/audiojs/decode.git"
61
+ },
62
+ "keywords": [
63
+ "audio",
64
+ "decode",
65
+ "decoder",
66
+ "codec",
67
+ "mp3",
68
+ "wav",
69
+ "ogg",
70
+ "vorbis",
71
+ "opus",
72
+ "flac",
73
+ "aac",
74
+ "m4a",
75
+ "qoa",
76
+ "aiff",
77
+ "caf",
78
+ "webm",
79
+ "amr",
80
+ "wma",
81
+ "pcm",
82
+ "streaming"
83
+ ],
84
+ "author": "Dmitry Iv. <dfcreative@gmail.com>",
85
+ "license": "MIT",
86
+ "bugs": {
87
+ "url": "https://github.com/audiojs/decode/issues"
88
+ },
89
+ "homepage": "https://github.com/audiojs/decode#readme",
90
+ "publishConfig": {
91
+ "access": "public"
92
+ },
93
+ "engines": {
94
+ "node": ">=18"
95
+ }
96
+ }
package/readme.md ADDED
@@ -0,0 +1,154 @@
1
+ # @audio/decode [![test](https://github.com/audiojs/decode/actions/workflows/test.js.yml/badge.svg)](https://github.com/audiojs/decode/actions/workflows/test.js.yml)
2
+
3
+ Decode any audio format to raw samples.<br>
4
+ JS / WASM – no ffmpeg, no native bindings, works in both node and browser.<br>
5
+ Small API, minimal size, near-native performance, lazy-loading, chunked decoding.
6
+
7
+ [![npm install @audio/decode](https://nodei.co/npm/audio-decode.png?mini=true)](https://npmjs.org/package/@audio/decode/)
8
+
9
+ ```js
10
+ import decode from '@audio/decode';
11
+
12
+ const { channelData, sampleRate } = await decode(anyAudioBuffer);
13
+ ```
14
+
15
+ #### Supported formats
16
+
17
+ | Format | Package | Size | Engine |
18
+ |--------|---------|------|--------|
19
+ | MP3 | [@audio/decode-mp3](./packages/decode-mp3) | 92 KB | WASM |
20
+ | WAV | [@audio/decode-wav](./packages/decode-wav) | 4 KB | JS |
21
+ | OGG Vorbis | [@audio/decode-vorbis](./packages/decode-vorbis) | 164 KB | WASM |
22
+ | FLAC | [@audio/decode-flac](./packages/decode-flac) | 133 KB | WASM |
23
+ | Opus | [@audio/decode-opus](./packages/decode-opus) | 178 KB | WASM |
24
+ | M4A / AAC / ALAC | [@audio/decode-aac](./packages/decode-aac) | 368 KB | WASM + JS |
25
+ | QOA | [@audio/decode-qoa](./packages/decode-qoa) | 8 KB | JS |
26
+ | AIFF | [@audio/decode-aiff](./packages/decode-aiff) | 20 KB | JS |
27
+ | CAF | [@audio/decode-caf](./packages/decode-caf) | 7 KB | JS |
28
+ | WebM | [@audio/decode-webm](./packages/decode-webm) | 263 KB | WASM |
29
+ | AMR | [@audio/decode-amr](./packages/decode-amr) | 241 KB | WASM |
30
+ | WMA | [@audio/decode-wma](./packages/decode-wma) | 91 KB | WASM |
31
+
32
+ ### Whole-file
33
+
34
+ Auto-detects format. Input can be _ArrayBuffer_, _Uint8Array_, _Buffer_, or anything
35
+ that materializes to bytes — a _Blob_/_File_ (browser file input, drag-drop) or a fetch _Response_.
36
+
37
+ ```js
38
+ import decode from '@audio/decode'
39
+
40
+ let { channelData, sampleRate } = await decode(buf)
41
+ let fromFile = await decode(fileInput.files[0]) // File
42
+ let fromUrl = await decode(await fetch(url)) // Response
43
+ ```
44
+
45
+
46
+ ### Chunked
47
+
48
+ ```js
49
+ let dec = await decode.mp3()
50
+ let a = await dec(chunk1) // { channelData, sampleRate }
51
+ let b = await dec(chunk2)
52
+ await dec() // close
53
+ ```
54
+
55
+ ### Streaming
56
+
57
+ ```js
58
+ import decode from '@audio/decode'
59
+
60
+ for await (let { channelData, sampleRate } of decode.mp3(response.body)) {
61
+ // process chunks
62
+ }
63
+ ```
64
+
65
+ Works with `ReadableStream`, `fetch` body, Node stream, or any async iterable.
66
+
67
+ Formats: `mp3`, `flac`, `opus`, `oga`, `m4a`, `wav`, `qoa`, `aac`, `aiff`, `caf`, `webm`, `amr`, `wma`.
68
+
69
+ ### Browser
70
+
71
+ Each codec is a self-contained bundle under `@audio/*` — no transitive deps, no import map bloat.
72
+ For selective loading in the browser (avoids bundling all codecs):
73
+
74
+ ```html
75
+ <script type="importmap">
76
+ {
77
+ "imports": {
78
+ "@audio/decode": "https://esm.sh/audio-decode",
79
+ "audio-type": "https://esm.sh/audio-type",
80
+ "@audio/decode-mp3": "https://esm.sh/@audio/decode-mp3",
81
+ "@audio/decode-wav": "https://esm.sh/@audio/decode-wav",
82
+ "@audio/decode-flac": "https://esm.sh/@audio/decode-flac",
83
+ "@audio/decode-opus": "https://esm.sh/@audio/decode-opus",
84
+ "@audio/decode-vorbis": "https://esm.sh/@audio/decode-vorbis",
85
+ "@audio/decode-aac": "https://esm.sh/@audio/decode-aac",
86
+ "@audio/decode-qoa": "https://esm.sh/@audio/decode-qoa",
87
+ "@audio/decode-aiff": "https://esm.sh/@audio/decode-aiff",
88
+ "@audio/decode-caf": "https://esm.sh/@audio/decode-caf",
89
+ "@audio/decode-webm": "https://esm.sh/@audio/decode-webm",
90
+ "@audio/decode-amr": "https://esm.sh/@audio/decode-amr",
91
+ "@audio/decode-wma": "https://esm.sh/@audio/decode-wma"
92
+ }
93
+ }
94
+ </script>
95
+ <script type="module">
96
+ import decode from '@audio/decode'
97
+ let { channelData, sampleRate } = await decode(buf)
98
+ </script>
99
+ ```
100
+
101
+ Only list the codecs you need — each `@audio/decode-*` package bundles all its WASM/JS deps internally.
102
+
103
+ ### Metadata
104
+
105
+ Read tags, pictures, markers and regions without decoding samples. Available for
106
+ `wav`, `mp3`, `flac`, `oga` (Ogg Vorbis), `opus`, and `m4a`.
107
+
108
+ ```js
109
+ import { wav, mp3, flac, oga, opus, m4a } from '@audio/decode/meta'
110
+
111
+ let { meta, sampleRate, markers, regions } = mp3(bytes)
112
+ // meta: { title, artist, album, year, bpm, key, comment, pictures, raw, ... }
113
+ // markers: [{ sample, label }]
114
+ // regions: [{ sample, length, label }]
115
+ ```
116
+
117
+ Each codec sub-package also exposes its parser directly:
118
+
119
+ ```js
120
+ import { parseMeta } from '@audio/decode-wav/meta'
121
+ let info = parseMeta(wavBytes)
122
+ ```
123
+
124
+ ### WebWorker
125
+
126
+ Each `@audio/decode-*` package is a self-contained ESM module — import directly in a worker:
127
+
128
+ ```js
129
+ // decode-worker.js
130
+ import decode from '@audio/decode-mp3'
131
+
132
+ self.onmessage = async ({ data }) => {
133
+ let pcm = await decode(data)
134
+ self.postMessage(pcm, pcm.channelData.map(ch => ch.buffer))
135
+ }
136
+
137
+ // main.js
138
+ let worker = new Worker('./decode-worker.js', { type: 'module' })
139
+ worker.postMessage(mp3buf, [mp3buf])
140
+ worker.onmessage = ({ data }) => { /* { channelData, sampleRate } */ }
141
+ ```
142
+
143
+ ## See also
144
+
145
+ * [encode](https://github.com/audiojs/encode) – encode PCM into any audio format.
146
+ * [audio-type](https://github.com/audiojs/audio-type) – detect audio format from buffer.
147
+ <!--
148
+ * [wasm-audio-decoders](https://github.com/eshaz/wasm-audio-decoders) – compact & fast WASM audio decoders.
149
+ * [AudioDecoder](https://developer.mozilla.org/en-US/docs/Web/API/AudioDecoder) – native WebCodecs decoder API.
150
+ * [decodeAudioData](https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/decodeAudioData) – built-in browser decoding method.
151
+ * [ffmpeg.wasm](https://github.com/ffmpegwasm/ffmpeg.wasm) – full encoding/decoding library.
152
+ -->
153
+
154
+ <p align="center"><a href="./LICENSE">MIT</a> • <a href="https://github.com/krishnized/license/">ॐ</a>
package/stream.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { AudioData } from './audio-decode.js';
2
+
3
+ type Format = 'mp3' | 'flac' | 'opus' | 'oga' | 'm4a' | 'wav' | 'qoa' | 'aac' | 'aiff' | 'caf' | 'webm' | 'amr' | 'wma';
4
+
5
+ /** Chunked decode from stream or async iterable. */
6
+ declare function decodeChunked(
7
+ source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,
8
+ format: Format
9
+ ): AsyncGenerator<AudioData>;
10
+
11
+ export default decodeChunked;
12
+ export { decodeChunked };
13
+
14
+ export default decodeStream;
15
+ export { decodeStream };
package/stream.js ADDED
@@ -0,0 +1 @@
1
+ export { decodeChunked as default, decodeChunked } from './audio-decode.js'
package/test.html ADDED
@@ -0,0 +1,34 @@
1
+ <!doctype html>
2
+ <title>audio-decode tests</title>
3
+ <script type="importmap">
4
+ {
5
+ "imports": {
6
+ "./audio-decode.js": "./audio-decode.js",
7
+ "audio-lena/wav": "./node_modules/audio-lena/wav.js",
8
+ "audio-lena/mp3": "./node_modules/audio-lena/mp3.js",
9
+ "audio-lena/ogg": "./node_modules/audio-lena/ogg.js",
10
+ "audio-lena/flac": "./node_modules/audio-lena/flac.js",
11
+ "audio-lena/opus": "./node_modules/audio-lena/opus.js",
12
+ "audio-lena/aiff": "./node_modules/audio-lena/aiff.js",
13
+ "audio-lena/caf": "./node_modules/audio-lena/caf.js",
14
+ "audio-lena/webm": "./node_modules/audio-lena/webm.js",
15
+ "audio-lena/aac": "./node_modules/audio-lena/aac.js",
16
+ "audio-lena/m4a": "./node_modules/audio-lena/m4a.js",
17
+ "audio-type": "./node_modules/audio-type/audio-type.js",
18
+ "tst": "./node_modules/tst/tst.js",
19
+ "@audio/decode-mp3": "./packages/decode-mp3/decode-mp3.js",
20
+ "@audio/decode-wav": "./packages/decode-wav/decode-wav.js",
21
+ "@audio/decode-flac": "./packages/decode-flac/decode-flac.js",
22
+ "@audio/decode-opus": "./packages/decode-opus/decode-opus.js",
23
+ "@audio/decode-vorbis": "./packages/decode-vorbis/decode-vorbis.js",
24
+ "@audio/decode-aac": "./packages/decode-aac/decode-aac.js",
25
+ "@audio/decode-qoa": "./packages/decode-qoa/decode-qoa.js",
26
+ "@audio/decode-aiff": "./packages/decode-aiff/decode-aiff.js",
27
+ "@audio/decode-caf": "./packages/decode-caf/decode-caf.js",
28
+ "@audio/decode-webm": "./packages/decode-webm/decode-webm.js",
29
+ "@audio/decode-amr": "./packages/decode-amr/decode-amr.js",
30
+ "@audio/decode-wma": "./packages/decode-wma/decode-wma.js"
31
+ }
32
+ }
33
+ </script>
34
+ <script type="module" src="./test.js"></script>