@audio/decode-aac 1.0.2
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 +9 -0
- package/README.md +60 -0
- package/decode-aac.d.ts +16 -0
- package/decode-aac.js +356 -0
- package/package.json +46 -0
- package/src/aac.wasm.cjs +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
This work is offered to Krishna (https://github.com/krishnized/license).
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
This package is licensed under the GNU General Public License v2.0 (GPL-2.0),
|
|
6
|
+
as required by the included FAAD2 library.
|
|
7
|
+
|
|
8
|
+
FAAD2 Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
|
|
9
|
+
Full GPL-2.0 text: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# decode-aac
|
|
2
|
+
|
|
3
|
+
Decode AAC/M4A audio to PCM float samples. FAAD2 compiled to WASM — works in Node.js and browsers, no native dependencies.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm i @audio/aac-decode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import decode from '@audio/aac-decode'
|
|
15
|
+
|
|
16
|
+
// M4A or raw ADTS — auto-detected
|
|
17
|
+
let { channelData, sampleRate } = await decode(uint8array)
|
|
18
|
+
// channelData: Float32Array[] (one per channel)
|
|
19
|
+
// sampleRate: number
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Streaming
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import { decoder } from '@audio/aac-decode'
|
|
26
|
+
|
|
27
|
+
let dec = await decoder()
|
|
28
|
+
let { channelData, sampleRate } = dec.decode(chunk)
|
|
29
|
+
dec.free()
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
### `decode(src: Uint8Array | ArrayBuffer): Promise<AudioData>`
|
|
35
|
+
|
|
36
|
+
Whole-file decode. Auto-detects M4A (MP4 container) vs raw ADTS.
|
|
37
|
+
|
|
38
|
+
### `decoder(): Promise<AACDecoder>`
|
|
39
|
+
|
|
40
|
+
Creates a decoder instance for manual control.
|
|
41
|
+
|
|
42
|
+
- **`dec.decode(data)`** — decode chunk, returns `{ channelData, sampleRate }`
|
|
43
|
+
- **`dec.flush()`** — flush remaining (returns empty for AAC)
|
|
44
|
+
- **`dec.free()`** — release WASM memory
|
|
45
|
+
|
|
46
|
+
### `AudioData`
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
{ channelData: Float32Array[], sampleRate: number }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Formats
|
|
53
|
+
|
|
54
|
+
- M4A / MP4 with AAC audio
|
|
55
|
+
- Raw ADTS streams (.aac)
|
|
56
|
+
- LC, HE-AAC v1/v2 (SBR, PS)
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
GPL-2.0 (FAAD2) — [krishnized](https://github.com/krishnized/license)
|
package/decode-aac.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface AudioData {
|
|
2
|
+
channelData: Float32Array[];
|
|
3
|
+
sampleRate: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
interface AACDecoder {
|
|
7
|
+
decode(data: Uint8Array): AudioData;
|
|
8
|
+
flush(): AudioData;
|
|
9
|
+
free(): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Whole-file decode — auto-detects M4A vs ADTS */
|
|
13
|
+
export default function decode(src: ArrayBuffer | Uint8Array): Promise<AudioData>;
|
|
14
|
+
|
|
15
|
+
/** Create streaming decoder instance */
|
|
16
|
+
export function decoder(): Promise<AACDecoder>;
|
package/decode-aac.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AAC decoder — FAAD2 compiled to WASM
|
|
3
|
+
* Decodes M4A (MP4/AAC) and raw ADTS streams
|
|
4
|
+
*
|
|
5
|
+
* let { channelData, sampleRate } = await decode(m4abuf)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
let _modP
|
|
9
|
+
|
|
10
|
+
async function getMod() {
|
|
11
|
+
if (_modP) return _modP
|
|
12
|
+
let p = (async () => {
|
|
13
|
+
let createAAC
|
|
14
|
+
if (typeof process !== 'undefined' && process.versions?.node) {
|
|
15
|
+
let m = 'module'
|
|
16
|
+
let { createRequire } = await import(m)
|
|
17
|
+
createAAC = createRequire(import.meta.url)('./src/aac.wasm.cjs')
|
|
18
|
+
} else {
|
|
19
|
+
let mod = await import('./src/aac.wasm.cjs')
|
|
20
|
+
createAAC = mod.default || mod
|
|
21
|
+
}
|
|
22
|
+
return createAAC()
|
|
23
|
+
})()
|
|
24
|
+
_modP = p
|
|
25
|
+
try { return await p }
|
|
26
|
+
catch (e) { _modP = null; throw e }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Whole-file decode
|
|
31
|
+
* @param {Uint8Array|ArrayBuffer} src
|
|
32
|
+
* @returns {Promise<{channelData: Float32Array[], sampleRate: number}>}
|
|
33
|
+
*/
|
|
34
|
+
export default async function decode(src) {
|
|
35
|
+
let buf = src instanceof Uint8Array ? src : new Uint8Array(src)
|
|
36
|
+
let dec = await decoder()
|
|
37
|
+
try {
|
|
38
|
+
return dec.decode(buf)
|
|
39
|
+
} finally {
|
|
40
|
+
dec.free()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create decoder instance
|
|
46
|
+
* @returns {Promise<{decode(chunk: Uint8Array): {channelData, sampleRate}, flush(), free()}>}
|
|
47
|
+
*/
|
|
48
|
+
export async function decoder() {
|
|
49
|
+
return new AACDecoder(await getMod())
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const EMPTY = Object.freeze({ channelData: [], sampleRate: 0 })
|
|
53
|
+
|
|
54
|
+
class AACDecoder {
|
|
55
|
+
constructor(mod) {
|
|
56
|
+
this.m = mod
|
|
57
|
+
this.h = null
|
|
58
|
+
this.sr = 0
|
|
59
|
+
this.ch = 0
|
|
60
|
+
this.done = false
|
|
61
|
+
this._ptr = 0
|
|
62
|
+
this._cap = 0
|
|
63
|
+
this._left = null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
decode(data) {
|
|
67
|
+
if (this.done) throw Error('Decoder already freed')
|
|
68
|
+
if (!data?.length) return EMPTY
|
|
69
|
+
|
|
70
|
+
let buf = data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
71
|
+
|
|
72
|
+
// detect M4A (ftyp box at offset 4)
|
|
73
|
+
if (buf.length > 8 && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70)
|
|
74
|
+
return this._decodeM4A(buf)
|
|
75
|
+
|
|
76
|
+
return this._decodeADTS(buf)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
flush() {
|
|
80
|
+
if (this._left) this._left = null
|
|
81
|
+
return EMPTY
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
free() {
|
|
85
|
+
if (this.done) return
|
|
86
|
+
this.done = true
|
|
87
|
+
if (this.h) {
|
|
88
|
+
this.m._aac_close(this.h)
|
|
89
|
+
this.m._aac_free_buf()
|
|
90
|
+
this.h = null
|
|
91
|
+
}
|
|
92
|
+
if (this._ptr) {
|
|
93
|
+
this.m._free(this._ptr)
|
|
94
|
+
this._ptr = 0
|
|
95
|
+
this._cap = 0
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_alloc(len) {
|
|
100
|
+
if (len > this._cap) {
|
|
101
|
+
if (this._ptr) this.m._free(this._ptr)
|
|
102
|
+
this._cap = len
|
|
103
|
+
this._ptr = this.m._malloc(len)
|
|
104
|
+
}
|
|
105
|
+
return this._ptr
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_decodeADTS(buf) {
|
|
109
|
+
let m = this.m
|
|
110
|
+
|
|
111
|
+
// prepend leftover from previous call
|
|
112
|
+
if (this._left) {
|
|
113
|
+
let merged = new Uint8Array(this._left.length + buf.length)
|
|
114
|
+
merged.set(this._left)
|
|
115
|
+
merged.set(buf, this._left.length)
|
|
116
|
+
buf = merged
|
|
117
|
+
this._left = null
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!this.h) {
|
|
121
|
+
if (buf.length < 7) { this._left = buf.slice(); return EMPTY }
|
|
122
|
+
let h = m._aac_create()
|
|
123
|
+
let srP = m._aac_sr_ptr(), chP = m._aac_ch_ptr()
|
|
124
|
+
let ptr = this._alloc(buf.length)
|
|
125
|
+
m.HEAPU8.set(buf, ptr)
|
|
126
|
+
let consumed = m._aac_init(h, ptr, buf.length, srP, chP)
|
|
127
|
+
if (consumed < 0) { m._aac_close(h); throw Error('ADTS init failed (code ' + consumed + ')') }
|
|
128
|
+
this.sr = m.getValue(srP, 'i32')
|
|
129
|
+
this.ch = m.getValue(chP, 'i8')
|
|
130
|
+
if (!this.ch) {
|
|
131
|
+
// not enough data to detect channels — buffer for next call
|
|
132
|
+
m._aac_close(h)
|
|
133
|
+
this._left = buf.length < 8192 ? buf.slice() : null
|
|
134
|
+
return EMPTY
|
|
135
|
+
}
|
|
136
|
+
this.h = h
|
|
137
|
+
buf = buf.subarray(consumed)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// extract complete ADTS frames only — never feed partial data to FAAD2
|
|
141
|
+
let frames = [], pos = 0
|
|
142
|
+
while (pos + 6 < buf.length) {
|
|
143
|
+
if (buf[pos] !== 0xFF || (buf[pos + 1] & 0xF6) !== 0xF0) { pos++; continue }
|
|
144
|
+
let flen = ((buf[pos + 3] & 0x03) << 11) | (buf[pos + 4] << 3) | (buf[pos + 5] >> 5)
|
|
145
|
+
if (flen < 7 || pos + flen > buf.length) break
|
|
146
|
+
frames.push(buf.subarray(pos, pos + flen))
|
|
147
|
+
pos += flen
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (pos < buf.length) {
|
|
151
|
+
let left = buf.subarray(pos)
|
|
152
|
+
this._left = left.length < 8192 ? left.slice() : null
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!frames.length) return EMPTY
|
|
156
|
+
return this._feedFrames(frames)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
_decodeM4A(buf) {
|
|
160
|
+
let { asc, frames } = demuxM4A(buf)
|
|
161
|
+
if (!asc || !frames.length) return EMPTY
|
|
162
|
+
|
|
163
|
+
let m = this.m
|
|
164
|
+
let h = m._aac_create()
|
|
165
|
+
|
|
166
|
+
let srP = m._aac_sr_ptr(), chP = m._aac_ch_ptr()
|
|
167
|
+
let ptr = this._alloc(asc.length)
|
|
168
|
+
m.HEAPU8.set(asc, ptr)
|
|
169
|
+
let err = m._aac_init2(h, ptr, asc.length, srP, chP)
|
|
170
|
+
if (err < 0) { m._aac_close(h); throw Error('M4A init failed (code ' + err + ')') }
|
|
171
|
+
|
|
172
|
+
this.sr = m.getValue(srP, 'i32')
|
|
173
|
+
this.ch = m.getValue(chP, 'i8')
|
|
174
|
+
if (!this.ch) { m._aac_close(h); throw Error('M4A init: no channels in ASC') }
|
|
175
|
+
this.h = h
|
|
176
|
+
|
|
177
|
+
return this._feedFrames(frames)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
_feedFrames(frames) {
|
|
181
|
+
let m = this.m, h = this.h
|
|
182
|
+
let chunks = [], totalPerCh = 0, channels = this.ch, errors = 0
|
|
183
|
+
|
|
184
|
+
for (let frame of frames) {
|
|
185
|
+
let ptr = this._alloc(frame.length)
|
|
186
|
+
m.HEAPU8.set(frame, ptr)
|
|
187
|
+
let out = m._aac_decode(h, ptr, frame.length)
|
|
188
|
+
if (!out) { errors++; continue }
|
|
189
|
+
|
|
190
|
+
let n = m._aac_samples()
|
|
191
|
+
let sr = m._aac_samplerate()
|
|
192
|
+
if (sr) this.sr = sr
|
|
193
|
+
let ch = m._aac_channels()
|
|
194
|
+
if (ch) channels = ch
|
|
195
|
+
|
|
196
|
+
let spc = n / channels
|
|
197
|
+
chunks.push({ data: new Float32Array(m.HEAPF32.buffer, out, n).slice(), ch: channels, spc })
|
|
198
|
+
totalPerCh += spc
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!totalPerCh) return EMPTY
|
|
202
|
+
|
|
203
|
+
let channelData = Array.from({ length: channels }, () => new Float32Array(totalPerCh))
|
|
204
|
+
let pos = 0
|
|
205
|
+
for (let { data, ch, spc } of chunks) {
|
|
206
|
+
for (let c = 0; c < ch; c++) {
|
|
207
|
+
let out = channelData[c]
|
|
208
|
+
for (let s = 0; s < spc; s++) out[pos + s] = data[s * ch + c]
|
|
209
|
+
}
|
|
210
|
+
pos += spc
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return { channelData, sampleRate: this.sr, errors }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
// ===== M4A demuxer =====
|
|
219
|
+
|
|
220
|
+
function demuxM4A(buf) {
|
|
221
|
+
let asc = null, stsz = null, stco = null, stsc = null
|
|
222
|
+
let mdatOff = 0, mdatLen = 0
|
|
223
|
+
|
|
224
|
+
parseBoxes(buf, 0, buf.length, (type, data, off) => {
|
|
225
|
+
if (type === 'esds') asc = parseEsds(data)
|
|
226
|
+
else if (type === 'stsz') stsz = parseStsz(data)
|
|
227
|
+
else if (type === 'stco') stco = parseStco(data)
|
|
228
|
+
else if (type === 'co64') stco = parseCo64(data)
|
|
229
|
+
else if (type === 'stsc') stsc = parseStsc(data)
|
|
230
|
+
else if (type === 'mdat') { mdatOff = off; mdatLen = data.length }
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
if (!asc) return { asc: null, frames: [] }
|
|
234
|
+
|
|
235
|
+
let frames = (stsz && stco)
|
|
236
|
+
? extractFrames(buf, stsz, stco, stsc)
|
|
237
|
+
: mdatLen ? scanMdat(buf, mdatOff, mdatLen) : []
|
|
238
|
+
|
|
239
|
+
return { asc, frames }
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const CONTAINERS = new Set(['moov', 'trak', 'mdia', 'minf', 'stbl', 'udta', 'meta', 'edts', 'sinf'])
|
|
243
|
+
|
|
244
|
+
function parseBoxes(buf, start, end, cb) {
|
|
245
|
+
let off = start
|
|
246
|
+
while (off < end - 8) {
|
|
247
|
+
let size = r32(buf, off)
|
|
248
|
+
let type = String.fromCharCode(buf[off + 4], buf[off + 5], buf[off + 6], buf[off + 7])
|
|
249
|
+
|
|
250
|
+
if (size === 0) {
|
|
251
|
+
size = end - off
|
|
252
|
+
} else if (size === 1 && off + 16 <= end) {
|
|
253
|
+
size = r32(buf, off + 12)
|
|
254
|
+
if (size < 16) break
|
|
255
|
+
} else if (size < 8) {
|
|
256
|
+
break
|
|
257
|
+
}
|
|
258
|
+
if (off + size > end) size = end - off
|
|
259
|
+
|
|
260
|
+
let bodyOff = off + 8
|
|
261
|
+
|
|
262
|
+
if (type === 'stsd') parseSampleDesc(buf, bodyOff, size - 8, cb)
|
|
263
|
+
else if (CONTAINERS.has(type)) parseBoxes(buf, bodyOff + (type === 'meta' ? 4 : 0), off + size, cb)
|
|
264
|
+
else cb(type, buf.subarray(bodyOff, off + size), bodyOff)
|
|
265
|
+
|
|
266
|
+
off += size
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function parseSampleDesc(buf, off, len, cb) {
|
|
271
|
+
let entries = r32(buf, off + 4), pos = off + 8
|
|
272
|
+
for (let i = 0; i < entries && pos < off + len; i++) {
|
|
273
|
+
let eSize = r32(buf, pos)
|
|
274
|
+
let eType = String.fromCharCode(buf[pos + 4], buf[pos + 5], buf[pos + 6], buf[pos + 7])
|
|
275
|
+
if (eType === 'mp4a' && eSize > 36) parseBoxes(buf, pos + 36, pos + eSize, cb)
|
|
276
|
+
pos += eSize
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function parseEsds(data) {
|
|
281
|
+
let off = 4
|
|
282
|
+
while (off < data.length - 2) {
|
|
283
|
+
let tag = data[off++], len = 0, b
|
|
284
|
+
do { b = data[off++]; len = (len << 7) | (b & 0x7f) } while (b & 0x80 && off < data.length)
|
|
285
|
+
if (tag === 0x03) off += 3
|
|
286
|
+
else if (tag === 0x04) off += 13
|
|
287
|
+
else if (tag === 0x05) return data.subarray(off, off + len)
|
|
288
|
+
else off += len
|
|
289
|
+
}
|
|
290
|
+
return null
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function parseStsz(data) {
|
|
294
|
+
let sz = r32(data, 4), n = r32(data, 8)
|
|
295
|
+
if (sz) return Array(n).fill(sz)
|
|
296
|
+
let sizes = new Array(n)
|
|
297
|
+
for (let i = 0; i < n; i++) sizes[i] = r32(data, 12 + i * 4)
|
|
298
|
+
return sizes
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function parseStco(data) {
|
|
302
|
+
let n = r32(data, 4), o = new Array(n)
|
|
303
|
+
for (let i = 0; i < n; i++) o[i] = r32(data, 8 + i * 4)
|
|
304
|
+
return o
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function parseCo64(data) {
|
|
308
|
+
let n = r32(data, 4), o = new Array(n)
|
|
309
|
+
for (let i = 0; i < n; i++) o[i] = r32(data, 8 + i * 8 + 4)
|
|
310
|
+
return o
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function parseStsc(data) {
|
|
314
|
+
let n = r32(data, 4), e = new Array(n)
|
|
315
|
+
for (let i = 0; i < n; i++) e[i] = { first: r32(data, 8 + i * 12), spc: r32(data, 12 + i * 12) }
|
|
316
|
+
return e
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function extractFrames(buf, stsz, stco, stsc) {
|
|
320
|
+
let frames = [], si = 0
|
|
321
|
+
for (let ci = 0; ci < stco.length; ci++) {
|
|
322
|
+
let spc = 1
|
|
323
|
+
if (stsc?.length) {
|
|
324
|
+
let cn = ci + 1
|
|
325
|
+
for (let j = stsc.length - 1; j >= 0; j--)
|
|
326
|
+
if (cn >= stsc[j].first) { spc = stsc[j].spc; break }
|
|
327
|
+
}
|
|
328
|
+
let off = stco[ci]
|
|
329
|
+
for (let s = 0; s < spc && si < stsz.length; s++) {
|
|
330
|
+
let sz = stsz[si++]
|
|
331
|
+
if (off + sz <= buf.length) frames.push(buf.subarray(off, off + sz))
|
|
332
|
+
off += sz
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return frames
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function scanMdat(buf, off, len) {
|
|
339
|
+
let frames = [], end = off + len, pos = off
|
|
340
|
+
while (pos < end - 7) {
|
|
341
|
+
if (buf[pos] === 0xFF && (buf[pos + 1] & 0xF6) === 0xF0) {
|
|
342
|
+
let flen = ((buf[pos + 3] & 0x03) << 11) | (buf[pos + 4] << 3) | (buf[pos + 5] >> 5)
|
|
343
|
+
if (flen > 0 && pos + flen <= end) {
|
|
344
|
+
frames.push(buf.subarray(pos, pos + flen))
|
|
345
|
+
pos += flen
|
|
346
|
+
continue
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
pos++
|
|
350
|
+
}
|
|
351
|
+
return frames
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function r32(buf, off) {
|
|
355
|
+
return (buf[off] << 24 | buf[off + 1] << 16 | buf[off + 2] << 8 | buf[off + 3]) >>> 0
|
|
356
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/decode-aac",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Decode AAC/M4A audio via FAAD2 WASM",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "decode-aac.js",
|
|
7
|
+
"types": "decode-aac.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./decode-aac.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "bash build.sh",
|
|
17
|
+
"test": "node test.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"decode-aac.js",
|
|
21
|
+
"decode-aac.d.ts",
|
|
22
|
+
"src/aac.wasm.cjs",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"aac",
|
|
27
|
+
"m4a",
|
|
28
|
+
"mp4",
|
|
29
|
+
"audio",
|
|
30
|
+
"decode",
|
|
31
|
+
"decoder",
|
|
32
|
+
"wasm",
|
|
33
|
+
"faad2"
|
|
34
|
+
],
|
|
35
|
+
"license": "GPL-2.0",
|
|
36
|
+
"author": "audiojs",
|
|
37
|
+
"homepage": "https://github.com/audiojs/decode-aac#readme",
|
|
38
|
+
"bugs": "https://github.com/audiojs/decode-aac/issues",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/audiojs/decode-aac.git"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=16"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/aac.wasm.cjs
ADDED
|
Binary file
|