@audio/decode-caf 1.1.0 → 1.1.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # decode-caf
1
+ # @audio/decode-caf
2
2
 
3
3
  Decode Core Audio Format (CAF) audio to PCM float samples.
4
4
 
@@ -7,13 +7,13 @@ Part of [audio-decode](https://github.com/audiojs/audio-decode).
7
7
  ## Install
8
8
 
9
9
  ```
10
- npm i @audio/caf-decode
10
+ npm i @audio/decode-caf
11
11
  ```
12
12
 
13
13
  ## Usage
14
14
 
15
15
  ```js
16
- import decode from '@audio/caf-decode'
16
+ import decode from '@audio/decode-caf'
17
17
 
18
18
  let { channelData, sampleRate } = await decode(cafBuffer)
19
19
  ```
@@ -21,7 +21,7 @@ let { channelData, sampleRate } = await decode(cafBuffer)
21
21
  ### Streaming
22
22
 
23
23
  ```js
24
- import { decoder } from '@audio/caf-decode'
24
+ import { decoder } from '@audio/decode-caf'
25
25
 
26
26
  let dec = await decoder()
27
27
  let result = dec.decode(chunk)
package/decode-caf.js CHANGED
@@ -23,7 +23,7 @@ export default async function decode(src) {
23
23
  * @returns {Promise<{decode(chunk: Uint8Array): {channelData, sampleRate}, flush(), free()}>}
24
24
  */
25
25
  export async function decoder() {
26
- let hdr = null, left = null, freed = false
26
+ let hdr = null, left = null, freed = false, dataLeft = Infinity
27
27
  return {
28
28
  decode(data) {
29
29
  if (freed) throw Error('Decoder already freed')
@@ -33,12 +33,17 @@ export async function decoder() {
33
33
  if (!hdr) {
34
34
  hdr = scanCafHdr(chunk)
35
35
  if (!hdr) { left = chunk.slice(); return EMPTY }
36
+ dataLeft = hdr.dataSize
36
37
  chunk = chunk.subarray(hdr.dataStart)
37
38
  }
39
+ if (dataLeft <= 0) return EMPTY // past the data chunk — ignore trailing chunks
38
40
  let fb = hdr.frameBytes
39
- let complete = Math.floor(chunk.length / fb) * fb
40
- if (!complete) { if (chunk.length) left = chunk.slice(); return EMPTY }
41
- if (chunk.length > complete) left = chunk.subarray(complete).slice()
41
+ let avail = Math.min(chunk.length, dataLeft) // don't read past the declared data size
42
+ let complete = Math.floor(avail / fb) * fb
43
+ if (!complete) { if (chunk.length && dataLeft > chunk.length) left = chunk.slice(); return EMPTY }
44
+ dataLeft -= complete
45
+ let rest = chunk.subarray(complete)
46
+ if (rest.length && dataLeft > 0) left = rest.subarray(0, Math.min(rest.length, dataLeft)).slice()
42
47
  return decodeCafRaw(chunk.subarray(0, complete), hdr)
43
48
  },
44
49
  flush() { left = null; return EMPTY },
@@ -78,13 +83,15 @@ function scanCafHdr(buf) {
78
83
  if (!desc) return null
79
84
  let dataStart = off + 4 // skip editCount
80
85
  if (dataStart > buf.length) return null
86
+ // -1 (0xFFFF…) size means "until EOF" — read to end; else payload minus 4-byte editCount
87
+ let dataSize = (sizeHi === 0xFFFFFFFF && sizeLo === 0xFFFFFFFF) ? Infinity : Math.max(0, size - 4)
81
88
  let { formatID, formatFlags, channelsPerFrame: ch, bitsPerChannel: bits } = desc
82
89
  let bytesPerSample = bits >> 3
83
90
  let frameBytes
84
91
  if (formatID === 'alaw' || formatID === 'ulaw') frameBytes = ch
85
92
  else frameBytes = ch * bytesPerSample
86
93
  if (!frameBytes) return null
87
- return { ...desc, dataStart, frameBytes }
94
+ return { ...desc, dataStart, frameBytes, dataSize }
88
95
  }
89
96
  if (size < 0) break
90
97
  if (sizeHi === 0xFFFFFFFF && sizeLo === 0xFFFFFFFF) break
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audio/decode-caf",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Decode CAF (Core Audio Format) audio to PCM samples",
5
5
  "type": "module",
6
6
  "main": "decode-caf.js",