carta1 1.0.22 → 1.1.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/codec/browser/interface.js +0 -1
- package/codec/coding/bitallocation.js +159 -250
- package/codec/coding/quantization.js +79 -78
- package/codec/core/buffers.js +1 -30
- package/codec/core/constants.js +10 -180
- package/codec/core/options.js +0 -13
- package/codec/pipeline/decoder.js +23 -3
- package/codec/pipeline/encoder.js +37 -43
- package/dist/carta1-worker-interface.min.js.map +1 -1
- 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
- package/codec/analysis/psychoacoustics.js +0 -631
|
@@ -71,7 +71,6 @@ class Carta1Worker {
|
|
|
71
71
|
* @param {number} [options.transientThresholdLow] - Low band transient threshold
|
|
72
72
|
* @param {number} [options.transientThresholdMid] - Mid band transient threshold
|
|
73
73
|
* @param {number} [options.transientThresholdHigh] - High band transient threshold
|
|
74
|
-
* @param {number} [options.normalizationDb] - Normalization level in dB
|
|
75
74
|
* @returns {Promise<Object>} Encoding result
|
|
76
75
|
* @returns {Blob} returns.aeaBlob - ATRAC1 encoded audio blob
|
|
77
76
|
* @returns {Object} returns.shortBlockData - Short block frame indices
|
|
@@ -1,317 +1,226 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Carta1 Audio Codec - Bit Allocation Module
|
|
3
3
|
*
|
|
4
|
-
* This module implements the bit allocation
|
|
5
|
-
* distributing available bits
|
|
6
|
-
*
|
|
4
|
+
* This module implements the bit allocation system for the Carta1 audio codec,
|
|
5
|
+
* responsible for distributing available bits across frequency bands to minimize
|
|
6
|
+
* perceptual distortion while maintaining the target bitrate.
|
|
7
|
+
*
|
|
8
|
+
* The module uses Rate-Distortion Optimization (RDO) with a greedy algorithm
|
|
9
|
+
* that allocates bits to Band Frequency Units (BFUs) based on the perceptual
|
|
10
|
+
* benefit per bit spent. It employs psychoacoustic modeling to determine
|
|
11
|
+
* scale factors and uses a priority queue to efficiently find the optimal
|
|
12
|
+
* bit distribution.
|
|
13
|
+
*
|
|
14
|
+
* Key components:
|
|
15
|
+
* - RDO-based bit allocation using exponential distortion modeling
|
|
16
|
+
* - Scale factor computation for each frequency band
|
|
17
|
+
* - Max-heap priority queue for greedy optimization
|
|
18
|
+
* - Support for variable word lengths per BFU
|
|
19
|
+
*
|
|
20
|
+
* The algorithm ensures that bits are allocated where they provide the
|
|
21
|
+
* greatest reduction in audible distortion, resulting in high-quality
|
|
22
|
+
* audio compression at the target bitrate.
|
|
7
23
|
*/
|
|
24
|
+
|
|
8
25
|
import {
|
|
26
|
+
NUM_BFUS,
|
|
9
27
|
FRAME_BITS,
|
|
10
28
|
FRAME_OVERHEAD_BITS,
|
|
11
29
|
BITS_PER_BFU_METADATA,
|
|
12
|
-
BFU_AMOUNTS,
|
|
13
30
|
MAX_WORD_LENGTH_INDEX,
|
|
14
31
|
WORD_LENGTH_BITS,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
INTERPOLATION_COMPENSATION_FACTOR,
|
|
18
|
-
BFU_MASK_INTERPOLATION_TABLE,
|
|
19
|
-
BFU_FREQUENCIES,
|
|
20
|
-
NUM_BFUS,
|
|
21
|
-
SAMPLE_RATE,
|
|
22
|
-
PSYMODEL_FFT_SIZE,
|
|
32
|
+
INV_POWER_OF_TWO,
|
|
33
|
+
SCALE_FACTORS,
|
|
23
34
|
} from '../core/constants.js'
|
|
24
35
|
|
|
25
36
|
/**
|
|
26
|
-
* Allocate bits to BFUs
|
|
27
|
-
* @param {
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {
|
|
30
|
-
* @
|
|
31
|
-
* @returns {Object} Allocation results with BFU count and bit distribution
|
|
37
|
+
* Allocate bits to BFUs using optimized greedy Lp-RDO
|
|
38
|
+
* @param {Array<Float32Array>} bfuData
|
|
39
|
+
* @param {Int32Array} bfuSizes
|
|
40
|
+
* @param {number} maxBfuCount
|
|
41
|
+
* @returns {{bfuCount:number, allocation:Int32Array, scaleFactorIndices:Int32Array}}
|
|
32
42
|
*/
|
|
33
|
-
export function allocateBits(
|
|
34
|
-
const
|
|
35
|
-
const maskDb = interpolateMask(psychoResults.criticalBandThresholds)
|
|
36
|
-
const smr = calculateSMR(energyDb, maskDb, maxBfuCount)
|
|
37
|
-
const usedBFU = selectOptimalBfuCount(smr, energyDb, maxBfuCount)
|
|
43
|
+
export function allocateBits(bfuData, bfuSizes, maxBfuCount) {
|
|
44
|
+
const usedBFU = maxBfuCount
|
|
38
45
|
const avail =
|
|
39
46
|
FRAME_BITS - FRAME_OVERHEAD_BITS - usedBFU * BITS_PER_BFU_METADATA
|
|
40
|
-
const allocation = distributeBitsGreedy(usedBFU, smr, bfuSizes, avail)
|
|
41
|
-
return { bfuCount: usedBFU, allocation }
|
|
42
|
-
}
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
*/
|
|
51
|
-
function calculateBfuEnergy(bfuData, bfuSizes, bfuCount) {
|
|
52
|
-
const out = new Float32Array(bfuCount)
|
|
53
|
-
const minDb = PSYMODEL_MIN_POWER_DB
|
|
54
|
-
for (let i = 0; i < bfuCount; i++) {
|
|
55
|
-
const sz = bfuSizes[i]
|
|
56
|
-
if (!sz) {
|
|
57
|
-
out[i] = minDb
|
|
58
|
-
continue
|
|
59
|
-
}
|
|
60
|
-
let sum = 0,
|
|
61
|
-
buf = bfuData[i]
|
|
62
|
-
for (let j = 0; j < sz; j++) sum += buf[j] * buf[j]
|
|
63
|
-
out[i] = sum > 0 ? 10 * Math.log10(sum / sz) : minDb
|
|
48
|
+
const rdoResult = distributeBitsRDO(usedBFU, bfuData, bfuSizes, avail)
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
bfuCount: usedBFU,
|
|
52
|
+
allocation: rdoResult.wordLengths,
|
|
53
|
+
scaleFactorIndices: rdoResult.scaleFactorIndices,
|
|
64
54
|
}
|
|
65
|
-
return out
|
|
66
55
|
}
|
|
67
56
|
|
|
68
57
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
58
|
+
* Distributes available bits across Band Frequency Units (BFUs) using Rate-Distortion Optimization.
|
|
59
|
+
*
|
|
60
|
+
* This function implements an optimized greedy RDO allocator that minimizes perceptual distortion
|
|
61
|
+
* while staying within the bit budget. It uses a priority queue (max-heap) to greedily allocate
|
|
62
|
+
* bits to the BFUs that provide the greatest distortion reduction per bit spent.
|
|
63
|
+
*
|
|
64
|
+
* @param {number} activeBfuCount
|
|
65
|
+
* @param {Array<Float32Array>} bfuData
|
|
66
|
+
* @param {Int32Array} bfuSizes
|
|
67
|
+
* @param {number} remainingBits
|
|
68
|
+
* @returns {{wordLengths: Int32Array, scaleFactorIndices: Int32Array}}
|
|
72
69
|
*/
|
|
73
|
-
function
|
|
74
|
-
const
|
|
70
|
+
function distributeBitsRDO(activeBfuCount, bfuData, bfuSizes, remainingBits) {
|
|
71
|
+
const scaleFactorTable = new Int32Array(NUM_BFUS)
|
|
72
|
+
const wordLengths = new Int32Array(activeBfuCount)
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const currentBandThreshold = criticalBandThresholds[interpolationEntry.band]
|
|
79
|
-
const nextBandThreshold = criticalBandThresholds[interpolationEntry.next]
|
|
74
|
+
const heapIndices = []
|
|
75
|
+
const heapPriorities = []
|
|
80
76
|
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
) -
|
|
86
|
-
interpolationEntry.x0) *
|
|
87
|
-
interpolationEntry.tInv
|
|
77
|
+
const deltaDistPerCoeff = (bfuIndex, currentWl, nextWl) => {
|
|
78
|
+
const sfi = scaleFactorTable[bfuIndex]
|
|
79
|
+
const scaleFactor = SCALE_FACTORS[sfi]
|
|
80
|
+
if (scaleFactor === 0) return 0
|
|
88
81
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
(nextBandThreshold - currentBandThreshold) * normalizedFreqPosition
|
|
82
|
+
const bits1 = WORD_LENGTH_BITS[currentWl] | 0
|
|
83
|
+
const bits2 = WORD_LENGTH_BITS[nextWl] | 0
|
|
92
84
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
interpolatedValue +
|
|
96
|
-
Math.abs(nextBandThreshold - currentBandThreshold) *
|
|
97
|
-
INTERPOLATION_COMPENSATION_FACTOR
|
|
98
|
-
}
|
|
85
|
+
const f1 = bits1 === 0 ? 2.0 : INV_POWER_OF_TWO[bits1]
|
|
86
|
+
const f2 = INV_POWER_OF_TWO[bits2]
|
|
99
87
|
|
|
100
|
-
|
|
101
|
-
}
|
|
88
|
+
return scaleFactor * (f1 - f2)
|
|
89
|
+
}
|
|
102
90
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
* @param {Float32Array} energyDb - Energy values in dB for each BFU
|
|
107
|
-
* @param {Float32Array} maskDb - Masking threshold values in dB for each BFU
|
|
108
|
-
* @param {number} bfuCount - Number of BFUs to process
|
|
109
|
-
* @returns {Float32Array} SMR values for each BFU (-Infinity for inaudible BFUs)
|
|
110
|
-
*/
|
|
111
|
-
function calculateSMR(energyDb, maskDb, bfuCount) {
|
|
112
|
-
const smrValues = new Float32Array(bfuCount)
|
|
91
|
+
for (let bfuIndex = 0; bfuIndex < activeBfuCount; bfuIndex++) {
|
|
92
|
+
const sz = bfuSizes[bfuIndex] | 0
|
|
93
|
+
if (sz === 0) continue
|
|
113
94
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
smrValues[bfuIndex] =
|
|
117
|
-
energyValue <= PSYMODEL_MIN_POWER_DB
|
|
118
|
-
? -Infinity
|
|
119
|
-
: energyValue - maskDb[bfuIndex]
|
|
120
|
-
}
|
|
95
|
+
const sfi = findScaleFactor(bfuData[bfuIndex].subarray(0, sz))
|
|
96
|
+
scaleFactorTable[bfuIndex] = sfi
|
|
121
97
|
|
|
122
|
-
|
|
123
|
-
}
|
|
98
|
+
if (sfi === 0) continue
|
|
124
99
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
* @param {number} maxBfuCount - Maximum BFUs available
|
|
131
|
-
* @returns {number} Optimal number of BFUs to use for encoding
|
|
132
|
-
*/
|
|
133
|
-
function selectOptimalBfuCount(smrValues, energyValues, maxBfuCount) {
|
|
134
|
-
// Collect BFUs with positive SMR (above masking threshold)
|
|
135
|
-
const positiveSMRBfus = []
|
|
136
|
-
for (let bfuIndex = 0; bfuIndex < maxBfuCount; bfuIndex++) {
|
|
137
|
-
if (smrValues[bfuIndex] > 0) {
|
|
138
|
-
positiveSMRBfus.push({
|
|
139
|
-
index: bfuIndex,
|
|
140
|
-
smrValue: smrValues[bfuIndex],
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
}
|
|
100
|
+
const currentWl = 0
|
|
101
|
+
const nextWl = 1
|
|
102
|
+
const deltaBits =
|
|
103
|
+
(WORD_LENGTH_BITS[nextWl] - WORD_LENGTH_BITS[currentWl]) | 0
|
|
104
|
+
if (deltaBits <= 0) continue
|
|
144
105
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (energyValues[bfuIndex] > PSYMODEL_MIN_POWER_DB) {
|
|
149
|
-
return (
|
|
150
|
-
BFU_AMOUNTS.find((count) => count > bfuIndex) ||
|
|
151
|
-
BFU_AMOUNTS[BFU_AMOUNTS.length - 1]
|
|
152
|
-
)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return BFU_AMOUNTS[0]
|
|
106
|
+
const ddPerCoeff = deltaDistPerCoeff(bfuIndex, currentWl, nextWl)
|
|
107
|
+
heapIndices.push(bfuIndex)
|
|
108
|
+
heapPriorities.push(ddPerCoeff / deltaBits)
|
|
156
109
|
}
|
|
157
110
|
|
|
158
|
-
//
|
|
159
|
-
|
|
111
|
+
// Heapify
|
|
112
|
+
for (let i = (heapIndices.length >> 1) - 1; i >= 0; i--)
|
|
113
|
+
siftDown(heapIndices, heapPriorities, i)
|
|
160
114
|
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
115
|
+
// Greedy spending
|
|
116
|
+
while (remainingBits > 0 && heapIndices.length > 0) {
|
|
117
|
+
const bfu = heapIndices[0]
|
|
118
|
+
const cur = wordLengths[bfu] | 0
|
|
119
|
+
const nxt = cur + 1
|
|
167
120
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (positiveSMRBfus.length <= candidateCount) return candidateCount
|
|
121
|
+
const sz = bfuSizes[bfu] | 0
|
|
122
|
+
const deltaBits = (WORD_LENGTH_BITS[nxt] - WORD_LENGTH_BITS[cur]) | 0
|
|
123
|
+
const cost = deltaBits * sz
|
|
172
124
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
(cumulativeSmr[positiveSMRBfus.length - 1] -
|
|
178
|
-
cumulativeSmr[lastIncludedIndex]) /
|
|
179
|
-
(positiveSMRBfus.length - lastIncludedIndex - 1)
|
|
125
|
+
if (cost > remainingBits || cost <= 0) {
|
|
126
|
+
popRoot(heapIndices, heapPriorities)
|
|
127
|
+
continue
|
|
128
|
+
}
|
|
180
129
|
|
|
181
|
-
|
|
182
|
-
|
|
130
|
+
remainingBits -= cost
|
|
131
|
+
wordLengths[bfu] = nxt
|
|
132
|
+
|
|
133
|
+
if (nxt < MAX_WORD_LENGTH_INDEX) {
|
|
134
|
+
const nxt2 = nxt + 1
|
|
135
|
+
const deltaBits2 = (WORD_LENGTH_BITS[nxt2] - WORD_LENGTH_BITS[nxt]) | 0
|
|
136
|
+
if (deltaBits2 > 0) {
|
|
137
|
+
heapPriorities[0] = deltaDistPerCoeff(bfu, nxt, nxt2) / deltaBits2
|
|
138
|
+
siftDown(heapIndices, heapPriorities, 0)
|
|
139
|
+
} else {
|
|
140
|
+
popRoot(heapIndices, heapPriorities)
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
popRoot(heapIndices, heapPriorities)
|
|
144
|
+
}
|
|
183
145
|
}
|
|
184
146
|
|
|
185
|
-
return
|
|
147
|
+
return { wordLengths, scaleFactorIndices: scaleFactorTable }
|
|
186
148
|
}
|
|
187
149
|
|
|
188
150
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* @param {
|
|
192
|
-
* @
|
|
193
|
-
* @param {Array} bfuSizes - Size (coefficient count) of each BFU
|
|
194
|
-
* @param {number} remainingBits - Total bits available for distribution
|
|
195
|
-
* @returns {Int32Array} Word length index allocation per BFU
|
|
151
|
+
* Find the optimal scale factor index for a set of coefficients.
|
|
152
|
+
* Same semantics as the original.
|
|
153
|
+
* @param {Float32Array} coefficients
|
|
154
|
+
* @returns {number}
|
|
196
155
|
*/
|
|
197
|
-
function
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
) {
|
|
203
|
-
const wordLengthAllocation = new Int32Array(activeBfuCount)
|
|
204
|
-
const heapBfuIndices = []
|
|
205
|
-
const heapPriorities = []
|
|
206
|
-
|
|
207
|
-
// Initialize heap with BFUs that have finite SMR values
|
|
208
|
-
for (let bfuIndex = 0; bfuIndex < activeBfuCount; bfuIndex++) {
|
|
209
|
-
if (smrValues[bfuIndex] > -Infinity) {
|
|
210
|
-
heapBfuIndices.push(bfuIndex)
|
|
211
|
-
heapPriorities.push(smrValues[bfuIndex])
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Build max-heap structure
|
|
216
|
-
for (
|
|
217
|
-
let nodeIndex = (heapBfuIndices.length >> 1) - 1;
|
|
218
|
-
nodeIndex >= 0;
|
|
219
|
-
nodeIndex--
|
|
220
|
-
) {
|
|
221
|
-
siftDown(heapBfuIndices, heapPriorities, nodeIndex)
|
|
156
|
+
export function findScaleFactor(coefficients) {
|
|
157
|
+
let maxAmplitude = 0.0
|
|
158
|
+
for (let i = 0; i < coefficients.length; i++) {
|
|
159
|
+
const a = Math.abs(coefficients[i])
|
|
160
|
+
if (a > maxAmplitude) maxAmplitude = a
|
|
222
161
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const currentBfu = heapBfuIndices[0]
|
|
227
|
-
const currentWordLength = wordLengthAllocation[currentBfu]
|
|
228
|
-
|
|
229
|
-
// Skip BFUs that have reached maximum quantization precision
|
|
230
|
-
if (currentWordLength >= MAX_WORD_LENGTH_INDEX) {
|
|
231
|
-
popRoot(heapBfuIndices, heapPriorities)
|
|
232
|
-
continue
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Calculate bit cost for upgrading this BFU's quantization
|
|
236
|
-
const bfuSize = bfuSizes[currentBfu]
|
|
237
|
-
const upgradeCost =
|
|
238
|
-
WORD_LENGTH_BITS[currentWordLength + 1] * bfuSize -
|
|
239
|
-
WORD_LENGTH_BITS[currentWordLength] * bfuSize
|
|
240
|
-
|
|
241
|
-
if (upgradeCost > remainingBits) {
|
|
242
|
-
popRoot(heapBfuIndices, heapPriorities)
|
|
243
|
-
continue
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Perform the upgrade
|
|
247
|
-
remainingBits -= upgradeCost
|
|
248
|
-
wordLengthAllocation[currentBfu] = currentWordLength + 1
|
|
249
|
-
heapPriorities[0] += DISTORTION_DELTA_DB[currentWordLength]
|
|
250
|
-
siftDown(heapBfuIndices, heapPriorities, 0)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return wordLengthAllocation
|
|
162
|
+
if (maxAmplitude === 0) return 0
|
|
163
|
+
const index = Math.ceil(3 * (Math.log2(maxAmplitude) + 21))
|
|
164
|
+
return Math.max(0, Math.min(63, index))
|
|
254
165
|
}
|
|
255
166
|
|
|
256
167
|
/**
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
168
|
+
* Removes the root element from a max-heap and maintains heap property.
|
|
169
|
+
*
|
|
170
|
+
* This function efficiently removes the maximum priority element from the heap
|
|
171
|
+
* by replacing it with the last element and then restoring the heap property
|
|
172
|
+
* through sifting down.
|
|
173
|
+
*
|
|
174
|
+
* @param {Array<number>} heapIndices
|
|
175
|
+
* @param {Array<number>} heapPriorities
|
|
260
176
|
*/
|
|
261
177
|
function popRoot(heapIndices, heapPriorities) {
|
|
262
|
-
const
|
|
263
|
-
heapIndices[0] = heapIndices[
|
|
264
|
-
heapPriorities[0] = heapPriorities[
|
|
178
|
+
const last = heapIndices.length - 1
|
|
179
|
+
heapIndices[0] = heapIndices[last]
|
|
180
|
+
heapPriorities[0] = heapPriorities[last]
|
|
265
181
|
heapIndices.pop()
|
|
266
182
|
heapPriorities.pop()
|
|
267
183
|
if (heapIndices.length) siftDown(heapIndices, heapPriorities, 0)
|
|
268
184
|
}
|
|
269
185
|
|
|
270
186
|
/**
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
187
|
+
* Restores max-heap property by sifting an element down from a given position.
|
|
188
|
+
*
|
|
189
|
+
* This function maintains the heap invariant where parent nodes have higher
|
|
190
|
+
* priority values than their children. It compares the element at startIndex
|
|
191
|
+
* with its children and swaps with the larger child until the heap property
|
|
192
|
+
* is satisfied, or it reaches a leaf position.
|
|
193
|
+
*
|
|
194
|
+
* @param {Array<number>} heapIndices
|
|
195
|
+
* @param {Array<number>} heapPriorities
|
|
196
|
+
* @param {number} startIndex
|
|
275
197
|
*/
|
|
276
198
|
function siftDown(heapIndices, heapPriorities, startIndex) {
|
|
277
199
|
const heapSize = heapIndices.length
|
|
278
|
-
let
|
|
279
|
-
const
|
|
280
|
-
const
|
|
200
|
+
let i = startIndex
|
|
201
|
+
const idxVal = heapIndices[i]
|
|
202
|
+
const prVal = heapPriorities[i]
|
|
281
203
|
|
|
282
204
|
while (true) {
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
let
|
|
286
|
-
let
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
heapPriorities[leftChildIndex] > maxPriority
|
|
292
|
-
) {
|
|
293
|
-
maxIndex = leftChildIndex
|
|
294
|
-
maxPriority = heapPriorities[leftChildIndex]
|
|
205
|
+
const l = (i << 1) + 1
|
|
206
|
+
const r = l + 1
|
|
207
|
+
let maxI = i
|
|
208
|
+
let maxP = prVal
|
|
209
|
+
|
|
210
|
+
if (l < heapSize && heapPriorities[l] > maxP) {
|
|
211
|
+
maxI = l
|
|
212
|
+
maxP = heapPriorities[l]
|
|
295
213
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (
|
|
299
|
-
rightChildIndex < heapSize &&
|
|
300
|
-
heapPriorities[rightChildIndex] > maxPriority
|
|
301
|
-
) {
|
|
302
|
-
maxIndex = rightChildIndex
|
|
214
|
+
if (r < heapSize && heapPriorities[r] > maxP) {
|
|
215
|
+
maxI = r
|
|
303
216
|
}
|
|
217
|
+
if (maxI === i) break
|
|
304
218
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
// Move the higher priority child up
|
|
309
|
-
heapIndices[currentIndex] = heapIndices[maxIndex]
|
|
310
|
-
heapPriorities[currentIndex] = heapPriorities[maxIndex]
|
|
311
|
-
currentIndex = maxIndex
|
|
219
|
+
heapIndices[i] = heapIndices[maxI]
|
|
220
|
+
heapPriorities[i] = heapPriorities[maxI]
|
|
221
|
+
i = maxI
|
|
312
222
|
}
|
|
313
223
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
heapPriorities[currentIndex] = originalPriorityValue
|
|
224
|
+
heapIndices[i] = idxVal
|
|
225
|
+
heapPriorities[i] = prVal
|
|
317
226
|
}
|