@audio/decode-aiff 1.2.3 → 1.3.1
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/README.md +16 -23
- package/decode-aiff.d.ts +6 -6
- package/decode-aiff.js +30 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# @audio/decode-aiff
|
|
2
2
|
|
|
3
|
-
Decode AIFF and AIFF-C audio to PCM float samples
|
|
4
|
-
Part of [decode](https://github.com/audiojs/decode).
|
|
3
|
+
Decode AIFF and AIFF-C audio to PCM float samples.
|
|
5
4
|
|
|
6
5
|
## Install
|
|
7
6
|
|
|
@@ -12,42 +11,36 @@ npm i @audio/decode-aiff
|
|
|
12
11
|
## Usage
|
|
13
12
|
|
|
14
13
|
```js
|
|
15
|
-
import decode from '@audio/decode-aiff'
|
|
14
|
+
import decode, { decoder } from '@audio/decode-aiff'
|
|
16
15
|
|
|
17
|
-
let { channelData, sampleRate } =
|
|
18
|
-
// channelData: Float32Array[] (one per channel)
|
|
19
|
-
// sampleRate: number
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Streaming
|
|
16
|
+
let { channelData, sampleRate } = decode(aiffBytes)
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
import { decoder } from '@audio/decode-aiff'
|
|
26
|
-
|
|
27
|
-
let dec = await decoder()
|
|
18
|
+
let dec = decoder()
|
|
28
19
|
let result = dec.decode(chunk)
|
|
29
20
|
dec.free()
|
|
30
21
|
```
|
|
31
22
|
|
|
23
|
+
`decode()` and `decoder()` are synchronous.
|
|
24
|
+
|
|
32
25
|
## API
|
|
33
26
|
|
|
34
|
-
### `decode(src):
|
|
27
|
+
### `decode(src): AudioData`
|
|
35
28
|
|
|
36
|
-
|
|
29
|
+
Decode a complete `Uint8Array` or `ArrayBuffer`.
|
|
37
30
|
|
|
38
|
-
### `decoder():
|
|
31
|
+
### `decoder(): AIFFDecoder`
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
Create a decoder instance.
|
|
41
34
|
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
35
|
+
- `dec.decode(data)`: decode a chunk.
|
|
36
|
+
- `dec.flush()`: decode buffered `ima4` or `GSM` data; otherwise return an empty result.
|
|
37
|
+
- `dec.free()`: release resources.
|
|
45
38
|
|
|
46
39
|
## Formats
|
|
47
40
|
|
|
48
|
-
- AIFF
|
|
49
|
-
- AIFF-C
|
|
41
|
+
- AIFF: 8, 16, 24, and 32-bit signed big-endian PCM.
|
|
42
|
+
- AIFF-C: `NONE`/`twos`, `sowt`, `fl32`, `fl64`, `alaw`, `ulaw`, `ima4`, and `GSM`.
|
|
50
43
|
|
|
51
44
|
## License
|
|
52
45
|
|
|
53
|
-
|
|
46
|
+
[ॐ](https://github.com/krishnized/license/) · [MIT](./LICENSE)
|
package/decode-aiff.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
interface AudioData {
|
|
1
|
+
export interface AudioData {
|
|
2
2
|
channelData: Float32Array[];
|
|
3
3
|
sampleRate: number;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
interface AIFFDecoder {
|
|
7
|
-
decode(data: Uint8Array): AudioData;
|
|
7
|
+
decode(data: Uint8Array | ArrayBuffer): AudioData;
|
|
8
8
|
flush(): AudioData;
|
|
9
9
|
free(): void;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
/** Decode AIFF
|
|
13
|
-
export default function decode(src: ArrayBuffer | Uint8Array):
|
|
12
|
+
/** Decode a complete AIFF or AIFF-C file synchronously. */
|
|
13
|
+
export default function decode(src: ArrayBuffer | Uint8Array): AudioData;
|
|
14
14
|
|
|
15
|
-
/** Create decoder
|
|
16
|
-
export function decoder():
|
|
15
|
+
/** Create a synchronous decoder. */
|
|
16
|
+
export function decoder(): AIFFDecoder;
|
package/decode-aiff.js
CHANGED
|
@@ -292,8 +292,12 @@ function asr(x, n) {
|
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
function decodeGSM(b, ssndOff, ssndSize, nCh, nFrames, sr) {
|
|
295
|
-
let
|
|
296
|
-
|
|
295
|
+
let blocks = Math.floor(Math.min(ssndSize, b.length - ssndOff) / 33)
|
|
296
|
+
// COMM counts samples (libsndfile, so Audacity), or blocks as Apple counts ima4
|
|
297
|
+
let len = nFrames > blocks ? Math.min(nFrames, blocks * 160) : nFrames * 160
|
|
298
|
+
let totalFrames = Math.ceil(len / 160)
|
|
299
|
+
// the last block's padding past len falls off the array (typed arrays drop out-of-range writes)
|
|
300
|
+
let channelData = [new Float32Array(len)]
|
|
297
301
|
let out = channelData[0], p = ssndOff
|
|
298
302
|
|
|
299
303
|
// Decoder state (mirrors struct gsm_state)
|
|
@@ -372,9 +376,9 @@ function decodeGSM(b, ssndOff, ssndSize, nCh, nFrames, sr) {
|
|
|
372
376
|
return { channelData, sampleRate: sr }
|
|
373
377
|
}
|
|
374
378
|
|
|
375
|
-
// GSM 6.10 bit unpacking: 33 bytes
|
|
379
|
+
// GSM 6.10 bit unpacking: 33 bytes = 0xD signature nibble + 260 bits of LARc[8] and 4 subframes
|
|
376
380
|
function gsmBits(buf, off) {
|
|
377
|
-
let bc =
|
|
381
|
+
let bc = 4
|
|
378
382
|
function r(n) {
|
|
379
383
|
let val = 0
|
|
380
384
|
for (let i = 0; i < n; i++) {
|
|
@@ -441,7 +445,7 @@ function gsmRpeDecode(xmaxc, Mc, xMc, erp) {
|
|
|
441
445
|
// 4.2.16: APCM inverse quantization
|
|
442
446
|
let fac = GSM_FAC[mant]
|
|
443
447
|
let shift = 6 - exp
|
|
444
|
-
let round = shift >
|
|
448
|
+
let round = shift > 0 ? 1 << (shift - 1) : 0 // gsm_asl(1, shift-1)
|
|
445
449
|
|
|
446
450
|
let xMp = new Int32Array(13)
|
|
447
451
|
for (let i = 0; i < 13; i++) {
|
|
@@ -456,14 +460,10 @@ function gsmRpeDecode(xmaxc, Mc, xMc, erp) {
|
|
|
456
460
|
for (let i = 0; i < 13; i++) erp[Mc + 3 * i] = xMp[i]
|
|
457
461
|
}
|
|
458
462
|
|
|
459
|
-
/**
|
|
460
|
-
|
|
461
|
-
* @param {Uint8Array|ArrayBuffer} src
|
|
462
|
-
* @returns {Promise<{channelData: Float32Array[], sampleRate: number}>}
|
|
463
|
-
*/
|
|
464
|
-
export default async function decode(src) {
|
|
463
|
+
/** Decode a complete AIFF file synchronously. */
|
|
464
|
+
export default function decode(src) {
|
|
465
465
|
let buf = src instanceof Uint8Array ? src : src instanceof ArrayBuffer ? new Uint8Array(src) : src
|
|
466
|
-
let dec =
|
|
466
|
+
let dec = decoder()
|
|
467
467
|
try {
|
|
468
468
|
let result = dec.decode(buf)
|
|
469
469
|
if (!result.channelData.length) result = dec.flush()
|
|
@@ -473,27 +473,26 @@ export default async function decode(src) {
|
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
-
/**
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
*/
|
|
480
|
-
export async function decoder() {
|
|
481
|
-
let hdr = null, left = null, freed = false
|
|
476
|
+
/** Create a synchronous decoder. */
|
|
477
|
+
export function decoder() {
|
|
478
|
+
let hdr = null, left = null, deferredChunks = null, deferredLength = 0, freed = false
|
|
482
479
|
return {
|
|
483
480
|
decode(data) {
|
|
484
481
|
if (freed) throw Error('Decoder already freed')
|
|
485
|
-
if (!data
|
|
482
|
+
if (!data || !data.byteLength) return EMPTY
|
|
486
483
|
let chunk = data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
487
484
|
if (left) { chunk = cat(left, chunk); left = null }
|
|
488
485
|
if (!hdr) {
|
|
489
486
|
hdr = scanAiffHdr(chunk)
|
|
490
487
|
if (!hdr) { left = chunk.slice(); return EMPTY }
|
|
491
|
-
|
|
492
|
-
if (
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
488
|
+
deferredChunks = hdr.comp === 'ima4' || hdr.comp === 'GSM ' || hdr.comp === 'gsm ' ? [] : null
|
|
489
|
+
if (!deferredChunks) chunk = chunk.subarray(hdr.dataStart)
|
|
490
|
+
}
|
|
491
|
+
// IMA4 and GSM need the complete container.
|
|
492
|
+
if (deferredChunks) {
|
|
493
|
+
deferredChunks.push(new Uint8Array(chunk))
|
|
494
|
+
deferredLength += chunk.length
|
|
495
|
+
return EMPTY
|
|
497
496
|
}
|
|
498
497
|
let fb = hdr.frameBytes
|
|
499
498
|
let complete = Math.floor(chunk.length / fb) * fb
|
|
@@ -502,15 +501,16 @@ export async function decoder() {
|
|
|
502
501
|
return decodeAiffRaw(chunk.subarray(0, complete), hdr)
|
|
503
502
|
},
|
|
504
503
|
flush() {
|
|
505
|
-
if (
|
|
506
|
-
let
|
|
507
|
-
|
|
508
|
-
|
|
504
|
+
if (deferredChunks && deferredLength) {
|
|
505
|
+
let input = new Uint8Array(deferredLength), offset = 0
|
|
506
|
+
for (let chunk of deferredChunks) { input.set(chunk, offset); offset += chunk.length }
|
|
507
|
+
deferredChunks = []; deferredLength = 0
|
|
508
|
+
return parseAiff(input)
|
|
509
509
|
}
|
|
510
510
|
left = null
|
|
511
511
|
return EMPTY
|
|
512
512
|
},
|
|
513
|
-
free() { freed = true; left = null; hdr = null },
|
|
513
|
+
free() { freed = true; left = null; hdr = null; deferredChunks = null; deferredLength = 0 },
|
|
514
514
|
}
|
|
515
515
|
}
|
|
516
516
|
|