carta1 1.1.7 → 1.1.9
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/codec/coding/bitallocation.js +209 -110
- package/codec/core/constants.js +19 -0
- package/codec/core/options.js +1 -1
- package/codec/pipeline/encoder.js +8 -3
- package/dist/carta1-worker.min.js +1 -1
- package/dist/carta1-worker.min.js.map +1 -1
- package/dist/carta1.min.js +1 -1
- package/dist/carta1.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,21 +5,20 @@
|
|
|
5
5
|
* responsible for distributing available bits across frequency bands to minimize
|
|
6
6
|
* perceptual distortion while maintaining the target bitrate.
|
|
7
7
|
*
|
|
8
|
-
* The module uses Rate-Distortion Optimization (RDO)
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* The module uses Rate-Distortion Optimization (RDO) by searching over a
|
|
9
|
+
* predefined set of valid Band Frequency Unit (BFU) counts. For each count,
|
|
10
|
+
* it performs a greedy bit distribution to find the best allocation. This
|
|
11
|
+
* approach optimally trades off the cost of encoding more frequency bands
|
|
12
|
+
* (metadata overhead) against the benefit of reducing truncation distortion.
|
|
13
13
|
*
|
|
14
14
|
* Key components:
|
|
15
|
-
* - RDO
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
* - Support for variable word lengths per BFU
|
|
15
|
+
* - RDO search over valid BFU counts to select the optimal number of bands.
|
|
16
|
+
* - Greedy bit allocation for a fixed BFU count using a max-heap.
|
|
17
|
+
* - Exponential distortion modeling based on scale factors.
|
|
18
|
+
* - Support for variable word lengths per BFU.
|
|
19
19
|
*
|
|
20
|
-
* The algorithm ensures that
|
|
21
|
-
*
|
|
22
|
-
* audio compression at the target bitrate.
|
|
20
|
+
* The algorithm ensures that the codec dynamically adapts the encoded bandwidth
|
|
21
|
+
* to best match the signal characteristics for the given bitrate.
|
|
23
22
|
*/
|
|
24
23
|
|
|
25
24
|
import {
|
|
@@ -31,10 +30,41 @@ import {
|
|
|
31
30
|
WORD_LENGTH_BITS,
|
|
32
31
|
INV_POWER_OF_TWO,
|
|
33
32
|
SCALE_FACTORS,
|
|
33
|
+
BFU_AMOUNTS,
|
|
34
|
+
WORD_LENGTH_DELTA_BITS,
|
|
35
|
+
DISTORTION_DELTA_FACTORS,
|
|
34
36
|
} from '../core/constants.js'
|
|
35
37
|
|
|
38
|
+
const biasedScaleFactorCache = new Map()
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Builds and returns a cached table of biased scale factors.
|
|
42
|
+
*
|
|
43
|
+
* @param {number} bias
|
|
44
|
+
* @returns {Float64Array}
|
|
45
|
+
*/
|
|
46
|
+
function buildBiasedScaleFactorTable(bias) {
|
|
47
|
+
if (biasedScaleFactorCache.has(bias)) {
|
|
48
|
+
return biasedScaleFactorCache.get(bias)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const out = new Float64Array(64)
|
|
52
|
+
if (bias === 1) {
|
|
53
|
+
out.set(SCALE_FACTORS)
|
|
54
|
+
} else {
|
|
55
|
+
for (let i = 0; i < 64; i++) {
|
|
56
|
+
out[i] = Math.pow(SCALE_FACTORS[i], bias)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
biasedScaleFactorCache.set(bias, out)
|
|
60
|
+
return out
|
|
61
|
+
}
|
|
62
|
+
|
|
36
63
|
/**
|
|
37
|
-
* Allocate bits
|
|
64
|
+
* Allocate bits by finding the optimal BFU count and distribution using RDO.
|
|
65
|
+
* This function searches through the valid BFU counts to find the one that
|
|
66
|
+
* minimizes the total perceptual distortion.
|
|
67
|
+
*
|
|
38
68
|
* @param {Array<Float32Array>} bfuData
|
|
39
69
|
* @param {Int32Array} bfuSizes
|
|
40
70
|
* @param {number} maxBfuCount
|
|
@@ -42,136 +72,224 @@ import {
|
|
|
42
72
|
* @returns {{bfuCount:number, allocation:Int32Array, scaleFactorIndices:Int32Array}}
|
|
43
73
|
*/
|
|
44
74
|
export function allocateBits(bfuData, bfuSizes, maxBfuCount, allocationBias) {
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
const allScaleFactorIndices = new Int32Array(maxBfuCount)
|
|
76
|
+
const zeroBitDistortions = new Float32Array(maxBfuCount)
|
|
77
|
+
const biasedScaleFactors = buildBiasedScaleFactorTable(allocationBias)
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < maxBfuCount; i++) {
|
|
80
|
+
const sz = bfuSizes[i] | 0
|
|
81
|
+
if (sz === 0) continue
|
|
82
|
+
|
|
83
|
+
const sfi = findScaleFactor(bfuData[i], sz)
|
|
84
|
+
allScaleFactorIndices[i] = sfi
|
|
85
|
+
if (sfi > 0) {
|
|
86
|
+
const effectiveScaleFactor = biasedScaleFactors[sfi]
|
|
87
|
+
zeroBitDistortions[i] = effectiveScaleFactor * 2.0 * sz
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let bestResult = null
|
|
92
|
+
let minTotalDistortion = Infinity
|
|
93
|
+
|
|
94
|
+
for (const candidateBfuCount of BFU_AMOUNTS) {
|
|
95
|
+
if (candidateBfuCount > maxBfuCount) continue
|
|
96
|
+
|
|
97
|
+
const availableBits =
|
|
98
|
+
FRAME_BITS -
|
|
99
|
+
FRAME_OVERHEAD_BITS -
|
|
100
|
+
candidateBfuCount * BITS_PER_BFU_METADATA
|
|
101
|
+
|
|
102
|
+
if (availableBits < 0) continue
|
|
103
|
+
|
|
104
|
+
const rdoResult = distributeBitsRDO(
|
|
105
|
+
candidateBfuCount,
|
|
106
|
+
bfuSizes,
|
|
107
|
+
availableBits,
|
|
108
|
+
biasedScaleFactors,
|
|
109
|
+
allScaleFactorIndices
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const totalDistortion = calculateTotalDistortion(
|
|
113
|
+
candidateBfuCount,
|
|
114
|
+
maxBfuCount,
|
|
115
|
+
bfuSizes,
|
|
116
|
+
rdoResult.wordLengths,
|
|
117
|
+
rdoResult.scaleFactorIndices,
|
|
118
|
+
biasedScaleFactors,
|
|
119
|
+
zeroBitDistortions
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if (totalDistortion < minTotalDistortion) {
|
|
123
|
+
minTotalDistortion = totalDistortion
|
|
124
|
+
bestResult = {
|
|
125
|
+
bfuCount: candidateBfuCount,
|
|
126
|
+
allocation: rdoResult.wordLengths,
|
|
127
|
+
scaleFactorIndices: rdoResult.scaleFactorIndices,
|
|
128
|
+
}
|
|
129
|
+
}
|
|
61
130
|
}
|
|
131
|
+
|
|
132
|
+
if (!bestResult) {
|
|
133
|
+
const fallbackBfuCount = BFU_AMOUNTS[0]
|
|
134
|
+
return {
|
|
135
|
+
bfuCount: fallbackBfuCount,
|
|
136
|
+
allocation: new Int32Array(fallbackBfuCount),
|
|
137
|
+
scaleFactorIndices: new Int32Array(NUM_BFUS),
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return bestResult
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Calculates the total distortion for a given allocation.
|
|
146
|
+
* This includes quantization distortion for coded bands and truncation
|
|
147
|
+
* distortion for uncoded bands.
|
|
148
|
+
* @param {number} activeBfuCount
|
|
149
|
+
* @param {number} maxBfuCount
|
|
150
|
+
* @param {Int32Array} bfuSizes
|
|
151
|
+
* @param {Int32Array} wordLengths
|
|
152
|
+
* @param {Int32Array} scaleFactorIndices
|
|
153
|
+
* @param {number} biasedScaleFactors
|
|
154
|
+
* @param {Float32Array} zeroBitDistortions
|
|
155
|
+
* @returns {number}
|
|
156
|
+
*/
|
|
157
|
+
function calculateTotalDistortion(
|
|
158
|
+
activeBfuCount,
|
|
159
|
+
maxBfuCount,
|
|
160
|
+
bfuSizes,
|
|
161
|
+
wordLengths,
|
|
162
|
+
scaleFactorIndices,
|
|
163
|
+
biasedScaleFactors,
|
|
164
|
+
zeroBitDistortions
|
|
165
|
+
) {
|
|
166
|
+
let totalDistortion = 0.0
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < activeBfuCount; i++) {
|
|
169
|
+
const wl = wordLengths[i] | 0
|
|
170
|
+
const bits = WORD_LENGTH_BITS[wl] | 0
|
|
171
|
+
if (bits === 0) {
|
|
172
|
+
totalDistortion += zeroBitDistortions[i]
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const sfi = scaleFactorIndices[i]
|
|
177
|
+
if (sfi === 0) continue
|
|
178
|
+
|
|
179
|
+
const effectiveScaleFactor = biasedScaleFactors[sfi]
|
|
180
|
+
const distortionFactor = INV_POWER_OF_TWO[bits]
|
|
181
|
+
|
|
182
|
+
totalDistortion += effectiveScaleFactor * distortionFactor * bfuSizes[i]
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
for (let i = activeBfuCount; i < maxBfuCount; i++) {
|
|
186
|
+
totalDistortion += zeroBitDistortions[i]
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return totalDistortion
|
|
62
190
|
}
|
|
63
191
|
|
|
64
192
|
/**
|
|
65
193
|
* Distributes available bits across Band Frequency Units (BFUs) using Rate-Distortion Optimization.
|
|
66
|
-
*
|
|
67
|
-
* This function implements an optimized greedy RDO allocator that minimizes perceptual distortion
|
|
68
|
-
* while staying within the bit budget. It uses a priority queue (max-heap) to greedily allocate
|
|
69
|
-
* bits to the BFUs that provide the greatest distortion reduction per bit spent.
|
|
194
|
+
* (Modified to accept pre-calculated scale factors)
|
|
70
195
|
*
|
|
71
196
|
* @param {number} activeBfuCount
|
|
72
|
-
* @param {Array<Float32Array>} bfuData
|
|
73
197
|
* @param {Int32Array} bfuSizes
|
|
74
198
|
* @param {number} remainingBits
|
|
75
|
-
* @param {
|
|
199
|
+
* @param {Float64Array} biasedScaleFactors
|
|
200
|
+
* @param {Int32Array} allScaleFactorIndices
|
|
76
201
|
* @returns {{wordLengths: Int32Array, scaleFactorIndices: Int32Array}}
|
|
77
202
|
*/
|
|
78
203
|
function distributeBitsRDO(
|
|
79
204
|
activeBfuCount,
|
|
80
|
-
bfuData,
|
|
81
205
|
bfuSizes,
|
|
82
206
|
remainingBits,
|
|
83
|
-
|
|
207
|
+
biasedScaleFactors,
|
|
208
|
+
allScaleFactorIndices
|
|
84
209
|
) {
|
|
85
|
-
const scaleFactorTable = new Int32Array(NUM_BFUS)
|
|
86
210
|
const wordLengths = new Int32Array(activeBfuCount)
|
|
87
211
|
|
|
88
|
-
const heapIndices =
|
|
89
|
-
const heapPriorities =
|
|
90
|
-
|
|
91
|
-
const deltaDistPerCoeff = (bfuIndex, currentWl, nextWl) => {
|
|
92
|
-
const sfi = scaleFactorTable[bfuIndex]
|
|
93
|
-
const scaleFactor = SCALE_FACTORS[sfi]
|
|
94
|
-
if (scaleFactor === 0) return 0
|
|
95
|
-
|
|
96
|
-
const effectiveScaleFactor = Math.pow(scaleFactor, allocationBias)
|
|
97
|
-
|
|
98
|
-
const bits1 = WORD_LENGTH_BITS[currentWl] | 0
|
|
99
|
-
const bits2 = WORD_LENGTH_BITS[nextWl] | 0
|
|
100
|
-
|
|
101
|
-
const f1 = bits1 === 0 ? 2.0 : INV_POWER_OF_TWO[bits1]
|
|
102
|
-
const f2 = INV_POWER_OF_TWO[bits2]
|
|
103
|
-
|
|
104
|
-
return effectiveScaleFactor * (f1 - f2)
|
|
105
|
-
}
|
|
212
|
+
const heapIndices = new Int32Array(activeBfuCount)
|
|
213
|
+
const heapPriorities = new Float32Array(activeBfuCount)
|
|
214
|
+
let heapSize = 0
|
|
106
215
|
|
|
107
216
|
for (let bfuIndex = 0; bfuIndex < activeBfuCount; bfuIndex++) {
|
|
108
217
|
const sz = bfuSizes[bfuIndex] | 0
|
|
109
218
|
if (sz === 0) continue
|
|
110
219
|
|
|
111
|
-
const sfi =
|
|
112
|
-
scaleFactorTable[bfuIndex] = sfi
|
|
113
|
-
|
|
220
|
+
const sfi = allScaleFactorIndices[bfuIndex]
|
|
114
221
|
if (sfi === 0) continue
|
|
115
222
|
|
|
116
|
-
const
|
|
117
|
-
const nextWl = 1
|
|
118
|
-
const deltaBits =
|
|
119
|
-
(WORD_LENGTH_BITS[nextWl] - WORD_LENGTH_BITS[currentWl]) | 0
|
|
223
|
+
const deltaBits = WORD_LENGTH_DELTA_BITS[0]
|
|
120
224
|
if (deltaBits <= 0) continue
|
|
121
225
|
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
226
|
+
const distortionDelta =
|
|
227
|
+
biasedScaleFactors[sfi] * DISTORTION_DELTA_FACTORS[0]
|
|
228
|
+
|
|
229
|
+
heapIndices[heapSize] = bfuIndex
|
|
230
|
+
heapPriorities[heapSize] = distortionDelta / deltaBits
|
|
231
|
+
heapSize++
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (heapSize === 0) {
|
|
235
|
+
return { wordLengths, scaleFactorIndices: allScaleFactorIndices }
|
|
125
236
|
}
|
|
126
237
|
|
|
127
238
|
// Heapify
|
|
128
|
-
for (let i = (
|
|
129
|
-
siftDown(heapIndices, heapPriorities, i)
|
|
239
|
+
for (let i = (heapSize >> 1) - 1; i >= 0; i--) {
|
|
240
|
+
siftDown(heapIndices, heapPriorities, i, heapSize)
|
|
241
|
+
}
|
|
130
242
|
|
|
131
|
-
// Greedy spending
|
|
132
|
-
while (remainingBits > 0 &&
|
|
243
|
+
// Greedy spending loop
|
|
244
|
+
while (remainingBits > 0 && heapSize > 0) {
|
|
133
245
|
const bfu = heapIndices[0]
|
|
134
246
|
const cur = wordLengths[bfu] | 0
|
|
135
|
-
const nxt = cur + 1
|
|
136
|
-
|
|
137
247
|
const sz = bfuSizes[bfu] | 0
|
|
138
|
-
const deltaBits =
|
|
248
|
+
const deltaBits = WORD_LENGTH_DELTA_BITS[cur]
|
|
139
249
|
const cost = deltaBits * sz
|
|
140
250
|
|
|
141
251
|
if (cost > remainingBits || cost <= 0) {
|
|
142
|
-
|
|
252
|
+
const last = heapSize - 1
|
|
253
|
+
heapIndices[0] = heapIndices[last]
|
|
254
|
+
heapPriorities[0] = heapPriorities[last]
|
|
255
|
+
heapSize--
|
|
256
|
+
if (heapSize > 0) siftDown(heapIndices, heapPriorities, 0, heapSize)
|
|
143
257
|
continue
|
|
144
258
|
}
|
|
145
259
|
|
|
146
260
|
remainingBits -= cost
|
|
261
|
+
const nxt = cur + 1
|
|
147
262
|
wordLengths[bfu] = nxt
|
|
148
263
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
popRoot(heapIndices, heapPriorities)
|
|
157
|
-
}
|
|
264
|
+
const deltaBitsNext = WORD_LENGTH_DELTA_BITS[nxt]
|
|
265
|
+
if (nxt < MAX_WORD_LENGTH_INDEX && deltaBitsNext > 0) {
|
|
266
|
+
const sfi = allScaleFactorIndices[bfu]
|
|
267
|
+
const distortionDelta =
|
|
268
|
+
biasedScaleFactors[sfi] * DISTORTION_DELTA_FACTORS[nxt]
|
|
269
|
+
heapPriorities[0] = distortionDelta / deltaBitsNext
|
|
270
|
+
siftDown(heapIndices, heapPriorities, 0, heapSize)
|
|
158
271
|
} else {
|
|
159
|
-
|
|
272
|
+
const last = heapSize - 1
|
|
273
|
+
heapIndices[0] = heapIndices[last]
|
|
274
|
+
heapPriorities[0] = heapPriorities[last]
|
|
275
|
+
heapSize--
|
|
276
|
+
if (heapSize > 0) siftDown(heapIndices, heapPriorities, 0, heapSize)
|
|
160
277
|
}
|
|
161
278
|
}
|
|
162
279
|
|
|
163
|
-
return { wordLengths, scaleFactorIndices:
|
|
280
|
+
return { wordLengths, scaleFactorIndices: allScaleFactorIndices }
|
|
164
281
|
}
|
|
165
282
|
|
|
166
283
|
/**
|
|
167
284
|
* Find the optimal scale factor index for a set of coefficients.
|
|
168
285
|
* Same semantics as the original.
|
|
169
286
|
* @param {Float32Array} coefficients
|
|
287
|
+
* @param {number} length
|
|
170
288
|
* @returns {number}
|
|
171
289
|
*/
|
|
172
|
-
export function findScaleFactor(coefficients) {
|
|
290
|
+
export function findScaleFactor(coefficients, length) {
|
|
173
291
|
let maxAmplitude = 0.0
|
|
174
|
-
for (let i = 0; i <
|
|
292
|
+
for (let i = 0; i < length; i++) {
|
|
175
293
|
const a = Math.abs(coefficients[i])
|
|
176
294
|
if (a > maxAmplitude) maxAmplitude = a
|
|
177
295
|
}
|
|
@@ -180,25 +298,6 @@ export function findScaleFactor(coefficients) {
|
|
|
180
298
|
return Math.max(0, Math.min(63, index))
|
|
181
299
|
}
|
|
182
300
|
|
|
183
|
-
/**
|
|
184
|
-
* Removes the root element from a max-heap and maintains heap property.
|
|
185
|
-
*
|
|
186
|
-
* This function efficiently removes the maximum priority element from the heap
|
|
187
|
-
* by replacing it with the last element and then restoring the heap property
|
|
188
|
-
* through sifting down.
|
|
189
|
-
*
|
|
190
|
-
* @param {Array<number>} heapIndices
|
|
191
|
-
* @param {Array<number>} heapPriorities
|
|
192
|
-
*/
|
|
193
|
-
function popRoot(heapIndices, heapPriorities) {
|
|
194
|
-
const last = heapIndices.length - 1
|
|
195
|
-
heapIndices[0] = heapIndices[last]
|
|
196
|
-
heapPriorities[0] = heapPriorities[last]
|
|
197
|
-
heapIndices.pop()
|
|
198
|
-
heapPriorities.pop()
|
|
199
|
-
if (heapIndices.length) siftDown(heapIndices, heapPriorities, 0)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
301
|
/**
|
|
203
302
|
* Restores max-heap property by sifting an element down from a given position.
|
|
204
303
|
*
|
|
@@ -207,12 +306,12 @@ function popRoot(heapIndices, heapPriorities) {
|
|
|
207
306
|
* with its children and swaps with the larger child until the heap property
|
|
208
307
|
* is satisfied, or it reaches a leaf position.
|
|
209
308
|
*
|
|
210
|
-
* @param {
|
|
211
|
-
* @param {
|
|
309
|
+
* @param {Int32Array} heapIndices
|
|
310
|
+
* @param {Float32Array} heapPriorities
|
|
212
311
|
* @param {number} startIndex
|
|
312
|
+
* @param {number} heapSize
|
|
213
313
|
*/
|
|
214
|
-
function siftDown(heapIndices, heapPriorities, startIndex) {
|
|
215
|
-
const heapSize = heapIndices.length
|
|
314
|
+
function siftDown(heapIndices, heapPriorities, startIndex, heapSize) {
|
|
216
315
|
let i = startIndex
|
|
217
316
|
const idxVal = heapIndices[i]
|
|
218
317
|
const prVal = heapPriorities[i]
|
package/codec/core/constants.js
CHANGED
|
@@ -158,3 +158,22 @@ export const INV_POWER_OF_TWO = (() => {
|
|
|
158
158
|
}
|
|
159
159
|
return table
|
|
160
160
|
})()
|
|
161
|
+
|
|
162
|
+
export const WORD_LENGTH_DELTA_BITS = (() => {
|
|
163
|
+
const table = new Int32Array(MAX_WORD_LENGTH_INDEX)
|
|
164
|
+
for (let i = 0; i < MAX_WORD_LENGTH_INDEX; i++) {
|
|
165
|
+
table[i] = (WORD_LENGTH_BITS[i + 1] - WORD_LENGTH_BITS[i]) | 0
|
|
166
|
+
}
|
|
167
|
+
return table
|
|
168
|
+
})()
|
|
169
|
+
|
|
170
|
+
export const DISTORTION_DELTA_FACTORS = (() => {
|
|
171
|
+
const table = new Float64Array(MAX_WORD_LENGTH_INDEX)
|
|
172
|
+
table[0] = 2.0 - INV_POWER_OF_TWO[WORD_LENGTH_BITS[1]]
|
|
173
|
+
for (let i = 1; i < MAX_WORD_LENGTH_INDEX; i++) {
|
|
174
|
+
const bits1 = WORD_LENGTH_BITS[i] | 0
|
|
175
|
+
const bits2 = WORD_LENGTH_BITS[i + 1] | 0
|
|
176
|
+
table[i] = INV_POWER_OF_TWO[bits1] - INV_POWER_OF_TWO[bits2]
|
|
177
|
+
}
|
|
178
|
+
return table
|
|
179
|
+
})()
|
package/codec/core/options.js
CHANGED
|
@@ -52,7 +52,7 @@ class EncoderOptions {
|
|
|
52
52
|
name: 'Bit allocation bias',
|
|
53
53
|
description:
|
|
54
54
|
'Controls how bits are distributed across the frequency spectrum during allocation. Higher values focus more bits on loud spectral components, while lower values spread bits more evenly across frequencies.',
|
|
55
|
-
range: [0.
|
|
55
|
+
range: [0.0, 5.0],
|
|
56
56
|
step: 0.01,
|
|
57
57
|
},
|
|
58
58
|
fixedBlockModes: {
|
|
@@ -392,11 +392,16 @@ export function quantizationStage(context) {
|
|
|
392
392
|
scaleFactorIndices,
|
|
393
393
|
} = allocateBits(bfuData, bfuSizes, bfuCount, options.allocationBias)
|
|
394
394
|
|
|
395
|
+
const slicedWordLengthIndices = allocation.slice(0, selectedBfuCount)
|
|
396
|
+
const slicedScaleFactorIndices = scaleFactorIndices.slice(
|
|
397
|
+
0,
|
|
398
|
+
selectedBfuCount
|
|
399
|
+
)
|
|
395
400
|
const quantizedCoefficients = []
|
|
396
401
|
|
|
397
402
|
for (let bfu = 0; bfu < selectedBfuCount; bfu++) {
|
|
398
403
|
const data = bfuData[bfu].subarray(0, bfuSizes[bfu])
|
|
399
|
-
const wordLength =
|
|
404
|
+
const wordLength = slicedWordLengthIndices[bfu]
|
|
400
405
|
const bitsPerSample = WORD_LENGTH_BITS[wordLength]
|
|
401
406
|
const quantized = quantize(data, scaleFactorIndices[bfu], bitsPerSample)
|
|
402
407
|
quantizedCoefficients.push(quantized)
|
|
@@ -404,8 +409,8 @@ export function quantizationStage(context) {
|
|
|
404
409
|
|
|
405
410
|
return {
|
|
406
411
|
nBfu: selectedBfuCount,
|
|
407
|
-
scaleFactorIndices,
|
|
408
|
-
wordLengthIndices:
|
|
412
|
+
scaleFactorIndices: slicedScaleFactorIndices,
|
|
413
|
+
wordLengthIndices: slicedWordLengthIndices,
|
|
409
414
|
quantizedCoefficients,
|
|
410
415
|
blockModes,
|
|
411
416
|
}
|