@openclaw/whatsapp 2026.5.28 → 2026.5.31-beta.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.
Files changed (157) hide show
  1. package/dist/{access-control-Z0fYaWrx.js → access-control-C53zKYSN.js} +1 -1
  2. package/dist/{accounts-BMGM1RtF.js → accounts-DgViSyJx.js} +1 -0
  3. package/dist/{action-runtime-BdhkGtaP.js → action-runtime-Cyp5GNIT.js} +2 -2
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/action-runtime.runtime.js +1 -1
  6. package/dist/api.js +9 -9
  7. package/dist/{approval-handler.runtime-C25wPeBf.js → approval-handler.runtime-BVmOu6x1.js} +1 -2
  8. package/dist/{auth-store-BrKb0mwT.js → auth-store-CZ22aNcV.js} +4 -2
  9. package/dist/{channel-D3y4A5Dd.js → channel-DA2BAIo5.js} +17 -64
  10. package/dist/channel-config-api.js +1 -1
  11. package/dist/channel-plugin-api.js +1 -1
  12. package/dist/{channel-react-action-Cd2qkLqp.js → channel-react-action-zvbaCnGe.js} +3 -3
  13. package/dist/{channel.runtime-C228XUjs.js → channel.runtime-Q1LZDB5s.js} +4 -4
  14. package/dist/{channel.setup-BJQyTUUP.js → channel.setup-DHXOo4h5.js} +2 -3
  15. package/dist/{config-schema-CsNDlDpL.js → config-schema-CROZuhT-.js} +16 -0
  16. package/dist/{connection-controller-mpPGmqGq.js → connection-controller-Bnm4INld.js} +2 -2
  17. package/dist/contract-api.js +1 -1
  18. package/dist/light-runtime-api.js +1 -1
  19. package/dist/{login-CE4UYnyO.js → login-2fuBM7Je.js} +4 -4
  20. package/dist/{login-qr-LBvhEes5.js → login-qr-B1o7GFy8.js} +10 -6
  21. package/dist/login-qr-runtime.js +1 -1
  22. package/dist/{monitor-Ccph7Y8M.js → monitor-BVRq04Dt.js} +36 -18
  23. package/dist/runtime-api.js +7 -7
  24. package/dist/{send-C4LG-Cl6.js → send-DSlVXKL_.js} +53 -41
  25. package/dist/{send-api-C66vkRl9.js → send-api-Bjn-h80j.js} +3 -2
  26. package/dist/{session-D8UW2Vbn.js → session-DyGWNClj.js} +1 -1
  27. package/dist/{setup-core-DpfT4K-2.js → setup-core-OvPMaAsx.js} +4 -4
  28. package/dist/{setup-finalize-CFnxX7la.js → setup-finalize-Dk23pfKc.js} +3 -3
  29. package/dist/setup-plugin-api.js +1 -1
  30. package/dist/{setup-surface-DRsmp0ZS.js → setup-surface-F-jVrH8u.js} +3 -3
  31. package/node_modules/@audio/decode-aac/LICENSE +9 -0
  32. package/node_modules/@audio/decode-aac/README.md +60 -0
  33. package/node_modules/@audio/decode-aac/decode-aac.d.ts +16 -0
  34. package/node_modules/@audio/decode-aac/decode-aac.js +391 -0
  35. package/node_modules/@audio/decode-aac/package.json +47 -0
  36. package/node_modules/@audio/decode-aac/src/aac.wasm.cjs +0 -0
  37. package/node_modules/@audio/decode-aiff/LICENSE +21 -0
  38. package/node_modules/@audio/decode-aiff/README.md +53 -0
  39. package/node_modules/@audio/decode-aiff/decode-aiff.d.ts +16 -0
  40. package/node_modules/@audio/decode-aiff/decode-aiff.js +583 -0
  41. package/node_modules/@audio/decode-aiff/package.json +42 -0
  42. package/node_modules/@audio/decode-amr/LICENSE +191 -0
  43. package/node_modules/@audio/decode-amr/README.md +65 -0
  44. package/node_modules/@audio/decode-amr/decode-amr.d.ts +16 -0
  45. package/node_modules/@audio/decode-amr/decode-amr.js +159 -0
  46. package/node_modules/@audio/decode-amr/package.json +48 -0
  47. package/node_modules/@audio/decode-amr/src/amr.wasm.cjs +0 -0
  48. package/node_modules/@audio/decode-caf/LICENSE +21 -0
  49. package/node_modules/@audio/decode-caf/README.md +55 -0
  50. package/node_modules/@audio/decode-caf/decode-caf.d.ts +16 -0
  51. package/node_modules/@audio/decode-caf/decode-caf.js +190 -0
  52. package/node_modules/@audio/decode-caf/package.json +43 -0
  53. package/node_modules/{audio-buffer → @audio/decode-flac}/LICENSE +5 -2
  54. package/node_modules/@audio/decode-flac/README.md +23 -0
  55. package/node_modules/@audio/decode-flac/decode-flac.d.ts +16 -0
  56. package/node_modules/@audio/decode-flac/decode-flac.js +2994 -0
  57. package/node_modules/@audio/decode-flac/meta.js +115 -0
  58. package/node_modules/@audio/decode-flac/package.json +49 -0
  59. package/node_modules/@audio/decode-mp3/LICENSE +25 -0
  60. package/node_modules/@audio/decode-mp3/README.md +23 -0
  61. package/node_modules/@audio/decode-mp3/decode-mp3.d.ts +16 -0
  62. package/node_modules/@audio/decode-mp3/decode-mp3.js +868 -0
  63. package/node_modules/@audio/decode-mp3/meta.js +143 -0
  64. package/node_modules/@audio/decode-mp3/package.json +50 -0
  65. package/node_modules/@audio/decode-opus/LICENSE +25 -0
  66. package/node_modules/@audio/decode-opus/README.md +23 -0
  67. package/node_modules/@audio/decode-opus/decode-opus.d.ts +16 -0
  68. package/node_modules/@audio/decode-opus/decode-opus.js +3179 -0
  69. package/node_modules/@audio/decode-opus/package.json +47 -0
  70. package/node_modules/@audio/decode-qoa/LICENSE +25 -0
  71. package/node_modules/@audio/decode-qoa/README.md +21 -0
  72. package/node_modules/@audio/decode-qoa/decode-qoa.d.ts +16 -0
  73. package/node_modules/@audio/decode-qoa/decode-qoa.js +278 -0
  74. package/node_modules/@audio/decode-qoa/package.json +46 -0
  75. package/node_modules/@audio/decode-vorbis/LICENSE +25 -0
  76. package/node_modules/@audio/decode-vorbis/README.md +23 -0
  77. package/node_modules/@audio/decode-vorbis/decode-vorbis.d.ts +16 -0
  78. package/node_modules/@audio/decode-vorbis/decode-vorbis.js +2984 -0
  79. package/node_modules/@audio/decode-vorbis/package.json +47 -0
  80. package/node_modules/@audio/decode-wav/decode-wav.js +104 -0
  81. package/node_modules/@audio/decode-wav/meta.js +114 -0
  82. package/node_modules/@audio/decode-wav/package.json +27 -0
  83. package/node_modules/@audio/decode-webm/LICENSE +21 -0
  84. package/node_modules/@audio/decode-webm/README.md +57 -0
  85. package/node_modules/@audio/decode-webm/decode-webm.d.ts +16 -0
  86. package/node_modules/@audio/decode-webm/decode-webm.js +3964 -0
  87. package/node_modules/@audio/decode-webm/package.json +51 -0
  88. package/node_modules/@audio/decode-wma/LICENSE +12 -0
  89. package/node_modules/@audio/decode-wma/README.md +76 -0
  90. package/node_modules/@audio/decode-wma/decode-wma.d.ts +33 -0
  91. package/node_modules/@audio/decode-wma/decode-wma.js +525 -0
  92. package/node_modules/@audio/decode-wma/package.json +47 -0
  93. package/node_modules/@audio/decode-wma/src/wma.wasm.cjs +0 -0
  94. package/node_modules/audio-decode/.claude/settings.json +204 -0
  95. package/node_modules/audio-decode/.github/workflows/test.js.yml +11 -20
  96. package/node_modules/audio-decode/.gitmodules +9 -0
  97. package/node_modules/audio-decode/audio-decode.d.ts +48 -10
  98. package/node_modules/audio-decode/audio-decode.js +193 -77
  99. package/node_modules/audio-decode/meta.js +11 -0
  100. package/node_modules/audio-decode/package.json +49 -21
  101. package/node_modules/audio-decode/readme.md +129 -29
  102. package/node_modules/audio-decode/stream.d.ts +15 -0
  103. package/node_modules/audio-decode/stream.js +1 -0
  104. package/node_modules/audio-decode/test.html +29 -10
  105. package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts +2 -2
  106. package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -1
  107. package/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -1
  108. package/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +1 -1
  109. package/node_modules/lru-cache/dist/commonjs/index.d.ts +2 -2
  110. package/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
  111. package/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
  112. package/node_modules/lru-cache/dist/commonjs/index.min.js.map +1 -1
  113. package/node_modules/lru-cache/dist/commonjs/node/index.d.ts +2 -2
  114. package/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -1
  115. package/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -1
  116. package/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +1 -1
  117. package/node_modules/lru-cache/dist/esm/browser/index.d.ts +2 -2
  118. package/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -1
  119. package/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -1
  120. package/node_modules/lru-cache/dist/esm/browser/index.min.js.map +1 -1
  121. package/node_modules/lru-cache/dist/esm/index.d.ts +2 -2
  122. package/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
  123. package/node_modules/lru-cache/dist/esm/index.js.map +1 -1
  124. package/node_modules/lru-cache/dist/esm/index.min.js.map +1 -1
  125. package/node_modules/lru-cache/dist/esm/node/index.d.ts +2 -2
  126. package/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -1
  127. package/node_modules/lru-cache/dist/esm/node/index.js.map +1 -1
  128. package/node_modules/lru-cache/dist/esm/node/index.min.js.map +1 -1
  129. package/node_modules/lru-cache/package.json +1 -1
  130. package/node_modules/typebox/build/type/script/mapping.d.mts +5 -2
  131. package/node_modules/typebox/build/type/script/mapping.mjs +15 -8
  132. package/node_modules/typebox/build/type/script/parser.d.mts +3 -1
  133. package/node_modules/typebox/build/type/script/parser.mjs +2 -1
  134. package/node_modules/typebox/package.json +29 -29
  135. package/npm-shrinkwrap.json +156 -39
  136. package/openclaw.plugin.json +76 -0
  137. package/package.json +6 -6
  138. package/node_modules/audio-buffer/.eslintrc.json +0 -44
  139. package/node_modules/audio-buffer/.github/workflows/node.js.yml +0 -31
  140. package/node_modules/audio-buffer/.travis.yml +0 -7
  141. package/node_modules/audio-buffer/index.js +0 -76
  142. package/node_modules/audio-buffer/package.json +0 -37
  143. package/node_modules/audio-buffer/readme.md +0 -56
  144. package/node_modules/audio-decode/.eslintrc.json +0 -43
  145. package/node_modules/audio-decode/.travis.yml +0 -13
  146. package/node_modules/audio-decode/tea.yaml +0 -6
  147. package/node_modules/audio-decode/test-case.js +0 -11
  148. package/node_modules/audio-decode/test.js +0 -107
  149. package/node_modules/node-wav/README.md +0 -35
  150. package/node_modules/node-wav/file.wav +0 -0
  151. package/node_modules/node-wav/index.js +0 -291
  152. package/node_modules/node-wav/package.json +0 -29
  153. package/node_modules/node-wav/tests/file1.wav +0 -0
  154. package/node_modules/node-wav/tests/test.js +0 -66
  155. package/node_modules/node-wav/x.js +0 -12
  156. package/node_modules/node-wav/x.json +0 -86702
  157. package/node_modules/node-wav/x.js~ +0 -13
