@modplayjs/stb-vorbis 0.0.0-stage → 0.2.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/dist/vorbis.js ADDED
@@ -0,0 +1,1053 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ // Ported from stb_vorbis.c — decoder core: setup header parsing, packet
3
+ // decode (floors/residue/mapping/coupling/MDCT), frame finishing.
4
+ // Memory-source pull API (stb_vorbis_open_memory + get_frame_float).
5
+ import { NO_CODE, FAST_HUFFMAN_TABLE_SIZE, STB_VORBIS_FAST_HUFFMAN_LENGTH, } from './types.js';
6
+ import { get8, get32, getn, skip, startPage, startPacket, maybeStartPacket, nextSegment, get8Packet, get32Packet, flushPacket, prepHuffman, getBits, error, setFileOffset, getFileOffset, EOP, INVALID_BITS, } from './stream.js';
7
+ import { ilog, float32Unpack, lookup1Values, computeCodewords, computeAcceleratedHuffman, computeSortedHuffman, bitReverse, decodeRawShared, } from './codebook.js';
8
+ import { decodeResidue } from './residue.js';
9
+ import { inverseMdct } from './mdct.js';
10
+ import { computeTwiddleFactors, computeWindow, computeBitReverse, } from './imdct.js';
11
+ import { crc32Init } from './crc32.js';
12
+ import { INVERSE_DB_TABLE } from './tables.js';
13
+ const PAGEFLAG_first_page = 2;
14
+ const PAGEFLAG_last_page = 4;
15
+ const PAGEFLAG_continued_packet = 1;
16
+ export function vorbisValidate(data) {
17
+ return (data[0] === 0x76 && data[1] === 0x6f && data[2] === 0x72 &&
18
+ data[3] === 0x62 && data[4] === 0x69 && data[5] === 0x73);
19
+ }
20
+ /** draw_line (stb_vorbis.c:2043-2091) — LINE_OP(a,b) = a = b (NO_DEFER_FLOOR off). */
21
+ function drawLine(output, x0, y0, x10, y1, n) {
22
+ const dy = y1 - y0;
23
+ const adx = x10 - x0;
24
+ const ady = Math.abs(dy);
25
+ let x = x0, y = y0;
26
+ let err = 0;
27
+ const base = Math.trunc(dy / adx);
28
+ const sy = dy < 0 ? base - 1 : base + 1;
29
+ const ady2 = ady - Math.abs(base) * adx;
30
+ let x1 = x10;
31
+ if (x1 > n)
32
+ x1 = n;
33
+ if (x < x1) {
34
+ // LINE_OP(a,b) = a *= b (stb_vorbis.c:2032, deferred-floor flow):
35
+ // the floor multiplies the decoded residue.
36
+ output[x] = (output[x] ?? 0) * INVERSE_DB_TABLE[y & 255];
37
+ for (++x; x < x1; ++x) {
38
+ err += ady2;
39
+ if (err >= adx) {
40
+ err -= adx;
41
+ y += sy;
42
+ }
43
+ else {
44
+ y += base;
45
+ }
46
+ output[x] = (output[x] ?? 0) * INVERSE_DB_TABLE[y & 255];
47
+ }
48
+ }
49
+ }
50
+ function predictPoint(x, x0, x1, y0, y1) {
51
+ const dy = y1 - y0;
52
+ const adx = x1 - x0;
53
+ const err = Math.abs(dy) * (x - x0);
54
+ let off = 0;
55
+ if (err >= 0)
56
+ off = Math.floor(err / adx);
57
+ else
58
+ off = -Math.floor(-err / adx);
59
+ return dy >= 0 ? y0 + off : y0 - off;
60
+ }
61
+ function neighborsOf(x, n) {
62
+ // C neighbors() (stb_vorbis.c:1958-1969): the low/high LOCALS hold X
63
+ // coordinates; the returned *plow/*phigh are the INDICES of those
64
+ // neighbors.
65
+ let low = -1, lowI = -1;
66
+ let high = 65536, highI = -1;
67
+ for (let i = 0; i < n; ++i) {
68
+ const xi = x[i] ?? 0;
69
+ if (xi > low && xi < (x[n] ?? 0)) {
70
+ low = xi;
71
+ lowI = i;
72
+ }
73
+ if (xi < high && xi > (x[n] ?? 0)) {
74
+ high = xi;
75
+ highI = i;
76
+ }
77
+ }
78
+ return [lowI, highI];
79
+ }
80
+ function computeBlocksize(f, b, n) {
81
+ const n2 = n >> 1, n4 = n >> 2, n8 = n >> 3;
82
+ f.A[b] = new Float32Array(n2);
83
+ f.B[b] = new Float32Array(n2);
84
+ f.C[b] = new Float32Array(n4);
85
+ computeTwiddleFactorsInto(n, f.A[b], f.B[b], f.C[b]);
86
+ f.window[b] = new Float32Array(n2);
87
+ computeWindow(n, f.window[b]);
88
+ f.bitReverse[b] = new Uint16Array(n8);
89
+ computeBitReverse(n, f.bitReverse[b]);
90
+ return true;
91
+ }
92
+ function computeTwiddleFactorsInto(n, A, B, C) {
93
+ computeTwiddleFactors(n, A, B, C);
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // Setup header (start_decoder, stb_vorbis.c:3589-4213)
97
+ // ---------------------------------------------------------------------------
98
+ function startDecoder(f) {
99
+ let maxSubmaps = 0;
100
+ let longestFloorlist = 0;
101
+ f.firstDecode = true;
102
+ f.nextSeg = -1; // no mid-packet start yet
103
+ if (!startPage(f))
104
+ return false;
105
+ if (!(f.pageFlag & PAGEFLAG_first_page))
106
+ return error(f, 4);
107
+ if (f.pageFlag & PAGEFLAG_last_page)
108
+ return error(f, 4);
109
+ if (f.pageFlag & PAGEFLAG_continued_packet)
110
+ return error(f, 4);
111
+ if (f.segmentCount !== 1)
112
+ return error(f, 4);
113
+ if (f.segments[0] !== 30)
114
+ return error(f, 4);
115
+ // id packet
116
+ if (get8(f) !== 1)
117
+ return error(f, 4);
118
+ const header = new Uint8Array(6);
119
+ if (!getn(f, header, 6))
120
+ return error(f, 10);
121
+ if (!vorbisValidate(header))
122
+ return error(f, 4);
123
+ if (get32(f) !== 0)
124
+ return error(f, 4);
125
+ f.channels = get8(f);
126
+ if (!f.channels)
127
+ return error(f, 4);
128
+ if (f.channels > 256)
129
+ return error(f, 31);
130
+ f.sampleRate = get32(f);
131
+ if (!f.sampleRate)
132
+ return error(f, 4);
133
+ get32(f);
134
+ get32(f);
135
+ get32(f); // bitrates
136
+ let x = get8(f);
137
+ {
138
+ const log0 = x & 15;
139
+ const log1 = (x >> 4) & 15;
140
+ f.blocksize0 = 1 << log0;
141
+ f.blocksize1 = 1 << log1;
142
+ if (log0 < 6 || log0 > 13)
143
+ return error(f, 20);
144
+ if (log1 < 6 || log1 > 13)
145
+ return error(f, 20);
146
+ if (log0 > log1)
147
+ return error(f, 20);
148
+ }
149
+ x = get8(f);
150
+ if (!(x & 1))
151
+ return error(f, 4);
152
+ // comment packet
153
+ if (!startPage(f))
154
+ return false;
155
+ if (!startPacket(f))
156
+ return false;
157
+ if (!nextSegment(f))
158
+ return false;
159
+ if (get8Packet(f) !== 3)
160
+ return error(f, 20);
161
+ for (let i = 0; i < 6; ++i)
162
+ header[i] = get8Packet(f);
163
+ if (!vorbisValidate(header))
164
+ return error(f, 20);
165
+ {
166
+ const len = get32Packet(f);
167
+ for (let i = 0; i < len; ++i)
168
+ get8Packet(f); // vendor
169
+ const nComments = get32Packet(f);
170
+ for (let i = 0; i < nComments; ++i) {
171
+ const l = get32Packet(f);
172
+ for (let j = 0; j < l; ++j)
173
+ get8Packet(f);
174
+ }
175
+ x = get8Packet(f);
176
+ if (!(x & 1))
177
+ return error(f, 20);
178
+ }
179
+ skip(f, f.bytesInSeg);
180
+ f.bytesInSeg = 0;
181
+ {
182
+ let len = nextSegment(f);
183
+ while (len !== 0) {
184
+ skip(f, len);
185
+ f.bytesInSeg = 0;
186
+ len = nextSegment(f);
187
+ }
188
+ }
189
+ // setup packet
190
+ if (!startPacket(f))
191
+ return false;
192
+ crc32Init();
193
+ if (get8Packet(f) !== 5)
194
+ return error(f, 20);
195
+ for (let i = 0; i < 6; ++i)
196
+ header[i] = get8Packet(f);
197
+ if (!vorbisValidate(header))
198
+ return error(f, 20);
199
+ // codebooks
200
+ f.codebookCount = getBits(f, 8) + 1;
201
+ f.codebooks = [];
202
+ for (let i = 0; i < f.codebookCount; ++i) {
203
+ let values = null;
204
+ let total = 0;
205
+ const c = {
206
+ dimensions: 0, entries: 0, codewordLengths: null,
207
+ minimumValue: 0, deltaValue: 0, valueBits: 0, lookupType: 0,
208
+ sequenceP: 0, sparse: 0, lookupValues: 0, multiplicands: null,
209
+ codewords: null, fastHuffman: new Int32Array(FAST_HUFFMAN_TABLE_SIZE),
210
+ sortedCodewords: null, sortedValues: null, sortedEntries: 0,
211
+ };
212
+ f.codebooks.push(c);
213
+ let xx = getBits(f, 8);
214
+ if (xx !== 0x42)
215
+ return error(f, 20);
216
+ xx = getBits(f, 8);
217
+ if (xx !== 0x43)
218
+ return error(f, 20);
219
+ xx = getBits(f, 8);
220
+ if (xx !== 0x56)
221
+ return error(f, 20);
222
+ xx = getBits(f, 8);
223
+ c.dimensions = (getBits(f, 8) << 8) + xx;
224
+ xx = getBits(f, 8);
225
+ const y = getBits(f, 8);
226
+ c.entries = (getBits(f, 8) << 16) + (y << 8) + xx;
227
+ const ordered = getBits(f, 1);
228
+ c.sparse = ordered ? 0 : getBits(f, 1);
229
+ if (c.dimensions === 0 && c.entries !== 0)
230
+ return error(f, 20);
231
+ const lengths = new Uint8Array(c.entries);
232
+ if (ordered) {
233
+ let currentEntry = 0;
234
+ let currentLength = getBits(f, 5) + 1;
235
+ while (currentEntry < c.entries) {
236
+ const limit = c.entries - currentEntry;
237
+ const nn = getBits(f, ilog(limit));
238
+ if (currentLength >= 32)
239
+ return error(f, 20);
240
+ if (currentEntry + nn > c.entries)
241
+ return error(f, 20);
242
+ lengths.fill(currentLength, currentEntry, currentEntry + nn);
243
+ currentEntry += nn;
244
+ ++currentLength;
245
+ }
246
+ }
247
+ else {
248
+ for (let j = 0; j < c.entries; ++j) {
249
+ const present = c.sparse ? getBits(f, 1) : 1;
250
+ if (present) {
251
+ lengths[j] = getBits(f, 5) + 1;
252
+ ++total;
253
+ if (lengths[j] === 32)
254
+ return error(f, 20);
255
+ }
256
+ else {
257
+ lengths[j] = NO_CODE;
258
+ }
259
+ }
260
+ }
261
+ if (c.sparse && total >= c.entries >> 2) {
262
+ c.sparse = 0;
263
+ }
264
+ let sortedCount = 0;
265
+ if (c.sparse) {
266
+ sortedCount = total;
267
+ }
268
+ else {
269
+ for (let j = 0; j < c.entries; ++j) {
270
+ if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] !== NO_CODE)
271
+ ++sortedCount;
272
+ }
273
+ }
274
+ c.sortedEntries = sortedCount;
275
+ values = null;
276
+ if (!c.sparse) {
277
+ c.codewordLengths = lengths;
278
+ c.codewords = new Uint32Array(c.entries);
279
+ }
280
+ else {
281
+ if (c.sortedEntries) {
282
+ c.codewordLengths = new Uint8Array(c.sortedEntries);
283
+ c.codewords = new Uint32Array(c.sortedEntries);
284
+ values = new Uint32Array(c.sortedEntries);
285
+ }
286
+ }
287
+ if (!computeCodewords(c, lengths, c.entries, values))
288
+ return error(f, 20);
289
+ if (c.sortedEntries) {
290
+ c.sortedCodewords = new Uint32Array(c.sortedEntries + 1);
291
+ c.sortedValues = new Int32Array(c.sortedEntries + 1);
292
+ computeSortedHuffmanShared(c, lengths, values);
293
+ }
294
+ if (c.sparse) {
295
+ c.codewords = null;
296
+ }
297
+ computeAcceleratedHuffman(c);
298
+ c.lookupType = getBits(f, 4);
299
+ if (c.lookupType > 2)
300
+ return error(f, 20);
301
+ if (c.lookupType > 0) {
302
+ c.minimumValue = float32Unpack(getBits(f, 32));
303
+ c.deltaValue = float32Unpack(getBits(f, 32));
304
+ c.valueBits = getBits(f, 4) + 1;
305
+ c.sequenceP = getBits(f, 1);
306
+ if (c.lookupType === 1) {
307
+ const v = lookup1Values(c.entries, c.dimensions);
308
+ if (v < 0)
309
+ return error(f, 20);
310
+ c.lookupValues = v;
311
+ }
312
+ else {
313
+ c.lookupValues = c.entries * c.dimensions;
314
+ }
315
+ if (c.lookupValues === 0)
316
+ return error(f, 20);
317
+ const mults = new Int32Array(c.lookupValues);
318
+ for (let j = 0; j < c.lookupValues; ++j) {
319
+ const q = getBits(f, c.valueBits);
320
+ if (q === EOP)
321
+ return error(f, 20);
322
+ mults[j] = q;
323
+ }
324
+ if (c.lookupType === 1) {
325
+ // pre-expand lookup1 multiplicands
326
+ const len = c.sparse ? c.sortedEntries : c.entries;
327
+ c.multiplicands = new Float32Array(len * c.dimensions);
328
+ let last = 0;
329
+ for (let j = 0; j < len; ++j) {
330
+ const zz = c.sparse ? c.sortedValues[j] : j;
331
+ let div = 1;
332
+ for (let k = 0; k < c.dimensions; ++k) {
333
+ const off = Math.floor(zz / div) % c.lookupValues;
334
+ const val = mults[off] * c.deltaValue + c.minimumValue + last;
335
+ c.multiplicands[j * c.dimensions + k] = val;
336
+ if (c.sequenceP)
337
+ last = val;
338
+ if (k + 1 < c.dimensions)
339
+ div *= c.lookupValues;
340
+ }
341
+ }
342
+ c.lookupType = 2;
343
+ }
344
+ else {
345
+ let last = 0;
346
+ c.multiplicands = new Float32Array(c.lookupValues);
347
+ for (let j = 0; j < c.lookupValues; ++j) {
348
+ const val = mults[j] * c.deltaValue + c.minimumValue + last;
349
+ c.multiplicands[j] = val;
350
+ if (c.sequenceP)
351
+ last = val;
352
+ }
353
+ }
354
+ }
355
+ }
356
+ // time domain transfers (unused)
357
+ {
358
+ const tCount = getBits(f, 6) + 1;
359
+ for (let i = 0; i < tCount; ++i) {
360
+ if (getBits(f, 16) !== 0)
361
+ return error(f, 20);
362
+ }
363
+ }
364
+ // floors
365
+ f.floorCount = getBits(f, 6) + 1;
366
+ f.floorTypes = new Array(f.floorCount).fill(0);
367
+ f.floor0Config = [];
368
+ f.floor1Config = [];
369
+ for (let i = 0; i < f.floorCount; ++i) {
370
+ const ftype = getBits(f, 16);
371
+ if (ftype > 1)
372
+ return error(f, 20);
373
+ f.floorTypes[i] = ftype;
374
+ if (ftype === 0) {
375
+ return error(f, 26); // floor0 not supported (as stb_vorbis)
376
+ }
377
+ else {
378
+ const g = {
379
+ partitions: 0, partitionClassList: [], classDimensions: [], classSubclasses: [],
380
+ classMasterbooks: [], subclassBooks: [], Xlist: [], sortedOrder: [],
381
+ neighbors: [], floor1Multiplier: 0, rangebits: 0, values: 0,
382
+ };
383
+ f.floor1Config.push(g);
384
+ let maxClass = -1;
385
+ g.partitions = getBits(f, 5);
386
+ for (let j = 0; j < g.partitions; ++j) {
387
+ g.partitionClassList.push(getBits(f, 4));
388
+ if (g.partitionClassList[j] > maxClass)
389
+ maxClass = g.partitionClassList[j];
390
+ }
391
+ for (let j = 0; j <= maxClass; ++j) {
392
+ g.classDimensions[j] = getBits(f, 3) + 1;
393
+ g.classSubclasses[j] = getBits(f, 2);
394
+ if (g.classSubclasses[j]) {
395
+ g.classMasterbooks[j] = getBits(f, 8);
396
+ if ((g.classMasterbooks[j] ?? 0) >= f.codebookCount)
397
+ return error(f, 20);
398
+ }
399
+ for (let k = 0; k < (1 << g.classSubclasses[j]); ++k) {
400
+ g.subclassBooks[j] = g.subclassBooks[j] ?? [];
401
+ g.subclassBooks[j][k] = getBits(f, 8) - 1;
402
+ if ((g.subclassBooks[j][k] ?? 0) >= f.codebookCount)
403
+ return error(f, 20);
404
+ }
405
+ }
406
+ g.floor1Multiplier = getBits(f, 2) + 1;
407
+ g.rangebits = getBits(f, 4);
408
+ g.Xlist[0] = 0;
409
+ g.Xlist[1] = 1 << g.rangebits;
410
+ g.values = 2;
411
+ for (let j = 0; j < g.partitions; ++j) {
412
+ const cl = g.partitionClassList[j];
413
+ for (let k = 0; k < g.classDimensions[cl]; ++k) {
414
+ g.Xlist[g.values] = getBits(f, g.rangebits);
415
+ ++g.values;
416
+ }
417
+ }
418
+ // sort order
419
+ const p = [];
420
+ for (let j = 0; j < g.values; ++j)
421
+ p.push({ x: g.Xlist[j], id: j });
422
+ p.sort((a, b) => a.x - b.x);
423
+ for (let j = 0; j < g.values - 1; ++j) {
424
+ if (p[j].x === p[j + 1].x)
425
+ return error(f, 20);
426
+ }
427
+ for (let j = 0; j < g.values; ++j)
428
+ g.sortedOrder[j] = p[j].id;
429
+ // neighbors
430
+ for (let j = 2; j < g.values; ++j) {
431
+ const [low, high] = neighborsOf(g.Xlist, j);
432
+ g.neighbors[j] = [low, high];
433
+ }
434
+ if (g.values > longestFloorlist)
435
+ longestFloorlist = g.values;
436
+ }
437
+ }
438
+ // residue
439
+ f.residueCount = getBits(f, 6) + 1;
440
+ f.residueTypes = new Array(f.residueCount).fill(0);
441
+ f.residueConfig = [];
442
+ for (let i = 0; i < f.residueCount; ++i) {
443
+ const r = { begin: 0, end: 0, partSize: 0, classifications: 0, classbook: 0, classdata: null, residueBooks: null };
444
+ f.residueConfig.push(r);
445
+ const rtype = getBits(f, 16);
446
+ if (rtype > 2)
447
+ return error(f, 20);
448
+ f.residueTypes[i] = rtype;
449
+ r.begin = getBits(f, 24);
450
+ r.end = getBits(f, 24);
451
+ if (r.end < r.begin)
452
+ return error(f, 20);
453
+ r.partSize = getBits(f, 24) + 1;
454
+ r.classifications = getBits(f, 6) + 1;
455
+ r.classbook = getBits(f, 8);
456
+ if (r.classbook >= f.codebookCount)
457
+ return error(f, 20);
458
+ const residueCascade = new Uint8Array(64);
459
+ for (let j = 0; j < r.classifications; ++j) {
460
+ let highBits = 0;
461
+ const lowBits = getBits(f, 3);
462
+ if (getBits(f, 1))
463
+ highBits = getBits(f, 5);
464
+ residueCascade[j] = highBits * 8 + lowBits;
465
+ }
466
+ r.residueBooks = [];
467
+ for (let j = 0; j < r.classifications; ++j) {
468
+ const books = new Int16Array(8);
469
+ for (let k = 0; k < 8; ++k) {
470
+ if (residueCascade[j] & (1 << k)) {
471
+ books[k] = getBits(f, 8);
472
+ if ((books[k] ?? 0) >= f.codebookCount)
473
+ return error(f, 20);
474
+ }
475
+ else {
476
+ books[k] = -1;
477
+ }
478
+ }
479
+ r.residueBooks.push(books);
480
+ }
481
+ r.classdata = [];
482
+ const cbEntries = f.codebooks[r.classbook].entries;
483
+ const classwords = f.codebooks[r.classbook].dimensions;
484
+ for (let j = 0; j < cbEntries; ++j) {
485
+ const cd = new Uint8Array(classwords);
486
+ let temp = j;
487
+ for (let k = classwords - 1; k >= 0; --k) {
488
+ cd[k] = temp % r.classifications;
489
+ temp = Math.floor(temp / r.classifications);
490
+ }
491
+ r.classdata.push(cd);
492
+ }
493
+ }
494
+ // mapping
495
+ f.mappingCount = getBits(f, 6) + 1;
496
+ f.mapping = [];
497
+ for (let i = 0; i < f.mappingCount; ++i) {
498
+ const m = { couplingSteps: 0, chan: [], submaps: 0, submapFloor: [], submapResidue: [] };
499
+ f.mapping.push(m);
500
+ const mappingType = getBits(f, 16);
501
+ if (mappingType !== 0)
502
+ return error(f, 20);
503
+ if (getBits(f, 1))
504
+ m.submaps = getBits(f, 4) + 1;
505
+ else
506
+ m.submaps = 1;
507
+ if (m.submaps > maxSubmaps)
508
+ maxSubmaps = m.submaps;
509
+ if (getBits(f, 1)) {
510
+ m.couplingSteps = getBits(f, 8) + 1;
511
+ if (m.couplingSteps > f.channels)
512
+ return error(f, 20);
513
+ for (let k = 0; k < m.couplingSteps; ++k) {
514
+ const magnitude = getBits(f, ilog(f.channels - 1));
515
+ const angle = getBits(f, ilog(f.channels - 1));
516
+ if (magnitude >= f.channels || angle >= f.channels)
517
+ return error(f, 20);
518
+ if (magnitude === angle)
519
+ return error(f, 20);
520
+ m.chan.push({ magnitude, angle, mux: 0 });
521
+ }
522
+ }
523
+ else {
524
+ m.couplingSteps = 0;
525
+ }
526
+ // Allocate one channel entry PER CHANNEL (C: setup_malloc of
527
+ // f->channels entries, stb_vorbis.c:4081); the coupling loop above
528
+ // already wrote magnitude/angle into the first coupling_steps slots.
529
+ while (m.chan.length < f.channels)
530
+ m.chan.push({ magnitude: 0, angle: 0, mux: 0 });
531
+ if (getBits(f, 2))
532
+ return error(f, 20);
533
+ for (let j = 0; j < f.channels; ++j) {
534
+ if (m.submaps > 1) {
535
+ const mux = getBits(f, 4);
536
+ if (mux >= m.submaps)
537
+ return error(f, 20);
538
+ m.chan[j].mux = mux;
539
+ }
540
+ else {
541
+ // @SPECIFICATION: this case is missing from the spec
542
+ m.chan[j].mux = 0;
543
+ }
544
+ }
545
+ for (let j = 0; j < m.submaps; ++j) {
546
+ getBits(f, 8);
547
+ const fl = getBits(f, 8);
548
+ const rs = getBits(f, 8);
549
+ if (fl >= f.floorCount || rs >= f.residueCount)
550
+ return error(f, 20);
551
+ m.submapFloor.push(fl);
552
+ m.submapResidue.push(rs);
553
+ }
554
+ }
555
+ // modes
556
+ f.modeCount = getBits(f, 6) + 1;
557
+ f.modeConfig = [];
558
+ for (let i = 0; i < f.modeCount; ++i) {
559
+ const m = { blockflag: 0, mapping: 0, windowtype: 0, transformtype: 0 };
560
+ f.modeConfig.push(m);
561
+ m.blockflag = getBits(f, 1);
562
+ m.windowtype = getBits(f, 16);
563
+ m.transformtype = getBits(f, 16);
564
+ m.mapping = getBits(f, 8);
565
+ if (m.windowtype !== 0 || m.transformtype !== 0)
566
+ return error(f, 20);
567
+ if (m.mapping >= f.mappingCount)
568
+ return error(f, 20);
569
+ }
570
+ flushPacket(f);
571
+ f.previousLength = 0;
572
+ for (let i = 0; i < f.channels; ++i) {
573
+ f.channelBuffers[i] = new Float32Array(f.blocksize1);
574
+ f.previousWindow[i] = new Float32Array(f.blocksize1 / 2);
575
+ f.finalY[i] = new Int16Array(longestFloorlist);
576
+ }
577
+ computeBlocksize(f, 0, f.blocksize0);
578
+ computeBlocksize(f, 1, f.blocksize1);
579
+ f.blocksize[0] = f.blocksize0;
580
+ f.blocksize[1] = f.blocksize1;
581
+ if (f.nextSeg === -1) {
582
+ f.firstAudioPageOffset = getFileOffset(f);
583
+ }
584
+ else {
585
+ f.firstAudioPageOffset = 0;
586
+ }
587
+ return true;
588
+ }
589
+ function computeSortedHuffmanShared(c, lengths, values) {
590
+ computeSortedHuffman(c, lengths, values);
591
+ }
592
+ // ---------------------------------------------------------------------------
593
+ // Floor decode + draw (deferred-floor variant)
594
+ // ---------------------------------------------------------------------------
595
+ function doFloor(f, map, i, n, target, finalY) {
596
+ const n2 = n >> 1;
597
+ const s = map.chan[i].mux;
598
+ const floor = map.submapFloor[s];
599
+ if (f.floorTypes[floor] === 0) {
600
+ f.error = 11;
601
+ return false;
602
+ }
603
+ const g = f.floor1Config[floor];
604
+ let lx = 0;
605
+ let ly = finalY[0] * g.floor1Multiplier;
606
+ for (let q = 1; q < g.values; ++q) {
607
+ const j = g.sortedOrder[q];
608
+ if (finalY[j] >= 0) {
609
+ const hy = finalY[j] * g.floor1Multiplier;
610
+ const hx = g.Xlist[j];
611
+ if (lx !== hx) {
612
+ drawLine(target, lx, ly, hx, hy, n2);
613
+ }
614
+ lx = hx;
615
+ ly = hy;
616
+ }
617
+ }
618
+ if (lx < n2) {
619
+ for (let j = lx; j < n2; ++j) {
620
+ target[j] = (target[j] ?? 0) * INVERSE_DB_TABLE[ly & 255];
621
+ }
622
+ }
623
+ return true;
624
+ }
625
+ // ---------------------------------------------------------------------------
626
+ // Packet decode (vorbis_decode_initial/rest, stb_vorbis.c:3133-3523)
627
+ // ---------------------------------------------------------------------------
628
+ function vorbisDecodeInitial(f, res) {
629
+ f.channelBufferStart = 0;
630
+ f.channelBufferEnd = 0;
631
+ for (;;) {
632
+ if (f.eof)
633
+ return false;
634
+ if (!maybeStartPacket(f))
635
+ return false;
636
+ if (getBits(f, 1) !== 0) {
637
+ while (get8Packet(f) !== EOP) { /* flush */ }
638
+ continue;
639
+ }
640
+ const i = getBits(f, ilog(f.modeCount - 1));
641
+ if (i === EOP)
642
+ return false;
643
+ if (i >= f.modeCount)
644
+ return false;
645
+ res.mode = i;
646
+ const m = f.modeConfig[i];
647
+ let n, prev, next;
648
+ if (m.blockflag) {
649
+ n = f.blocksize1;
650
+ prev = getBits(f, 1);
651
+ next = getBits(f, 1);
652
+ }
653
+ else {
654
+ prev = next = 0;
655
+ n = f.blocksize0;
656
+ }
657
+ const windowCenter = n >> 1;
658
+ if (m.blockflag && !prev) {
659
+ res.leftStart = (n - f.blocksize0) >> 2;
660
+ res.leftEnd = (n + f.blocksize0) >> 2;
661
+ }
662
+ else {
663
+ res.leftStart = 0;
664
+ res.leftEnd = windowCenter;
665
+ }
666
+ if (m.blockflag && !next) {
667
+ res.rightStart = (n * 3 - f.blocksize0) >> 2;
668
+ res.rightEnd = (n * 3 + f.blocksize0) >> 2;
669
+ }
670
+ else {
671
+ res.rightStart = windowCenter;
672
+ res.rightEnd = n;
673
+ }
674
+ return true;
675
+ }
676
+ }
677
+ function vorbisDecodePacketRest(f, len, m, leftStart0, leftEnd0, rightStart0, rightEnd0, pLeft) {
678
+ void leftEnd0;
679
+ let leftStart = leftStart0;
680
+ const n = f.blocksize[m.blockflag];
681
+ const map = f.mapping[m.mapping];
682
+ const n2 = n >> 1;
683
+ const zeroChannel = new Array(256).fill(0);
684
+ const reallyZeroChannel = new Array(256).fill(0);
685
+ // FLOORS
686
+ for (let i = 0; i < f.channels; ++i) {
687
+ const s = map.chan[i].mux;
688
+ const floor = map.submapFloor[s];
689
+ zeroChannel[i] = 0;
690
+ if (f.floorTypes[floor] === 0) {
691
+ f.error = 11;
692
+ return false;
693
+ }
694
+ const g = f.floor1Config[floor];
695
+ if (getBits(f, 1)) {
696
+ const finalY = f.finalY[i];
697
+ const rangeList = [256, 128, 86, 64];
698
+ const range = rangeList[g.floor1Multiplier - 1];
699
+ let offset = 2;
700
+ finalY[0] = getBits(f, ilog(range) - 1);
701
+ finalY[1] = getBits(f, ilog(range) - 1);
702
+ const step2Flag = new Array(256).fill(0);
703
+ for (let j = 0; j < g.partitions; ++j) {
704
+ const pclass = g.partitionClassList[j];
705
+ const cdim = g.classDimensions[pclass];
706
+ const cbits = g.classSubclasses[pclass];
707
+ const csub = (1 << cbits) - 1;
708
+ let cval = 0;
709
+ if (cbits) {
710
+ const c = f.codebooks[g.classMasterbooks[pclass]];
711
+ cval = decodeShared(f, c);
712
+ }
713
+ for (let k = 0; k < cdim; ++k) {
714
+ const book = g.subclassBooks[pclass][cval & csub];
715
+ cval = cval >> cbits;
716
+ if (book >= 0) {
717
+ const c = f.codebooks[book];
718
+ finalY[offset++] = decodeShared(f, c);
719
+ }
720
+ else {
721
+ finalY[offset++] = 0;
722
+ }
723
+ }
724
+ }
725
+ if (f.validBits === INVALID_BITS) {
726
+ f.error = 11;
727
+ return false;
728
+ }
729
+ step2Flag[0] = step2Flag[1] = 1;
730
+ for (let j = 2; j < g.values; ++j) {
731
+ const low = g.neighbors[j][0];
732
+ const high = g.neighbors[j][1];
733
+ const pred = predictPoint(g.Xlist[j], g.Xlist[low], g.Xlist[high], finalY[low], finalY[high]);
734
+ const val = finalY[j];
735
+ const highroom = range - pred;
736
+ const lowroom = pred;
737
+ let room;
738
+ if (highroom < lowroom)
739
+ room = highroom * 2;
740
+ else
741
+ room = lowroom * 2;
742
+ if (val) {
743
+ step2Flag[low] = step2Flag[high] = 1;
744
+ step2Flag[j] = 1;
745
+ if (val >= room) {
746
+ if (highroom > lowroom)
747
+ finalY[j] = val - lowroom + pred;
748
+ else
749
+ finalY[j] = pred - val + highroom - 1;
750
+ }
751
+ else {
752
+ if (val & 1)
753
+ finalY[j] = pred - ((val + 1) >> 1);
754
+ else
755
+ finalY[j] = pred + (val >> 1);
756
+ }
757
+ }
758
+ else {
759
+ step2Flag[j] = 0;
760
+ finalY[j] = pred;
761
+ }
762
+ }
763
+ // defer floor: mark unused
764
+ for (let j = 0; j < g.values; ++j) {
765
+ if (!step2Flag[j])
766
+ finalY[j] = -1;
767
+ }
768
+ }
769
+ else {
770
+ zeroChannel[i] = 1;
771
+ }
772
+ }
773
+ // re-enable coupled channels
774
+ for (let i = 0; i < f.channels; ++i)
775
+ reallyZeroChannel[i] = zeroChannel[i] ?? 0;
776
+ for (let i = 0; i < map.couplingSteps; ++i) {
777
+ const mag = map.chan[i]?.magnitude ?? 0;
778
+ const ang = map.chan[i]?.angle ?? 0;
779
+ if (!zeroChannel[mag] || !zeroChannel[ang]) {
780
+ zeroChannel[mag] = 0;
781
+ zeroChannel[ang] = 0;
782
+ }
783
+ }
784
+ // RESIDUE
785
+ for (let i = 0; i < map.submaps; ++i) {
786
+ const residueBuffers = [];
787
+ const doNotDecode = [];
788
+ let ch = 0;
789
+ for (let j = 0; j < f.channels; ++j) {
790
+ if (map.chan[j].mux === i) {
791
+ if (zeroChannel[j]) {
792
+ doNotDecode[ch] = 1;
793
+ residueBuffers.push(null);
794
+ }
795
+ else {
796
+ doNotDecode[ch] = 0;
797
+ residueBuffers.push(f.channelBuffers[j]);
798
+ }
799
+ ++ch;
800
+ }
801
+ }
802
+ const r = map.submapResidue[i];
803
+ decodeResidue(f, residueBuffers, ch, n2, r, doNotDecode);
804
+ }
805
+ // INVERSE COUPLING
806
+ for (let i = map.couplingSteps - 1; i >= 0; --i) {
807
+ const mag = f.channelBuffers[map.chan[i]?.magnitude ?? 0];
808
+ const ang = f.channelBuffers[map.chan[i]?.angle ?? 0];
809
+ for (let j = 0; j < n2; ++j) {
810
+ let a2, m2;
811
+ if (mag[j] > 0) {
812
+ if (ang[j] > 0) {
813
+ m2 = mag[j];
814
+ a2 = mag[j] - ang[j];
815
+ }
816
+ else {
817
+ a2 = mag[j];
818
+ m2 = mag[j] + ang[j];
819
+ }
820
+ }
821
+ else {
822
+ if (ang[j] > 0) {
823
+ m2 = mag[j];
824
+ a2 = mag[j] + ang[j];
825
+ }
826
+ else {
827
+ a2 = mag[j];
828
+ m2 = mag[j] - ang[j];
829
+ }
830
+ }
831
+ mag[j] = m2;
832
+ ang[j] = a2;
833
+ }
834
+ }
835
+ // floors
836
+ for (let i = 0; i < f.channels; ++i) {
837
+ if (reallyZeroChannel[i]) {
838
+ f.channelBuffers[i].fill(0, 0, n2);
839
+ }
840
+ else {
841
+ doFloor(f, map, i, n, f.channelBuffers[i], f.finalY[i]);
842
+ }
843
+ }
844
+ // inverse MDCT
845
+ for (let i = 0; i < f.channels; ++i) {
846
+ inverseMdct(f.channelBuffers[i], n, f, m.blockflag);
847
+ }
848
+ flushPacket(f);
849
+ if (f.firstDecode) {
850
+ f.currentLoc = (0 - n2) >>> 0;
851
+ f.discardSamplesDeferred = n - rightEnd0;
852
+ f.currentLocValid = true;
853
+ f.firstDecode = false;
854
+ }
855
+ else if (f.discardSamplesDeferred) {
856
+ if (f.discardSamplesDeferred >= rightStart0 - leftStart) {
857
+ f.discardSamplesDeferred -= rightStart0 - leftStart;
858
+ leftStart = rightStart0;
859
+ pLeft.v = leftStart;
860
+ }
861
+ else {
862
+ leftStart += f.discardSamplesDeferred;
863
+ pLeft.v = leftStart;
864
+ f.discardSamplesDeferred = 0;
865
+ }
866
+ }
867
+ if (f.lastSegWhich === f.endSegWithKnownLoc) {
868
+ if (f.currentLocValid && (f.pageFlag & PAGEFLAG_last_page)) {
869
+ const currentEnd = f.knownLocForPacket;
870
+ if (currentEnd < f.currentLoc + (rightEnd0 - leftStart)) {
871
+ if (currentEnd < f.currentLoc) {
872
+ len.v = 0;
873
+ }
874
+ else {
875
+ len.v = currentEnd - f.currentLoc;
876
+ }
877
+ len.v += leftStart;
878
+ if (len.v > rightEnd0)
879
+ len.v = rightEnd0;
880
+ f.currentLoc += len.v;
881
+ return true;
882
+ }
883
+ }
884
+ f.currentLoc = (f.knownLocForPacket - (n2 - leftStart)) >>> 0;
885
+ f.currentLocValid = true;
886
+ }
887
+ if (f.currentLocValid)
888
+ f.currentLoc = (f.currentLoc + (rightStart0 - leftStart)) >>> 0;
889
+ len.v = rightEnd0;
890
+ return true;
891
+ }
892
+ function decodeShared(f, c) {
893
+ let v = codebookDecodeStartShared(f, c);
894
+ if (c.sparse)
895
+ v = c.sortedValues[v];
896
+ return v;
897
+ }
898
+ function codebookDecodeStartShared(z, c) {
899
+ // C DECODE/DECODE_RAW (stb_vorbis.c:1763-1773): the scalar huffman
900
+ // path has NO lookupType restriction — classmaster codebooks in floor1
901
+ // are lookupType 0 (pure huffman). Only codebook_decode_start (VQ)
902
+ // rejects type 0.
903
+ prepHuffman(z);
904
+ let zz = decodeRawShared(z, c);
905
+ if (zz < 0) {
906
+ if (z.bytesInSeg === 0 && z.lastSeg)
907
+ return zz;
908
+ z.error = 11;
909
+ }
910
+ return zz;
911
+ }
912
+ function vorbisDecodePacket(f, len, pLeft, pRight) {
913
+ const res = { leftStart: 0, leftEnd: 0, rightStart: 0, rightEnd: 0, mode: 0 };
914
+ if (!vorbisDecodeInitial(f, res))
915
+ return false;
916
+ pLeft.v = res.leftStart;
917
+ pRight.v = res.rightStart;
918
+ return vorbisDecodePacketRest(f, len, f.modeConfig[res.mode], res.leftStart, res.leftEnd, res.rightStart, res.rightEnd, pLeft);
919
+ }
920
+ function vorbisFinishFrame(f, len, left, right) {
921
+ const prev0 = f.previousLength;
922
+ if (f.previousLength) {
923
+ const n = f.previousLength;
924
+ const w = getWindow(f, n);
925
+ if (w === null)
926
+ return 0;
927
+ for (let i = 0; i < f.channels; ++i) {
928
+ const cb = f.channelBuffers[i];
929
+ const pw = f.previousWindow[i];
930
+ for (let j = 0; j < n; ++j) {
931
+ cb[left + j] = cb[left + j] * w[j] + pw[j] * w[n - 1 - j];
932
+ }
933
+ }
934
+ }
935
+ const prev = f.previousLength;
936
+ void prev0;
937
+ f.previousLength = len - right;
938
+ for (let i = 0; i < f.channels; ++i) {
939
+ const cb = f.channelBuffers[i];
940
+ const pw = f.previousWindow[i];
941
+ for (let j = 0; right + j < len; ++j) {
942
+ pw[j] = cb[right + j];
943
+ }
944
+ }
945
+ if (!prev)
946
+ return 0;
947
+ if (len < right)
948
+ right = len;
949
+ f.samplesOutput += right - left;
950
+ return right - left;
951
+ }
952
+ function getWindow(f, len0) {
953
+ const len = len0 << 1;
954
+ if (len === f.blocksize0)
955
+ return f.window[0];
956
+ if (len === f.blocksize1)
957
+ return f.window[1];
958
+ return null;
959
+ }
960
+ function vorbisPumpFirstFrame(f) {
961
+ const len = { v: 0 };
962
+ const left = { v: 0 };
963
+ const right = { v: 0 };
964
+ const res = vorbisDecodePacket(f, len, left, right);
965
+ if (res)
966
+ vorbisFinishFrame(f, len.v, left.v, right.v);
967
+ return res;
968
+ }
969
+ // ---------------------------------------------------------------------------
970
+ // Public API (memory source)
971
+ // ---------------------------------------------------------------------------
972
+ export function stbVorbisOpenMemory(data, errorOut) {
973
+ const f = {
974
+ stream: data,
975
+ streamStart: 0,
976
+ streamEnd: data.length,
977
+ streamPos: 0,
978
+ streamLen: data.length,
979
+ eof: false,
980
+ error: 0,
981
+ sampleRate: 0,
982
+ channels: 0,
983
+ blocksize: [0, 0],
984
+ blocksize0: 0,
985
+ blocksize1: 0,
986
+ codebookCount: 0,
987
+ codebooks: [],
988
+ floorCount: 0,
989
+ floorTypes: [],
990
+ floor0Config: [],
991
+ floor1Config: [],
992
+ residueCount: 0,
993
+ residueTypes: [],
994
+ residueConfig: [],
995
+ mappingCount: 0,
996
+ mapping: [],
997
+ modeCount: 0,
998
+ modeConfig: [],
999
+ channelBuffers: [],
1000
+ outputs: [],
1001
+ previousWindow: [],
1002
+ previousLength: 0,
1003
+ finalY: [],
1004
+ currentLoc: 0,
1005
+ currentLocValid: false,
1006
+ A: [], B: [], C: [], window: [], bitReverse: [],
1007
+ firstDecode: false,
1008
+ nextSeg: -1,
1009
+ lastSeg: false,
1010
+ lastSegWhich: 0,
1011
+ acc: 0,
1012
+ validBits: 0,
1013
+ packetBytes: 0,
1014
+ endSegWithKnownLoc: -2,
1015
+ knownLocForPacket: 0,
1016
+ discardSamplesDeferred: 0,
1017
+ samplesOutput: 0,
1018
+ lastPage: 0,
1019
+ segmentCount: 0,
1020
+ segments: new Uint8Array(255),
1021
+ pageFlag: 0,
1022
+ bytesInSeg: 0,
1023
+ channelBufferStart: 0,
1024
+ channelBufferEnd: 0,
1025
+ firstAudioPageOffset: 0,
1026
+ };
1027
+ if (!startDecoder(f)) {
1028
+ errorOut.v = f.error;
1029
+ return null;
1030
+ }
1031
+ vorbisPumpFirstFrame(f);
1032
+ return f;
1033
+ }
1034
+ export function stbVorbisGetFrameFloat(f, len) {
1035
+ const left = { v: 0 };
1036
+ const right = { v: 0 };
1037
+ if (!vorbisDecodePacket(f, len, left, right)) {
1038
+ f.channelBufferStart = 0;
1039
+ f.channelBufferEnd = 0;
1040
+ return null;
1041
+ }
1042
+ len.v = vorbisFinishFrame(f, len.v, left.v, right.v);
1043
+ for (let i = 0; i < f.channels; ++i) {
1044
+ f.outputs[i] = f.channelBuffers[i].subarray(left.v);
1045
+ }
1046
+ f.channelBufferStart = left.v;
1047
+ f.channelBufferEnd = left.v + len.v;
1048
+ if (len.v === 0)
1049
+ return null;
1050
+ return f.outputs;
1051
+ }
1052
+ export { bitReverse, ilog, setFileOffset, getFileOffset, EOP, INVALID_BITS };
1053
+ //# sourceMappingURL=vorbis.js.map