@@ -0,0 +1,583 @@
1
+ /**
2
+ * AIFF/AIFF-C decoder — pure JS
3
+ * Decodes AIFF and AIFF-C audio to Float32Array PCM samples
4
+ *
5
+ * let { channelData, sampleRate } = await decode(aiffbuf)
6
+ */
7
+
8
+ const EMPTY = Object.freeze({ channelData: [], sampleRate: 0 })
9
+
10
+ // A-law expansion table (ITU-T G.711)
11
+ const ALAW_TBL = new Int16Array(256)
12
+ // mu-law expansion table (ITU-T G.711)
13
+ const ULAW_TBL = new Int16Array(256)
14
+
15
+ ;(function buildTables() {
16
+ for (let i = 0; i < 256; i++) {
17
+ // A-law
18
+ let ax = i ^ 0x55, seg = (ax >> 4) & 7, val = ((ax & 0x0F) << 4) + 8
19
+ if (seg) val = (val + 256) << (seg - 1)
20
+ ALAW_TBL[i] = (ax & 0x80) ? val : -val
21
+
22
+ // mu-law
23
+ let ux = ~i & 0xFF
24
+ seg = (ux >> 4) & 7
25
+ val = ((ux & 0x0F) << 3) + 132
26
+ val <<= seg
27
+ ULAW_TBL[i] = (ux & 0x80) ? (val - 132) : -(val - 132)
28
+ }
29
+ })()
30
+
31
+ /**
32
+ * Read 80-bit IEEE 754 extended precision float
33
+ */
34
+ function readF80(b, o) {
35
+ let sign = (b[o] >> 7) & 1
36
+ let exp = ((b[o] & 0x7F) << 8) | b[o + 1]
37
+ let hi = ((b[o + 2] << 24) | (b[o + 3] << 16) | (b[o + 4] << 8) | b[o + 5]) >>> 0
38
+ let lo = ((b[o + 6] << 24) | (b[o + 7] << 16) | (b[o + 8] << 8) | b[o + 9]) >>> 0
39
+ if (exp === 0 && hi === 0 && lo === 0) return 0
40
+ if (exp === 0x7FFF) return sign ? -Infinity : Infinity
41
+ let f = (hi * 4294967296 + lo) / 9223372036854775808 // / 2^63
42
+ return (sign ? -1 : 1) * f * Math.pow(2, exp - 16383)
43
+ }
44
+
45
+ function str4(b, o) {
46
+ return String.fromCharCode(b[o], b[o + 1], b[o + 2], b[o + 3])
47
+ }
48
+
49
+ function r32(b, o) {
50
+ return ((b[o] << 24) | (b[o + 1] << 16) | (b[o + 2] << 8) | b[o + 3]) >>> 0
51
+ }
52
+
53
+ function r16(b, o) {
54
+ return (b[o] << 8) | b[o + 1]
55
+ }
56
+
57
+ /**
58
+ * Parse AIFF/AIFF-C and decode to Float32Array channels
59
+ */
60
+ function parseAiff(buf) {
61
+ if (!buf || buf.length < 12) return EMPTY
62
+
63
+ let b = buf instanceof Uint8Array ? buf : new Uint8Array(buf)
64
+ if (b.length < 12) return EMPTY
65
+
66
+ // Validate FORM header
67
+ if (str4(b, 0) !== 'FORM') throw Error('Not an AIFF file')
68
+ let form = str4(b, 8)
69
+ if (form !== 'AIFF' && form !== 'AIFC') throw Error('Not an AIFF file')
70
+ let isAIFC = form === 'AIFC'
71
+
72
+ let nCh = 0, nFrames = 0, bps = 0, sr = 0, comp = 'NONE'
73
+ let ssndOff = -1, ssndSize = 0
74
+
75
+ // Parse chunks
76
+ let pos = 12, end = Math.min(8 + r32(b, 4), b.length)
77
+ while (pos + 8 <= end) {
78
+ let ckId = str4(b, pos)
79
+ let ckSize = r32(b, pos + 4)
80
+ let ckData = pos + 8
81
+
82
+ if (ckId === 'COMM') {
83
+ if (ckData + 18 > b.length) throw Error('Truncated COMM chunk')
84
+ nCh = r16(b, ckData)
85
+ nFrames = r32(b, ckData + 2)
86
+ bps = r16(b, ckData + 6)
87
+ sr = readF80(b, ckData + 8)
88
+ if (isAIFC && ckSize >= 22 && ckData + 22 <= b.length) {
89
+ comp = str4(b, ckData + 18)
90
+ }
91
+ } else if (ckId === 'SSND') {
92
+ if (ckData + 8 > b.length) throw Error('Truncated SSND chunk')
93
+ let dataOff = r32(b, ckData)
94
+ ssndOff = ckData + 8 + dataOff
95
+ ssndSize = ckSize - 8 - dataOff
96
+ }
97
+
98
+ pos = ckData + ckSize + (ckSize & 1) // pad to even
99
+ }
100
+
101
+ if (!nCh || !nFrames || !sr || ssndOff < 0) return EMPTY
102
+
103
+ // Determine byte depth and decode strategy
104
+ let byteDepth = Math.ceil(bps / 8)
105
+ let frameBytes = byteDepth * nCh
106
+ let actualFrames = Math.min(nFrames, Math.floor(Math.min(ssndSize, b.length - ssndOff) / frameBytes))
107
+ if (actualFrames <= 0) return EMPTY
108
+
109
+ let channelData = Array.from({ length: nCh }, () => new Float32Array(actualFrames))
110
+ let p = ssndOff
111
+
112
+ // Compression-aware decode
113
+ let cUpper = comp.toUpperCase()
114
+ if (cUpper === 'NONE' || cUpper === 'TWOS' || comp === 'twos') {
115
+ // Big-endian signed integer PCM
116
+ decodePCM_BE(b, p, channelData, actualFrames, nCh, bps, byteDepth)
117
+ } else if (comp === 'sowt') {
118
+ // Little-endian signed integer PCM
119
+ decodePCM_LE(b, p, channelData, actualFrames, nCh, bps, byteDepth)
120
+ } else if (comp === 'fl32' || comp === 'FL32') {
121
+ decodeFloat32_BE(b, p, channelData, actualFrames, nCh)
122
+ } else if (comp === 'fl64' || comp === 'FL64') {
123
+ decodeFloat64_BE(b, p, channelData, actualFrames, nCh)
124
+ } else if (comp === 'alaw') {
125
+ decodeLaw(b, p, channelData, actualFrames, nCh, ALAW_TBL)
126
+ } else if (comp === 'ulaw' || comp === 'ULAW') {
127
+ decodeLaw(b, p, channelData, actualFrames, nCh, ULAW_TBL)
128
+ } else if (comp === 'ima4') {
129
+ return decodeIMA4(b, ssndOff, ssndSize, nCh, nFrames, sr)
130
+ } else if (comp === 'GSM ' || comp === 'gsm ') {
131
+ return decodeGSM(b, ssndOff, ssndSize, nCh, nFrames, sr)
132
+ } else {
133
+ throw Error('Unsupported AIFF-C compression: ' + comp)
134
+ }
135
+
136
+ return { channelData, sampleRate: sr }
137
+ }
138
+
139
+ function decodePCM_BE(b, p, channels, frames, nCh, bps, byteDepth) {
140
+ if (bps === 8) {
141
+ // 8-bit: unsigned, center at 128
142
+ for (let i = 0; i < frames; i++)
143
+ for (let c = 0; c < nCh; c++)
144
+ channels[c][i] = (b[p++] - 128) / 128
145
+ } else if (bps === 16) {
146
+ for (let i = 0; i < frames; i++)
147
+ for (let c = 0; c < nCh; c++) {
148
+ let v = (b[p] << 8) | b[p + 1]; p += 2
149
+ channels[c][i] = (v > 32767 ? v - 65536 : v) / 32768
150
+ }
151
+ } else if (bps === 24) {
152
+ for (let i = 0; i < frames; i++)
153
+ for (let c = 0; c < nCh; c++) {
154
+ let v = (b[p] << 16) | (b[p + 1] << 8) | b[p + 2]; p += 3
155
+ channels[c][i] = (v > 8388607 ? v - 16777216 : v) / 8388608
156
+ }
157
+ } else if (bps === 32) {
158
+ for (let i = 0; i < frames; i++)
159
+ for (let c = 0; c < nCh; c++) {
160
+ let v = ((b[p] << 24) | (b[p + 1] << 16) | (b[p + 2] << 8) | b[p + 3]); p += 4
161
+ channels[c][i] = v / 2147483648
162
+ }
163
+ } else {
164
+ throw Error('Unsupported bit depth: ' + bps)
165
+ }
166
+ }
167
+
168
+ function decodePCM_LE(b, p, channels, frames, nCh, bps, byteDepth) {
169
+ if (bps === 8) {
170
+ for (let i = 0; i < frames; i++)
171
+ for (let c = 0; c < nCh; c++)
172
+ channels[c][i] = (b[p++] - 128) / 128
173
+ } else if (bps === 16) {
174
+ for (let i = 0; i < frames; i++)
175
+ for (let c = 0; c < nCh; c++) {
176
+ let v = b[p] | (b[p + 1] << 8); p += 2
177
+ channels[c][i] = (v > 32767 ? v - 65536 : v) / 32768
178
+ }
179
+ } else if (bps === 24) {
180
+ for (let i = 0; i < frames; i++)
181
+ for (let c = 0; c < nCh; c++) {
182
+ let v = b[p] | (b[p + 1] << 8) | (b[p + 2] << 16); p += 3
183
+ channels[c][i] = (v > 8388607 ? v - 16777216 : v) / 8388608
184
+ }
185
+ } else if (bps === 32) {
186
+ for (let i = 0; i < frames; i++)
187
+ for (let c = 0; c < nCh; c++) {
188
+ let v = b[p] | (b[p + 1] << 8) | (b[p + 2] << 16) | (b[p + 3] << 24); p += 4
189
+ channels[c][i] = v / 2147483648
190
+ }
191
+ } else {
192
+ throw Error('Unsupported bit depth: ' + bps)
193
+ }
194
+ }
195
+
196
+ function decodeFloat32_BE(b, p, channels, frames, nCh) {
197
+ let dv = new DataView(b.buffer, b.byteOffset, b.byteLength)
198
+ for (let i = 0; i < frames; i++)
199
+ for (let c = 0; c < nCh; c++) {
200
+ channels[c][i] = dv.getFloat32(p, false); p += 4
201
+ }
202
+ }
203
+
204
+ function decodeFloat64_BE(b, p, channels, frames, nCh) {
205
+ let dv = new DataView(b.buffer, b.byteOffset, b.byteLength)
206
+ for (let i = 0; i < frames; i++)
207
+ for (let c = 0; c < nCh; c++) {
208
+ channels[c][i] = dv.getFloat64(p, false); p += 8
209
+ }
210
+ }
211
+
212
+ function decodeLaw(b, p, channels, frames, nCh, tbl) {
213
+ for (let i = 0; i < frames; i++)
214
+ for (let c = 0; c < nCh; c++)
215
+ channels[c][i] = tbl[b[p++]] / 32768
216
+ }
217
+
218
+ // ===== IMA4 ADPCM (Apple IMA ADPCM) =====
219
+ // 34 bytes/block/channel → 64 samples. COMM nFrames = number of blocks.
220
+
221
+ const IMA_STEP = new Int16Array([7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,173,190,209,230,253,279,307,337,371,408,449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767])
222
+ const IMA_IDX = new Int8Array([-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8])
223
+
224
+ function decodeIMA4(b, ssndOff, ssndSize, nCh, nBlocks, sr) {
225
+ let blockBytes = 34 * nCh
226
+ let totalSamples = nBlocks * 64
227
+ let channelData = Array.from({ length: nCh }, () => new Float32Array(totalSamples))
228
+ let p = ssndOff, sample = 0
229
+
230
+ for (let blk = 0; blk < nBlocks && p + blockBytes <= ssndOff + ssndSize; blk++) {
231
+ for (let c = 0; c < nCh; c++) {
232
+ let bp = p + c * 34
233
+ // Preamble: 16-bit BE — high 9 bits = predictor, low 7 bits = step index
234
+ let preamble = (b[bp] << 8) | b[bp + 1]
235
+ let predictor = preamble & 0xFF80 // top 9 bits, sign-extended via int16
236
+ if (predictor > 32767) predictor -= 65536
237
+ let stepIdx = preamble & 0x7F
238
+ if (stepIdx > 88) stepIdx = 88
239
+
240
+ let out = channelData[c]
241
+ for (let i = 0; i < 32; i++) {
242
+ let byte = b[bp + 2 + i]
243
+ // High nibble first, then low nibble
244
+ for (let nibbleIdx = 0; nibbleIdx < 2; nibbleIdx++) {
245
+ let nibble = nibbleIdx === 0 ? (byte >> 4) & 0xF : byte & 0xF
246
+ let step = IMA_STEP[stepIdx]
247
+ let diff = step >> 3
248
+ if (nibble & 1) diff += step >> 2
249
+ if (nibble & 2) diff += step >> 1
250
+ if (nibble & 4) diff += step
251
+ if (nibble & 8) diff = -diff
252
+ predictor += diff
253
+ if (predictor > 32767) predictor = 32767
254
+ if (predictor < -32768) predictor = -32768
255
+ stepIdx += IMA_IDX[nibble]
256
+ if (stepIdx < 0) stepIdx = 0
257
+ if (stepIdx > 88) stepIdx = 88
258
+ out[sample + i * 2 + nibbleIdx] = predictor / 32768
259
+ }
260
+ }
261
+ }
262
+ p += blockBytes
263
+ sample += 64
264
+ }
265
+
266
+ return { channelData, sampleRate: sr }
267
+ }
268
+
269
+ // ===== GSM 6.10 (Full Rate) =====
270
+ // 33 bytes/frame → 160 samples. RPE-LTP speech codec.
271
+ // Ported from libgsm by Jutta Degener and Carsten Bormann, TU Berlin.
272
+
273
+ // Table 4.3b: Quantization levels of the LTP gain quantizer
274
+ const GSM_QLB = [3277, 11469, 21299, 32767]
275
+ // Table 4.6: Normalized direct mantissa used to compute xM/xmax
276
+ const GSM_FAC = [18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767]
277
+
278
+ // Saturating 16-bit add/sub
279
+ function sadd(a, b) { let s = a + b; return s > 32767 ? 32767 : s < -32768 ? -32768 : s }
280
+ function ssub(a, b) { let s = a - b; return s > 32767 ? 32767 : s < -32768 ? -32768 : s }
281
+ // GSM_MULT_R(a,b): (a*b + 16384) >> 15, with saturation for MIN_WORD*MIN_WORD
282
+ function multr(a, b) {
283
+ if (a === -32768 && b === -32768) return 32767
284
+ return ((a * b + 16384) >> 15) | 0
285
+ }
286
+ // Arithmetic shift right (sign-preserving)
287
+ function asr(x, n) {
288
+ if (n >= 16) return x < 0 ? -1 : 0
289
+ if (n <= -16) return 0
290
+ if (n < 0) return x << -n
291
+ return x >> n // JS >> is always arithmetic
292
+ }
293
+
294
+ function decodeGSM(b, ssndOff, ssndSize, nCh, nFrames, sr) {
295
+ let totalFrames = Math.min(nFrames, Math.floor(ssndSize / 33))
296
+ let channelData = [new Float32Array(totalFrames * 160)]
297
+ let out = channelData[0], p = ssndOff
298
+
299
+ // Decoder state (mirrors struct gsm_state)
300
+ let dp0 = new Int32Array(280) // int32 to avoid overflow in intermediate calcs
301
+ let v = new Int32Array(9)
302
+ let LARpp = [new Int32Array(8), new Int32Array(8)]
303
+ let j = 0, nrp = 40, msr = 0
304
+
305
+ for (let f = 0; f < totalFrames; f++) {
306
+ let { LARc, sub } = gsmBits(b, p)
307
+ let wt = new Int32Array(160)
308
+
309
+ // Process 4 subframes: RPE decode + long-term synthesis
310
+ for (let s = 0; s < 4; s++) {
311
+ let sf = sub[s]
312
+ let erp = new Int32Array(40)
313
+ gsmRpeDecode(sf.xmaxc, sf.Mc, sf.xmc, erp)
314
+
315
+ // Long-term synthesis filtering (4.3.2)
316
+ let Nr = (sf.Nc < 40 || sf.Nc > 120) ? nrp : sf.Nc
317
+ nrp = Nr
318
+ let brp = GSM_QLB[sf.bc]
319
+ // drp is dp0 offset by 120; drp[k] = dp0[120+k], drp[k-Nr] = dp0[120+k-Nr]
320
+ for (let k = 0; k < 40; k++) {
321
+ let drpp = multr(brp, dp0[120 + k - Nr])
322
+ dp0[120 + k] = sadd(erp[k], drpp)
323
+ }
324
+ for (let k = 0; k < 40; k++) wt[s * 40 + k] = dp0[120 + k]
325
+
326
+ // Shift dp0: drp[-120+k] = drp[-80+k] for k=0..119
327
+ for (let k = 0; k < 120; k++) dp0[k] = dp0[k + 40]
328
+ }
329
+
330
+ // Short-term synthesis filter with LARp interpolation (4.2.8-4.2.9)
331
+ let LARpp_j = LARpp[j]
332
+ let LARpp_j_1 = LARpp[j ^ 1]
333
+ j ^= 1 // toggle for next frame
334
+
335
+ gsmDecodeLAR(LARc, LARpp_j)
336
+
337
+ let sr_out = new Int32Array(160)
338
+ let LARp = new Int32Array(8)
339
+
340
+ // Coefficients_0_12: LARp = 3/4 * prev + 1/4 * curr
341
+ for (let i = 0; i < 8; i++)
342
+ LARp[i] = sadd(sadd(LARpp_j_1[i] >> 2, LARpp_j[i] >> 2), LARpp_j_1[i] >> 1)
343
+ gsmLARpToRp(LARp)
344
+ gsmSynthFilter(v, LARp, 13, wt, 0, sr_out, 0)
345
+
346
+ // Coefficients_13_26: LARp = 1/2 * prev + 1/2 * curr
347
+ for (let i = 0; i < 8; i++)
348
+ LARp[i] = sadd(LARpp_j_1[i] >> 1, LARpp_j[i] >> 1)
349
+ gsmLARpToRp(LARp)
350
+ gsmSynthFilter(v, LARp, 14, wt, 13, sr_out, 13)
351
+
352
+ // Coefficients_27_39: LARp = 1/4 * prev + 3/4 * curr
353
+ for (let i = 0; i < 8; i++)
354
+ LARp[i] = sadd(sadd(LARpp_j_1[i] >> 2, LARpp_j[i] >> 2), LARpp_j[i] >> 1)
355
+ gsmLARpToRp(LARp)
356
+ gsmSynthFilter(v, LARp, 13, wt, 27, sr_out, 27)
357
+
358
+ // Coefficients_40_159: LARp = curr
359
+ for (let i = 0; i < 8; i++) LARp[i] = LARpp_j[i]
360
+ gsmLARpToRp(LARp)
361
+ gsmSynthFilter(v, LARp, 120, wt, 40, sr_out, 40)
362
+
363
+ // Postprocessing: de-emphasis + truncation/upscaling
364
+ for (let k = 0; k < 160; k++) {
365
+ msr = sadd(sr_out[k], multr(msr, 28180))
366
+ let s = sadd(msr, msr) & 0xFFF8
367
+ out[f * 160 + k] = (s > 32767 ? s - 65536 : s) / 32768
368
+ }
369
+ p += 33
370
+ }
371
+
372
+ return { channelData, sampleRate: sr }
373
+ }
374
+
375
+ // GSM 6.10 bit unpacking: 33 bytes → LARc[8] + 4 subframes
376
+ function gsmBits(buf, off) {
377
+ let bc = 0
378
+ function r(n) {
379
+ let val = 0
380
+ for (let i = 0; i < n; i++) {
381
+ val = (val << 1) | ((buf[off + (bc >> 3)] >> (7 - (bc & 7))) & 1)
382
+ bc++
383
+ }
384
+ return val
385
+ }
386
+ let LARc = [r(6),r(6),r(5),r(5),r(4),r(4),r(3),r(3)]
387
+ let sub = []
388
+ for (let s = 0; s < 4; s++)
389
+ sub.push({ Nc: r(7), bc: r(2), Mc: r(2), xmaxc: r(6), xmc: [r(3),r(3),r(3),r(3),r(3),r(3),r(3),r(3),r(3),r(3),r(3),r(3),r(3)] })
390
+ return { LARc, sub }
391
+ }
392
+
393
+ // 4.2.8: Decoding of the coded Log-Area Ratios
394
+ function gsmDecodeLAR(LARc, LARpp) {
395
+ // B*2, MIC, INVA from tables 4.1 and 4.2
396
+ const B2 = [0, 0, 4096, -5120, 188, -3584, -682, -2288]
397
+ const MIC = [-32, -32, -16, -16, -8, -8, -4, -4]
398
+ const INVA = [13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708]
399
+ for (let i = 0; i < 8; i++) {
400
+ let t = sadd(LARc[i], MIC[i]) << 10
401
+ t = ssub(t, B2[i])
402
+ t = multr(INVA[i], t)
403
+ LARpp[i] = sadd(t, t)
404
+ }
405
+ }
406
+
407
+ // 4.2.9.2: LARp to reflection coefficients (in-place)
408
+ function gsmLARpToRp(LARp) {
409
+ for (let i = 0; i < 8; i++) {
410
+ if (LARp[i] < 0) {
411
+ let t = LARp[i] === -32768 ? 32767 : -LARp[i]
412
+ LARp[i] = -(t < 11059 ? t << 1 : t < 20070 ? t + 11059 : sadd(t >> 2, 26112))
413
+ } else {
414
+ let t = LARp[i]
415
+ LARp[i] = t < 11059 ? t << 1 : t < 20070 ? t + 11059 : sadd(t >> 2, 26112)
416
+ }
417
+ }
418
+ }
419
+
420
+ // Short-term synthesis filter (4.2.10, synthesis direction)
421
+ function gsmSynthFilter(v, rrp, k, wt, wtOff, sr, srOff) {
422
+ for (let n = 0; n < k; n++) {
423
+ let sri = wt[wtOff + n]
424
+ for (let i = 7; i >= 0; i--) {
425
+ sri = ssub(sri, multr(rrp[i], v[i]))
426
+ v[i + 1] = sadd(v[i], multr(rrp[i], sri))
427
+ }
428
+ sr[srOff + n] = v[0] = sri
429
+ }
430
+ }
431
+
432
+ // 4.2.16-4.2.17: RPE decoding (inverse quantization + grid positioning)
433
+ function gsmRpeDecode(xmaxc, Mc, xMc, erp) {
434
+ // 4.2.15: Compute exp and mant from xmaxc
435
+ let exp = 0, mant
436
+ if (xmaxc > 15) exp = (xmaxc >> 3) - 1
437
+ mant = xmaxc - (exp << 3)
438
+ if (mant === 0) { exp = -4; mant = 7 }
439
+ else { while (mant <= 7) { mant = (mant << 1) | 1; exp-- }; mant -= 8 }
440
+
441
+ // 4.2.16: APCM inverse quantization
442
+ let fac = GSM_FAC[mant]
443
+ let shift = 6 - exp
444
+ let round = shift > 1 ? 1 << (shift - 1) : 0 // gsm_asl(1, shift-1)
445
+
446
+ let xMp = new Int32Array(13)
447
+ for (let i = 0; i < 13; i++) {
448
+ let t = ((xMc[i] << 1) - 7) << 12
449
+ t = multr(fac, t)
450
+ t = sadd(t, round)
451
+ xMp[i] = asr(t, shift)
452
+ }
453
+
454
+ // 4.2.17: RPE grid positioning
455
+ for (let k = 0; k < 40; k++) erp[k] = 0
456
+ for (let i = 0; i < 13; i++) erp[Mc + 3 * i] = xMp[i]
457
+ }
458
+
459
+ /**
460
+ * Whole-file decode
461
+ * @param {Uint8Array|ArrayBuffer} src
462
+ * @returns {Promise<{channelData: Float32Array[], sampleRate: number}>}
463
+ */
464
+ export default async function decode(src) {
465
+ let buf = src instanceof Uint8Array ? src : src instanceof ArrayBuffer ? new Uint8Array(src) : src
466
+ let dec = await decoder()
467
+ try {
468
+ let result = dec.decode(buf)
469
+ if (!result.channelData.length) result = dec.flush()
470
+ return result
471
+ } finally {
472
+ dec.free()
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Create decoder instance
478
+ * @returns {Promise<{decode(chunk: Uint8Array): {channelData, sampleRate}, flush(), free()}>}
479
+ */
480
+ export async function decoder() {
481
+ let hdr = null, left = null, freed = false
482
+ return {
483
+ decode(data) {
484
+ if (freed) throw Error('Decoder already freed')
485
+ if (!data?.length) return EMPTY
486
+ let chunk = data instanceof Uint8Array ? data : new Uint8Array(data)
487
+ if (left) { chunk = cat(left, chunk); left = null }
488
+ if (!hdr) {
489
+ hdr = scanAiffHdr(chunk)
490
+ if (!hdr) { left = chunk.slice(); return EMPTY }
491
+ // IMA4/GSM: buffer all SSND data, decode on flush
492
+ if (hdr.comp === 'ima4' || hdr.comp === 'GSM ' || hdr.comp === 'gsm ') {
493
+ left = chunk.slice()
494
+ return EMPTY
495
+ }
496
+ chunk = chunk.subarray(hdr.dataStart)
497
+ }
498
+ let fb = hdr.frameBytes
499
+ let complete = Math.floor(chunk.length / fb) * fb
500
+ if (!complete) { if (chunk.length) left = chunk.slice(); return EMPTY }
501
+ if (chunk.length > complete) left = chunk.subarray(complete).slice()
502
+ return decodeAiffRaw(chunk.subarray(0, complete), hdr)
503
+ },
504
+ flush() {
505
+ if (hdr && left && (hdr.comp === 'ima4' || hdr.comp === 'GSM ' || hdr.comp === 'gsm ')) {
506
+ let result = parseAiff(left)
507
+ left = null
508
+ return result
509
+ }
510
+ left = null
511
+ return EMPTY
512
+ },
513
+ free() { freed = true; left = null; hdr = null },
514
+ }
515
+ }
516
+
517
+ function cat(a, b) {
518
+ let r = new Uint8Array(a.length + b.length)
519
+ r.set(a); r.set(b, a.length)
520
+ return r
521
+ }
522
+
523
+ function scanAiffHdr(b) {
524
+ if (!b || b.length < 12) return null
525
+ if (str4(b, 0) !== 'FORM') throw Error('Not an AIFF file')
526
+ let form = str4(b, 8)
527
+ if (form !== 'AIFF' && form !== 'AIFC') throw Error('Not an AIFF file')
528
+ let isAIFC = form === 'AIFC'
529
+ let nCh = 0, bps = 0, sr = 0, comp = 'NONE', commFound = false
530
+ let pos = 12, end = Math.min(8 + r32(b, 4), b.length)
531
+ while (pos + 8 <= end) {
532
+ let ckId = str4(b, pos), ckSize = r32(b, pos + 4), ckData = pos + 8
533
+ if (ckId === 'COMM') {
534
+ if (ckData + 18 > b.length) return null
535
+ nCh = r16(b, ckData)
536
+ bps = r16(b, ckData + 6)
537
+ sr = readF80(b, ckData + 8)
538
+ if (isAIFC && ckSize >= 22 && ckData + 22 <= b.length) comp = str4(b, ckData + 18)
539
+ commFound = true
540
+ } else if (ckId === 'SSND') {
541
+ if (!commFound) return null
542
+ if (ckData + 8 > b.length) return null
543
+ let dataOff = r32(b, ckData)
544
+ let dataStart = ckData + 8 + dataOff
545
+ let cUpper = comp.toUpperCase()
546
+ let byteDepth = Math.ceil(bps / 8)
547
+ let frameBytes
548
+ if (comp === 'fl32' || comp === 'FL32') frameBytes = nCh * 4
549
+ else if (comp === 'fl64' || comp === 'FL64') frameBytes = nCh * 8
550
+ else if (comp === 'alaw' || comp === 'ulaw' || comp === 'ULAW') frameBytes = nCh
551
+ else if (comp === 'ima4' || comp === 'GSM ' || comp === 'gsm ') frameBytes = 1 // block-based, handled via flush
552
+ else frameBytes = nCh * byteDepth
553
+ return { nCh, bps, sr, comp, byteDepth, frameBytes, dataStart, isAIFC }
554
+ }
555
+ pos = ckData + ckSize + (ckSize & 1)
556
+ }
557
+ return null
558
+ }
559
+
560
+ function decodeAiffRaw(raw, hdr) {
561
+ let { nCh, bps, sr, comp, byteDepth, frameBytes } = hdr
562
+ let frames = Math.floor(raw.length / frameBytes)
563
+ if (!frames) return EMPTY
564
+ let channelData = Array.from({ length: nCh }, () => new Float32Array(frames))
565
+ let cUpper = comp.toUpperCase()
566
+ let p = 0
567
+ if (cUpper === 'NONE' || cUpper === 'TWOS' || comp === 'twos') {
568
+ decodePCM_BE(raw, 0, channelData, frames, nCh, bps, byteDepth)
569
+ } else if (comp === 'sowt') {
570
+ decodePCM_LE(raw, 0, channelData, frames, nCh, bps, byteDepth)
571
+ } else if (comp === 'fl32' || comp === 'FL32') {
572
+ decodeFloat32_BE(raw, 0, channelData, frames, nCh)
573
+ } else if (comp === 'fl64' || comp === 'FL64') {
574
+ decodeFloat64_BE(raw, 0, channelData, frames, nCh)
575
+ } else if (comp === 'alaw') {
576
+ decodeLaw(raw, 0, channelData, frames, nCh, ALAW_TBL)
577
+ } else if (comp === 'ulaw' || comp === 'ULAW') {
578
+ decodeLaw(raw, 0, channelData, frames, nCh, ULAW_TBL)
579
+ } else {
580
+ throw Error('Unsupported AIFF-C compression: ' + comp)
581
+ }
582
+ return { channelData, sampleRate: sr }
583
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@audio/decode-aiff",
3
+ "version": "1.1.1",
4
+ "description": "Decode AIFF/AIFF-C audio to PCM samples",
5
+ "type": "module",
6
+ "main": "decode-aiff.js",
7
+ "types": "decode-aiff.d.ts",
8
+ "exports": {
9
+ ".": "./decode-aiff.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "files": [
13
+ "decode-aiff.js",
14
+ "decode-aiff.d.ts",
15
+ "LICENSE"
16
+ ],
17
+ "keywords": [
18
+ "aiff",
19
+ "aifc",
20
+ "audio",
21
+ "decode",
22
+ "decoder",
23
+ "pcm"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "license": "MIT",
29
+ "author": "audiojs",
30
+ "homepage": "https://github.com/audiojs/decode-aiff#readme",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/audiojs/decode-aiff.git"
34
+ },
35
+ "engines": {
36
+ "node": ">=16"
37
+ },
38
+ "bugs": "https://github.com/audiojs/decode-aiff/issues",
39
+ "scripts": {
40
+ "test": "node test.js"
41
+ }
42
+ }