@core-workspace/infoflow-openclaw-plugin 2026.3.9 → 2026.3.27-beta.0
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/CHANGELOG.md +91 -0
- package/CLAUDE.md +135 -0
- package/COLLABORATION_REPORT.md +209 -0
- package/PROJECT_GUIDE.md +355 -0
- package/README.md +158 -66
- package/docs/dev-guide.md +63 -50
- package/docs/qa-feature-list.md +452 -0
- package/docs/webhook-guide.md +178 -0
- package/index.ts +28 -2
- package/openclaw.plugin.json +131 -21
- package/package.json +16 -3
- package/scripts/deploy.sh +66 -7
- package/scripts/postinstall.cjs +80 -0
- package/skills/infoflow-dev/SKILL.md +2 -2
- package/skills/infoflow-dev/references/api.md +1 -1
- package/src/adapter/inbound/webhook-parser.ts +27 -5
- package/src/adapter/inbound/ws-receiver.ts +304 -43
- package/src/adapter/outbound/markdown-local-images.ts +80 -0
- package/src/adapter/outbound/reply-dispatcher.ts +146 -65
- package/src/adapter/outbound/target-resolver.ts +4 -3
- package/src/channel/accounts.ts +97 -22
- package/src/channel/channel.ts +456 -12
- package/src/channel/media.ts +20 -6
- package/src/channel/monitor.ts +8 -3
- package/src/channel/outbound.ts +358 -21
- package/src/channel/streaming.ts +740 -0
- package/src/commands/changelog.ts +80 -0
- package/src/commands/doctor.ts +545 -0
- package/src/commands/logs.ts +449 -0
- package/src/commands/version.ts +20 -0
- package/src/compat/openclaw-sdk.ts +218 -0
- package/src/handler/message-handler.ts +673 -166
- package/src/logging.ts +1 -1
- package/src/runtime.ts +1 -1
- package/src/security/dm-policy.ts +1 -4
- package/src/security/group-policy.ts +174 -51
- package/src/tools/actions/index.ts +15 -13
- package/src/tools/cron/relay.ts +1154 -0
- package/src/tools/hooks/index.ts +13 -1
- package/src/tools/index.ts +714 -32
- package/src/types.ts +144 -25
- package/src/utils/audio/g722/dct_tables.ts +381 -0
- package/src/utils/audio/g722/decoder.ts +919 -0
- package/src/utils/audio/g722/defs.ts +105 -0
- package/src/utils/audio/g722/hd-parser.ts +247 -0
- package/src/utils/audio/g722/huff_tables.ts +240 -0
- package/src/utils/audio/g722/index.ts +78 -0
- package/src/utils/audio/g722/output_decoded.pcm +0 -0
- package/src/utils/audio/g722/output_decoded.wav +0 -0
- package/src/utils/audio/g722/tables.ts +173 -0
- package/src/utils/audio/g722/test_api.ts +31 -0
- package/src/utils/audio/g722/test_voice.hd +0 -0
- package/src/utils/bos/im-bos-client.ts +219 -0
- package/src/utils/group-agent-cache.ts +142 -0
- package/src/utils/token-adapter.ts +120 -51
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* G.722.1 / G.722.1 Annex C Decoder Implementation
|
|
3
|
+
* 基于 ITU-T G.722.1 Annex C 浮点源码移植到 TypeScript
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
G722Type,
|
|
8
|
+
G722Decoder,
|
|
9
|
+
DecInfo,
|
|
10
|
+
MAX_DCT_SIZE,
|
|
11
|
+
MAX_FRAME_SIZE,
|
|
12
|
+
FRAME_SIZE,
|
|
13
|
+
MAX_NUM_REGIONS,
|
|
14
|
+
NUM_REGIONS,
|
|
15
|
+
NUM_RATE_CONTROL_BITS,
|
|
16
|
+
NUM_RATE_CONTROL_POSSIBILITIES,
|
|
17
|
+
MAX_NUM_RATE_CONTROL_BITS,
|
|
18
|
+
MAX_NUM_RATE_CONTROL_POSSIBILITIES,
|
|
19
|
+
INTEROP_RMLT_SCALE_FACTOR_7,
|
|
20
|
+
INTEROP_RMLT_SCALE_FACTOR_14,
|
|
21
|
+
ESF_ADJUSTMENT_TO_RMS_INDEX,
|
|
22
|
+
NUM_CATEGORIES,
|
|
23
|
+
REGION_POWER_TABLE_NUM_NEGATIVES,
|
|
24
|
+
MAX_VECTOR_DIMENSION
|
|
25
|
+
} from './defs.js';
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
g722Window7kHz,
|
|
29
|
+
g722Window14kHz,
|
|
30
|
+
regionStandardDeviationTable,
|
|
31
|
+
vectorDimension,
|
|
32
|
+
numberOfVectors,
|
|
33
|
+
maxBin,
|
|
34
|
+
maxBinPlusOneInverse,
|
|
35
|
+
expectedBitsTable,
|
|
36
|
+
regionSize,
|
|
37
|
+
mltQuantCentroid
|
|
38
|
+
} from './tables.js';
|
|
39
|
+
|
|
40
|
+
import { differentialRegionPowerDecoderTree, tableOfDecoderTables } from './huff_tables.js';
|
|
41
|
+
import { dctCore320, dctCore640, cosMsinTables } from './dct_tables.js';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 打开/创建解码器
|
|
45
|
+
*/
|
|
46
|
+
export function g722DecOpen(codecType: G722Type): G722Decoder | null {
|
|
47
|
+
const decoder: G722Decoder = {
|
|
48
|
+
frameCnt: 0,
|
|
49
|
+
bitRate: 0,
|
|
50
|
+
frameSize: 0,
|
|
51
|
+
bandwidth: 0,
|
|
52
|
+
numberOfRegions: 0,
|
|
53
|
+
numberOfBitsPerFrame: 0,
|
|
54
|
+
numberOfWords16PerFrame: 0,
|
|
55
|
+
rmltScaleFactor: 0,
|
|
56
|
+
window: new Float32Array(0),
|
|
57
|
+
oldSamples: new Float32Array(MAX_DCT_SIZE >> 1),
|
|
58
|
+
oldDecoderMltCoefs: new Float32Array(MAX_DCT_SIZE),
|
|
59
|
+
decoderMltCoefs: new Float32Array(MAX_DCT_SIZE),
|
|
60
|
+
floatOutSamples: new Float32Array(MAX_DCT_SIZE),
|
|
61
|
+
numRateControlBits: 0,
|
|
62
|
+
numRateControlPossibilities: 0,
|
|
63
|
+
decInfo: {
|
|
64
|
+
numberOfBitsLeft: 0,
|
|
65
|
+
nextBit: 0,
|
|
66
|
+
codeWord: 0,
|
|
67
|
+
codeBitCount: 0,
|
|
68
|
+
codeWordIndex: 0,
|
|
69
|
+
codeWords: new Int16Array(0)
|
|
70
|
+
},
|
|
71
|
+
random: { b0: 1, b1: 1, b2: 1, b3: 1 },
|
|
72
|
+
bufferA: new Float32Array(MAX_DCT_SIZE),
|
|
73
|
+
bufferB: new Float32Array(MAX_DCT_SIZE),
|
|
74
|
+
maxRateCategories: new Int32Array(MAX_NUM_REGIONS),
|
|
75
|
+
minRateCategories: new Int32Array(MAX_NUM_REGIONS),
|
|
76
|
+
tempCategoryBalances: new Int32Array(2 * MAX_NUM_RATE_CONTROL_POSSIBILITIES)
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// 根据编解码器类型设置参数
|
|
80
|
+
switch (codecType) {
|
|
81
|
+
case G722Type.G722_1C_24:
|
|
82
|
+
decoder.bandwidth = 14000;
|
|
83
|
+
decoder.bitRate = 24000;
|
|
84
|
+
break;
|
|
85
|
+
case G722Type.G722_1C_32:
|
|
86
|
+
decoder.bandwidth = 14000;
|
|
87
|
+
decoder.bitRate = 32000;
|
|
88
|
+
break;
|
|
89
|
+
case G722Type.G722_1C_48:
|
|
90
|
+
decoder.bandwidth = 14000;
|
|
91
|
+
decoder.bitRate = 48000;
|
|
92
|
+
break;
|
|
93
|
+
case G722Type.G722_1_16:
|
|
94
|
+
decoder.bandwidth = 7000;
|
|
95
|
+
decoder.bitRate = 16000;
|
|
96
|
+
break;
|
|
97
|
+
case G722Type.G722_1_24:
|
|
98
|
+
decoder.bandwidth = 7000;
|
|
99
|
+
decoder.bitRate = 24000;
|
|
100
|
+
break;
|
|
101
|
+
case G722Type.G722_1_32:
|
|
102
|
+
decoder.bandwidth = 7000;
|
|
103
|
+
decoder.bitRate = 32000;
|
|
104
|
+
break;
|
|
105
|
+
default:
|
|
106
|
+
console.error('Unknown G722 decoder type!');
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 设置帧大小和区域数量
|
|
111
|
+
if (decoder.bandwidth === 7000) {
|
|
112
|
+
decoder.frameSize = FRAME_SIZE;
|
|
113
|
+
decoder.numberOfRegions = NUM_REGIONS;
|
|
114
|
+
decoder.numRateControlBits = NUM_RATE_CONTROL_BITS;
|
|
115
|
+
decoder.numRateControlPossibilities = NUM_RATE_CONTROL_POSSIBILITIES;
|
|
116
|
+
decoder.rmltScaleFactor = Math.floor(INTEROP_RMLT_SCALE_FACTOR_7);
|
|
117
|
+
decoder.window = g722Window7kHz;
|
|
118
|
+
} else {
|
|
119
|
+
decoder.frameSize = MAX_FRAME_SIZE;
|
|
120
|
+
decoder.numberOfRegions = MAX_NUM_REGIONS;
|
|
121
|
+
decoder.numRateControlBits = MAX_NUM_RATE_CONTROL_BITS;
|
|
122
|
+
decoder.numRateControlPossibilities = MAX_NUM_RATE_CONTROL_POSSIBILITIES;
|
|
123
|
+
decoder.rmltScaleFactor = Math.floor(INTEROP_RMLT_SCALE_FACTOR_14);
|
|
124
|
+
decoder.window = g722Window14kHz;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
decoder.numberOfBitsPerFrame = decoder.bitRate / 50;
|
|
128
|
+
decoder.numberOfWords16PerFrame = (decoder.bitRate / 50) >> 4;
|
|
129
|
+
|
|
130
|
+
return decoder;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 获取下一个比特
|
|
135
|
+
*/
|
|
136
|
+
function getNextBit(decInfo: DecInfo): number {
|
|
137
|
+
if (decInfo.codeBitCount === 0) {
|
|
138
|
+
decInfo.codeWord = decInfo.codeWords[decInfo.codeWordIndex++];
|
|
139
|
+
decInfo.codeBitCount = 16;
|
|
140
|
+
}
|
|
141
|
+
decInfo.codeBitCount--;
|
|
142
|
+
decInfo.nextBit = (decInfo.codeWord >> decInfo.codeBitCount) & 1;
|
|
143
|
+
return decInfo.nextBit;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 解码功率包络
|
|
148
|
+
*/
|
|
149
|
+
function decodeEnvelope(
|
|
150
|
+
decInfo: DecInfo,
|
|
151
|
+
numberOfRegions: number,
|
|
152
|
+
decoderRegionStandardDeviation: Float32Array,
|
|
153
|
+
absoluteRegionPowerIndex: Int32Array
|
|
154
|
+
): void {
|
|
155
|
+
const differentialRegionPowerIndex = new Int32Array(MAX_NUM_REGIONS);
|
|
156
|
+
|
|
157
|
+
// 恢复第一个区域的功率索引
|
|
158
|
+
let index = 0;
|
|
159
|
+
for (let i = 0; i < 5; i++) {
|
|
160
|
+
getNextBit(decInfo);
|
|
161
|
+
index <<= 1;
|
|
162
|
+
index += decInfo.nextBit;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
differentialRegionPowerIndex[0] = index - ESF_ADJUSTMENT_TO_RMS_INDEX;
|
|
166
|
+
decInfo.numberOfBitsLeft -= 5;
|
|
167
|
+
|
|
168
|
+
// 恢复后续区域的功率索引
|
|
169
|
+
for (let region = 1; region < numberOfRegions; region++) {
|
|
170
|
+
index = 0;
|
|
171
|
+
let bitCount = 0;
|
|
172
|
+
do {
|
|
173
|
+
// 检查索引有效性
|
|
174
|
+
if (index < 0 || index >= differentialRegionPowerDecoderTree[region].length) {
|
|
175
|
+
index = -12; // 默认值
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getNextBit(decInfo);
|
|
180
|
+
if (decInfo.nextBit === 0) {
|
|
181
|
+
index = differentialRegionPowerDecoderTree[region][index][0];
|
|
182
|
+
} else {
|
|
183
|
+
index = differentialRegionPowerDecoderTree[region][index][1];
|
|
184
|
+
}
|
|
185
|
+
decInfo.numberOfBitsLeft--;
|
|
186
|
+
bitCount++;
|
|
187
|
+
// 防止无限循环
|
|
188
|
+
if (bitCount > 20) {
|
|
189
|
+
index = -12; // 默认值
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
} while (index > 0);
|
|
193
|
+
differentialRegionPowerIndex[region] = -index;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 重建绝对功率索引
|
|
197
|
+
absoluteRegionPowerIndex[0] = differentialRegionPowerIndex[0];
|
|
198
|
+
for (let region = 1; region < numberOfRegions; region++) {
|
|
199
|
+
absoluteRegionPowerIndex[region] =
|
|
200
|
+
absoluteRegionPowerIndex[region - 1] +
|
|
201
|
+
differentialRegionPowerIndex[region] +
|
|
202
|
+
(-12); // DRP_DIFF_MIN
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 重建区域标准差
|
|
206
|
+
for (let region = 0; region < numberOfRegions; region++) {
|
|
207
|
+
const i = absoluteRegionPowerIndex[region] + REGION_POWER_TABLE_NUM_NEGATIVES;
|
|
208
|
+
if (i >= 0 && i < regionStandardDeviationTable.length) {
|
|
209
|
+
decoderRegionStandardDeviation[region] = regionStandardDeviationTable[i];
|
|
210
|
+
} else {
|
|
211
|
+
// 越界处理
|
|
212
|
+
decoderRegionStandardDeviation[region] = 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* 速率调整类别
|
|
219
|
+
*/
|
|
220
|
+
function rateAdjustCategories(
|
|
221
|
+
rateControl: number,
|
|
222
|
+
decoderPowerCategories: Int32Array,
|
|
223
|
+
decoderCategoryBalances: Int32Array
|
|
224
|
+
): void {
|
|
225
|
+
let i = 0;
|
|
226
|
+
while (rateControl > 0) {
|
|
227
|
+
const region = decoderCategoryBalances[i++];
|
|
228
|
+
decoderPowerCategories[region]++;
|
|
229
|
+
rateControl--;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* 分类函数
|
|
235
|
+
*/
|
|
236
|
+
function categorize(
|
|
237
|
+
numberOfRegions: number,
|
|
238
|
+
numRateControlPossibilities: number,
|
|
239
|
+
numberOfAvailableBits: number,
|
|
240
|
+
rmsIndex: Int32Array,
|
|
241
|
+
powerCategories: Int32Array,
|
|
242
|
+
categoryBalances: Int32Array,
|
|
243
|
+
maxRateCategories: Int32Array,
|
|
244
|
+
minRateCategories: Int32Array,
|
|
245
|
+
tempCategoryBalances: Int32Array
|
|
246
|
+
): void {
|
|
247
|
+
// 在较高比特率下进行补偿
|
|
248
|
+
if (numberOfRegions === NUM_REGIONS && numberOfAvailableBits > FRAME_SIZE) {
|
|
249
|
+
numberOfAvailableBits = FRAME_SIZE + (((numberOfAvailableBits - FRAME_SIZE) * 5) >> 3);
|
|
250
|
+
} else if (numberOfRegions === MAX_NUM_REGIONS && numberOfAvailableBits > MAX_FRAME_SIZE) {
|
|
251
|
+
numberOfAvailableBits = MAX_FRAME_SIZE + (((numberOfAvailableBits - MAX_FRAME_SIZE) * 5) >> 3);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let offset = -32;
|
|
255
|
+
let delta = 32;
|
|
256
|
+
|
|
257
|
+
// 二分搜索找到最佳偏移
|
|
258
|
+
do {
|
|
259
|
+
const testOffset = offset + delta;
|
|
260
|
+
let expectedNumberOfCodeBits = 0;
|
|
261
|
+
|
|
262
|
+
for (let region = 0; region < numberOfRegions; region += 2) {
|
|
263
|
+
let j0 = (testOffset - rmsIndex[region]) >> 1;
|
|
264
|
+
let j1 = (testOffset - rmsIndex[region + 1]) >> 1;
|
|
265
|
+
|
|
266
|
+
j0 = Math.max(0, Math.min(j0, NUM_CATEGORIES - 1));
|
|
267
|
+
j1 = Math.max(0, Math.min(j1, NUM_CATEGORIES - 1));
|
|
268
|
+
|
|
269
|
+
powerCategories[region] = j0;
|
|
270
|
+
powerCategories[region + 1] = j1;
|
|
271
|
+
expectedNumberOfCodeBits += expectedBitsTable[j0] + expectedBitsTable[j1];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (expectedNumberOfCodeBits >= numberOfAvailableBits - 32) {
|
|
275
|
+
offset = testOffset;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
delta >>= 1;
|
|
279
|
+
} while (delta > 0);
|
|
280
|
+
|
|
281
|
+
// 使用最终偏移重新计算类别
|
|
282
|
+
let expectedNumberOfCodeBits = 0;
|
|
283
|
+
for (let region = 0; region < numberOfRegions; region += 2) {
|
|
284
|
+
let j0 = (offset - rmsIndex[region]) >> 1;
|
|
285
|
+
let j1 = (offset - rmsIndex[region + 1]) >> 1;
|
|
286
|
+
|
|
287
|
+
j0 = Math.max(0, Math.min(j0, NUM_CATEGORIES - 1));
|
|
288
|
+
j1 = Math.max(0, Math.min(j1, NUM_CATEGORIES - 1));
|
|
289
|
+
|
|
290
|
+
powerCategories[region] = j0;
|
|
291
|
+
powerCategories[region + 1] = j1;
|
|
292
|
+
expectedNumberOfCodeBits += expectedBitsTable[j0] + expectedBitsTable[j1];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// 初始化最大/最小速率类别
|
|
296
|
+
for (let region = 0; region < numberOfRegions; region++) {
|
|
297
|
+
maxRateCategories[region] = powerCategories[region];
|
|
298
|
+
minRateCategories[region] = powerCategories[region];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
let max = expectedNumberOfCodeBits;
|
|
302
|
+
let min = expectedNumberOfCodeBits;
|
|
303
|
+
let maxRatePointer = numRateControlPossibilities;
|
|
304
|
+
let minRatePointer = numRateControlPossibilities;
|
|
305
|
+
|
|
306
|
+
// 计算类别平衡
|
|
307
|
+
for (let j = 0; j < numRateControlPossibilities - 1; j++) {
|
|
308
|
+
if (max + min <= numberOfAvailableBits * 2) {
|
|
309
|
+
let rawMin = 99;
|
|
310
|
+
let rawMinIndex = 0;
|
|
311
|
+
|
|
312
|
+
for (let region = 0; region < numberOfRegions; region++) {
|
|
313
|
+
if (maxRateCategories[region] > 0) {
|
|
314
|
+
const itemp0 = offset - rmsIndex[region] - (maxRateCategories[region] << 1);
|
|
315
|
+
if (itemp0 < rawMin) {
|
|
316
|
+
rawMin = itemp0;
|
|
317
|
+
rawMinIndex = region;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
maxRatePointer--;
|
|
323
|
+
tempCategoryBalances[maxRatePointer] = rawMinIndex;
|
|
324
|
+
|
|
325
|
+
max -= expectedBitsTable[maxRateCategories[rawMinIndex]];
|
|
326
|
+
maxRateCategories[rawMinIndex]--;
|
|
327
|
+
max += expectedBitsTable[maxRateCategories[rawMinIndex]];
|
|
328
|
+
} else {
|
|
329
|
+
let rawMax = -99;
|
|
330
|
+
let rawMaxIndex = 0;
|
|
331
|
+
|
|
332
|
+
for (let region = numberOfRegions - 1; region >= 0; region--) {
|
|
333
|
+
if (minRateCategories[region] < NUM_CATEGORIES - 1) {
|
|
334
|
+
const itemp0 = offset - rmsIndex[region] - (minRateCategories[region] << 1);
|
|
335
|
+
if (itemp0 > rawMax) {
|
|
336
|
+
rawMax = itemp0;
|
|
337
|
+
rawMaxIndex = region;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
tempCategoryBalances[minRatePointer] = rawMaxIndex;
|
|
343
|
+
minRatePointer++;
|
|
344
|
+
|
|
345
|
+
min -= expectedBitsTable[minRateCategories[rawMaxIndex]];
|
|
346
|
+
minRateCategories[rawMaxIndex]++;
|
|
347
|
+
min += expectedBitsTable[minRateCategories[rawMaxIndex]];
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for (let region = 0; region < numberOfRegions; region++) {
|
|
352
|
+
powerCategories[region] = maxRateCategories[region];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
for (let j = 0; j < numRateControlPossibilities - 1; j++) {
|
|
356
|
+
categoryBalances[j] = tempCategoryBalances[maxRatePointer++];
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* 索引转数组
|
|
362
|
+
*/
|
|
363
|
+
function indexToArray(index: number, array: Int32Array, category: number): number {
|
|
364
|
+
let numberOfNonZero = 0;
|
|
365
|
+
let p = index;
|
|
366
|
+
const maxBinPlusOne = maxBin[category] + 1;
|
|
367
|
+
const inverseOfMaxBinPlusOne = maxBinPlusOneInverse[category];
|
|
368
|
+
|
|
369
|
+
for (let j = vectorDimension[category] - 1; j >= 0; j--) {
|
|
370
|
+
const q = (p * inverseOfMaxBinPlusOne) >> 15;
|
|
371
|
+
array[j] = p - q * maxBinPlusOne;
|
|
372
|
+
p = q;
|
|
373
|
+
if (array[j] !== 0) {
|
|
374
|
+
numberOfNonZero++;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return numberOfNonZero;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* 获取随机数
|
|
383
|
+
*/
|
|
384
|
+
function getRand(random: { b0: number; b1: number; b2: number; b3: number }): number {
|
|
385
|
+
let randomWord = random.b0 + random.b3;
|
|
386
|
+
if ((randomWord & 32768) !== 0) randomWord++;
|
|
387
|
+
random.b3 = random.b2;
|
|
388
|
+
random.b2 = random.b1;
|
|
389
|
+
random.b1 = random.b0;
|
|
390
|
+
random.b0 = randomWord;
|
|
391
|
+
return randomWord;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* 解码向量量化的MLT索引
|
|
396
|
+
*/
|
|
397
|
+
function decodeVectorQuantizedMltIndices(
|
|
398
|
+
decoder: G722Decoder,
|
|
399
|
+
numberOfRegions: number,
|
|
400
|
+
decoderRegionStandardDeviation: Float32Array,
|
|
401
|
+
decoderPowerCategories: Int32Array,
|
|
402
|
+
decoderMltCoefs: Float32Array,
|
|
403
|
+
rmltScaleFactor: number
|
|
404
|
+
): void {
|
|
405
|
+
const decInfo = decoder.decInfo;
|
|
406
|
+
const random = decoder.random;
|
|
407
|
+
const k = new Int32Array(MAX_VECTOR_DIMENSION);
|
|
408
|
+
let ranOutOfBitsFlag = 0;
|
|
409
|
+
|
|
410
|
+
for (let region = 0; region < numberOfRegions; region++) {
|
|
411
|
+
const category = decoderPowerCategories[region];
|
|
412
|
+
let decoderMltIndex = region * regionSize;
|
|
413
|
+
const standardDeviation = decoderRegionStandardDeviation[region];
|
|
414
|
+
|
|
415
|
+
if (category < NUM_CATEGORIES - 1) {
|
|
416
|
+
const decoderTablePtr = tableOfDecoderTables[category];
|
|
417
|
+
|
|
418
|
+
// 检查解码表是否存在
|
|
419
|
+
if (!decoderTablePtr || decoderTablePtr.length === 0) {
|
|
420
|
+
// 如果表不存在,直接使用噪声填充
|
|
421
|
+
const noifillpos = standardDeviation * 0.70711;
|
|
422
|
+
const noifillneg = -noifillpos;
|
|
423
|
+
let randomWord = getRand(random);
|
|
424
|
+
for (let j = 0; j < regionSize; j++) {
|
|
425
|
+
if (j % 16 === 0 && j > 0) randomWord = getRand(random);
|
|
426
|
+
const temp1 = (randomWord & 1) === 0 ? noifillneg : noifillpos;
|
|
427
|
+
decoderMltCoefs[decoderMltIndex++] = temp1 * rmltScaleFactor;
|
|
428
|
+
randomWord >>= 1;
|
|
429
|
+
}
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const vecDim = vectorDimension[category];
|
|
434
|
+
const numVecs = numberOfVectors[category];
|
|
435
|
+
|
|
436
|
+
for (let n = 0; n < numVecs; n++) {
|
|
437
|
+
let index = 0;
|
|
438
|
+
let bitCount = 0;
|
|
439
|
+
const maxBits = 32; // 安全限制:防止无限循环
|
|
440
|
+
do {
|
|
441
|
+
if (decInfo.numberOfBitsLeft <= 0) {
|
|
442
|
+
ranOutOfBitsFlag = 1;
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
if (bitCount++ >= maxBits) {
|
|
446
|
+
// 解码失败,跳过此区域
|
|
447
|
+
ranOutOfBitsFlag = 1;
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
getNextBit(decInfo);
|
|
452
|
+
if (index >= decoderTablePtr.length) {
|
|
453
|
+
// 索引越界,解码错误
|
|
454
|
+
ranOutOfBitsFlag = 1;
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
if (decInfo.nextBit === 0) {
|
|
458
|
+
index = decoderTablePtr[index][0];
|
|
459
|
+
} else {
|
|
460
|
+
index = decoderTablePtr[index][1];
|
|
461
|
+
}
|
|
462
|
+
decInfo.numberOfBitsLeft--;
|
|
463
|
+
} while (index > 0);
|
|
464
|
+
|
|
465
|
+
if (ranOutOfBitsFlag === 1) break;
|
|
466
|
+
index = -index;
|
|
467
|
+
const numSignBits = indexToArray(index, k, category);
|
|
468
|
+
|
|
469
|
+
if (decInfo.numberOfBitsLeft >= numSignBits) {
|
|
470
|
+
let signsIndex = 0;
|
|
471
|
+
if (numSignBits !== 0) {
|
|
472
|
+
for (let j = 0; j < numSignBits; j++) {
|
|
473
|
+
getNextBit(decInfo);
|
|
474
|
+
signsIndex <<= 1;
|
|
475
|
+
signsIndex += decInfo.nextBit;
|
|
476
|
+
decInfo.numberOfBitsLeft--;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
let bit = 1 << (numSignBits - 1);
|
|
480
|
+
|
|
481
|
+
for (let j = 0; j < vecDim; j++) {
|
|
482
|
+
let decoderMltValue =
|
|
483
|
+
standardDeviation * mltQuantCentroid[category][k[j]] * rmltScaleFactor;
|
|
484
|
+
|
|
485
|
+
if (decoderMltValue !== 0) {
|
|
486
|
+
if ((signsIndex & bit) === 0) {
|
|
487
|
+
decoderMltValue *= -1;
|
|
488
|
+
}
|
|
489
|
+
bit >>= 1;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
decoderMltCoefs[decoderMltIndex++] = decoderMltValue;
|
|
493
|
+
}
|
|
494
|
+
} else {
|
|
495
|
+
ranOutOfBitsFlag = 1;
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (ranOutOfBitsFlag === 1) {
|
|
501
|
+
for (let j = region + 1; j < numberOfRegions; j++) {
|
|
502
|
+
decoderPowerCategories[j] = NUM_CATEGORIES - 1;
|
|
503
|
+
}
|
|
504
|
+
decoderMltIndex = region * regionSize;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// 噪声填充
|
|
509
|
+
if (category === NUM_CATEGORIES - 1) {
|
|
510
|
+
const noifillpos = standardDeviation * 0.70711;
|
|
511
|
+
const noifillneg = -noifillpos;
|
|
512
|
+
|
|
513
|
+
let randomWord = getRand(random);
|
|
514
|
+
for (let j = 0; j < 10; j++) {
|
|
515
|
+
const temp1 = (randomWord & 1) === 0 ? noifillneg : noifillpos;
|
|
516
|
+
decoderMltCoefs[decoderMltIndex++] = temp1 * rmltScaleFactor;
|
|
517
|
+
randomWord >>= 1;
|
|
518
|
+
}
|
|
519
|
+
randomWord = getRand(random);
|
|
520
|
+
for (let j = 0; j < 10; j++) {
|
|
521
|
+
const temp1 = (randomWord & 1) === 0 ? noifillneg : noifillpos;
|
|
522
|
+
decoderMltCoefs[decoderMltIndex++] = temp1 * rmltScaleFactor;
|
|
523
|
+
randomWord >>= 1;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (ranOutOfBitsFlag) {
|
|
529
|
+
decInfo.numberOfBitsLeft = -1;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// 简单的暴力DCT Type IV实现(用于验证)
|
|
534
|
+
function dctTypeIvSimple(input: Float32Array, output: Float32Array, dctLength: number): void {
|
|
535
|
+
// voipsdk的实现在dct_core矩阵中内置了 sqrt(2/N) 的缩放因子
|
|
536
|
+
const scale = Math.sqrt(2.0 / dctLength);
|
|
537
|
+
for (let k = 0; k < dctLength; k++) {
|
|
538
|
+
let sum = 0;
|
|
539
|
+
for (let n = 0; n < dctLength; n++) {
|
|
540
|
+
sum += input[n] * Math.cos(Math.PI * (n + 0.5) * (k + 0.5) / dctLength);
|
|
541
|
+
}
|
|
542
|
+
output[k] = sum * scale;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* DCT Type IV变换 - 使用简单暴力实现(调试用)
|
|
548
|
+
*/
|
|
549
|
+
function dctTypeIv(
|
|
550
|
+
input: Float32Array,
|
|
551
|
+
output: Float32Array,
|
|
552
|
+
dctLength: number,
|
|
553
|
+
bufferA: Float32Array,
|
|
554
|
+
bufferB: Float32Array
|
|
555
|
+
): void {
|
|
556
|
+
// 临时使用简单实现来验证
|
|
557
|
+
dctTypeIvSimple(input, output, dctLength);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* DCT Type IV变换 - 快速实现(原始)
|
|
562
|
+
*/
|
|
563
|
+
function dctTypeIvFast(
|
|
564
|
+
input: Float32Array,
|
|
565
|
+
output: Float32Array,
|
|
566
|
+
dctLength: number,
|
|
567
|
+
bufferA: Float32Array,
|
|
568
|
+
bufferB: Float32Array
|
|
569
|
+
): void {
|
|
570
|
+
const maxSetCountLog = dctLength === 640 ? 5 : 4;
|
|
571
|
+
const dctCorePtr = dctLength === 640 ? dctCore640 : dctCore320;
|
|
572
|
+
|
|
573
|
+
let inBuffer = input;
|
|
574
|
+
let outBuffer = bufferA;
|
|
575
|
+
let nextOutBuffer = bufferB;
|
|
576
|
+
|
|
577
|
+
// Sum/difference butterflies
|
|
578
|
+
for (let setCountLog = 0; setCountLog <= maxSetCountLog; setCountLog++) {
|
|
579
|
+
const setSpan = dctLength >> setCountLog;
|
|
580
|
+
const spanDiv20 = 1 << (maxSetCountLog - setCountLog);
|
|
581
|
+
const setCount = 1 << setCountLog;
|
|
582
|
+
let inPtrIndex = 0;
|
|
583
|
+
let nextOutBaseIndex = 0;
|
|
584
|
+
|
|
585
|
+
for (let setsLeft = setCount; setsLeft > 0; setsLeft--) {
|
|
586
|
+
let outPtrLowIndex = nextOutBaseIndex;
|
|
587
|
+
nextOutBaseIndex += setSpan;
|
|
588
|
+
let outPtrHighIndex = nextOutBaseIndex;
|
|
589
|
+
|
|
590
|
+
for (let i = 0; i < spanDiv20; i++) {
|
|
591
|
+
outPtrHighIndex -= 10;
|
|
592
|
+
|
|
593
|
+
for (let k = 0; k < 10; k++) {
|
|
594
|
+
const inValLow = inBuffer[inPtrIndex + k * 2];
|
|
595
|
+
const inValHigh = inBuffer[inPtrIndex + k * 2 + 1];
|
|
596
|
+
outBuffer[outPtrLowIndex + k] = inValLow + inValHigh;
|
|
597
|
+
outBuffer[outPtrHighIndex + 9 - k] = inValLow - inValHigh;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
inPtrIndex += 20;
|
|
601
|
+
outPtrLowIndex += 10;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
inBuffer = outBuffer;
|
|
606
|
+
outBuffer = nextOutBuffer;
|
|
607
|
+
nextOutBuffer = inBuffer;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// 10点变换
|
|
611
|
+
let fptr0Index = 0;
|
|
612
|
+
let bufferSwapIndex = 0;
|
|
613
|
+
const decadesCount = 2 << maxSetCountLog;
|
|
614
|
+
|
|
615
|
+
for (let decadesLeft = decadesCount; decadesLeft > 0; decadesLeft--) {
|
|
616
|
+
for (let row = 0; row < 10; row++) {
|
|
617
|
+
let sum = 0;
|
|
618
|
+
for (let col = 0; col < 10; col++) {
|
|
619
|
+
sum += inBuffer[fptr0Index + col] * dctCorePtr[row * 10 + col];
|
|
620
|
+
}
|
|
621
|
+
outBuffer[bufferSwapIndex + row] = sum;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
fptr0Index += 10;
|
|
625
|
+
bufferSwapIndex += 10;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// 交换缓冲区指针
|
|
629
|
+
inBuffer = outBuffer;
|
|
630
|
+
outBuffer = nextOutBuffer;
|
|
631
|
+
nextOutBuffer = inBuffer;
|
|
632
|
+
|
|
633
|
+
// Rotation butterflies
|
|
634
|
+
let tablePtrIndex = 0;
|
|
635
|
+
|
|
636
|
+
for (let setCountLog = maxSetCountLog; setCountLog >= 0; setCountLog--) {
|
|
637
|
+
const setSpan = dctLength >> setCountLog;
|
|
638
|
+
const spanDiv20 = 1 << (maxSetCountLog - setCountLog);
|
|
639
|
+
const setCount = 1 << setCountLog;
|
|
640
|
+
let nextInBaseIndex = 0;
|
|
641
|
+
let nextOutBaseIndex = 0;
|
|
642
|
+
|
|
643
|
+
const cosMsinPtr = cosMsinTables[tablePtrIndex];
|
|
644
|
+
|
|
645
|
+
for (let setsLeft = setCount; setsLeft > 0; setsLeft--) {
|
|
646
|
+
let inPtrLowIndex = nextInBaseIndex;
|
|
647
|
+
let inPtrHighIndex = inPtrLowIndex + (setSpan >> 1);
|
|
648
|
+
nextInBaseIndex += setSpan;
|
|
649
|
+
let outPtrLowIndex = nextOutBaseIndex;
|
|
650
|
+
nextOutBaseIndex += setSpan;
|
|
651
|
+
let outPtrHighIndex = nextOutBaseIndex;
|
|
652
|
+
let cosMsinIndex = 0;
|
|
653
|
+
|
|
654
|
+
for (let i = 0; i < spanDiv20; i++) {
|
|
655
|
+
outPtrHighIndex -= 10;
|
|
656
|
+
|
|
657
|
+
for (let k = 0; k < 10; k++) {
|
|
658
|
+
const cosVal = cosMsinPtr[cosMsinIndex + k].cosine;
|
|
659
|
+
const msinVal = cosMsinPtr[cosMsinIndex + k].minusSine;
|
|
660
|
+
const inLow = inBuffer[inPtrLowIndex + k];
|
|
661
|
+
const inHigh = inBuffer[inPtrHighIndex + k];
|
|
662
|
+
|
|
663
|
+
if (k % 2 === 0) {
|
|
664
|
+
// Even index: cos*low - msin*high, msin*low + cos*high
|
|
665
|
+
outBuffer[outPtrLowIndex + k] = cosVal * inLow - msinVal * inHigh;
|
|
666
|
+
outBuffer[outPtrHighIndex + 9 - k] = msinVal * inLow + cosVal * inHigh;
|
|
667
|
+
} else {
|
|
668
|
+
// Odd index: cos*low + msin*high, msin*low - cos*high
|
|
669
|
+
outBuffer[outPtrLowIndex + k] = cosVal * inLow + msinVal * inHigh;
|
|
670
|
+
outBuffer[outPtrHighIndex + 9 - k] = msinVal * inLow - cosVal * inHigh;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
cosMsinIndex += 10;
|
|
675
|
+
inPtrLowIndex += 10;
|
|
676
|
+
inPtrHighIndex += 10;
|
|
677
|
+
outPtrLowIndex += 10;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// 交换缓冲区
|
|
682
|
+
const tempBuffer = inBuffer;
|
|
683
|
+
inBuffer = outBuffer;
|
|
684
|
+
outBuffer = nextOutBuffer;
|
|
685
|
+
nextOutBuffer = tempBuffer;
|
|
686
|
+
|
|
687
|
+
tablePtrIndex++;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// 复制最终结果到输出
|
|
691
|
+
for (let i = 0; i < dctLength; i++) {
|
|
692
|
+
output[i] = inBuffer[i];
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* RMLT系数转换为采样
|
|
698
|
+
*/
|
|
699
|
+
function rmltCoefsToSamples(decoder: G722Decoder, coefs: Float32Array, outSamples: Float32Array): void {
|
|
700
|
+
const newSamples = new Float32Array(MAX_DCT_SIZE);
|
|
701
|
+
const dctSize = decoder.frameSize;
|
|
702
|
+
const halfDctSize = dctSize >> 1;
|
|
703
|
+
const pWindow = decoder.window;
|
|
704
|
+
const oldSamples = decoder.oldSamples;
|
|
705
|
+
|
|
706
|
+
// 执行逆DCT
|
|
707
|
+
dctTypeIv(coefs, newSamples, dctSize, decoder.bufferA, decoder.bufferB);
|
|
708
|
+
|
|
709
|
+
// 加窗和重叠相加
|
|
710
|
+
let outPtrIndex = 0;
|
|
711
|
+
let winNewIndex = 0;
|
|
712
|
+
let winOldIndex = halfDctSize - 4;
|
|
713
|
+
let oldPtrIndex = 0;
|
|
714
|
+
let newPtrIndex = halfDctSize - 4;
|
|
715
|
+
let oldPtr1Index = halfDctSize - 4;
|
|
716
|
+
let newPtr1Index = 0;
|
|
717
|
+
|
|
718
|
+
for (let valsLeft = halfDctSize; valsLeft > 0; valsLeft -= 4) {
|
|
719
|
+
const a0 = pWindow[winNewIndex] * newSamples[newPtrIndex + 3];
|
|
720
|
+
const a1 = pWindow[winNewIndex + 1] * newSamples[newPtrIndex + 2];
|
|
721
|
+
const a2 = pWindow[winNewIndex + 2] * newSamples[newPtrIndex + 1];
|
|
722
|
+
const a3 = pWindow[winNewIndex + 3] * newSamples[newPtrIndex];
|
|
723
|
+
|
|
724
|
+
const a4 = pWindow[winNewIndex + halfDctSize] * newSamples[newPtr1Index];
|
|
725
|
+
const a5 = pWindow[winNewIndex + halfDctSize + 1] * newSamples[newPtr1Index + 1];
|
|
726
|
+
const a6 = pWindow[winNewIndex + halfDctSize + 2] * newSamples[newPtr1Index + 2];
|
|
727
|
+
const a7 = pWindow[winNewIndex + halfDctSize + 3] * newSamples[newPtr1Index + 3];
|
|
728
|
+
|
|
729
|
+
const b0 = pWindow[winOldIndex + halfDctSize + 3] * oldSamples[oldPtrIndex];
|
|
730
|
+
const b1 = pWindow[winOldIndex + halfDctSize + 2] * oldSamples[oldPtrIndex + 1];
|
|
731
|
+
const b2 = pWindow[winOldIndex + halfDctSize + 1] * oldSamples[oldPtrIndex + 2];
|
|
732
|
+
const b3 = pWindow[winOldIndex + halfDctSize] * oldSamples[oldPtrIndex + 3];
|
|
733
|
+
|
|
734
|
+
const b4 = pWindow[winOldIndex + 3] * oldSamples[oldPtr1Index + 3];
|
|
735
|
+
const b5 = pWindow[winOldIndex + 2] * oldSamples[oldPtr1Index + 2];
|
|
736
|
+
const b6 = pWindow[winOldIndex + 1] * oldSamples[oldPtr1Index + 1];
|
|
737
|
+
const b7 = pWindow[winOldIndex] * oldSamples[oldPtr1Index];
|
|
738
|
+
|
|
739
|
+
outSamples[outPtrIndex] = a0 + b0;
|
|
740
|
+
outSamples[outPtrIndex + 1] = a1 + b1;
|
|
741
|
+
outSamples[outPtrIndex + 2] = a2 + b2;
|
|
742
|
+
outSamples[outPtrIndex + 3] = a3 + b3;
|
|
743
|
+
|
|
744
|
+
outSamples[outPtrIndex + halfDctSize] = a4 - b4;
|
|
745
|
+
outSamples[outPtrIndex + halfDctSize + 1] = a5 - b5;
|
|
746
|
+
outSamples[outPtrIndex + halfDctSize + 2] = a6 - b6;
|
|
747
|
+
outSamples[outPtrIndex + halfDctSize + 3] = a7 - b7;
|
|
748
|
+
|
|
749
|
+
outPtrIndex += 4;
|
|
750
|
+
winNewIndex += 4;
|
|
751
|
+
winOldIndex -= 4;
|
|
752
|
+
oldPtrIndex += 4;
|
|
753
|
+
newPtr1Index += 4;
|
|
754
|
+
newPtrIndex -= 4;
|
|
755
|
+
oldPtr1Index -= 4;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// 保存当前帧的后半部分供下一帧使用
|
|
759
|
+
oldSamples.set(newSamples.subarray(halfDctSize, dctSize), 0);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* 主解码函数
|
|
764
|
+
*/
|
|
765
|
+
function decoder(
|
|
766
|
+
hDecoder: G722Decoder,
|
|
767
|
+
bitstream: Int16Array,
|
|
768
|
+
decoderMltCoefs: Float32Array,
|
|
769
|
+
frameErrorFlag: number
|
|
770
|
+
): void {
|
|
771
|
+
const absoluteRegionPowerIndex = new Int32Array(MAX_NUM_REGIONS);
|
|
772
|
+
const decoderPowerCategories = new Int32Array(MAX_NUM_REGIONS);
|
|
773
|
+
const decoderCategoryBalances = new Int32Array(MAX_NUM_RATE_CONTROL_POSSIBILITIES - 1);
|
|
774
|
+
const decoderRegionStandardDeviation = new Float32Array(MAX_NUM_REGIONS);
|
|
775
|
+
|
|
776
|
+
const numberOfRegions = hDecoder.numberOfRegions;
|
|
777
|
+
const numberOfBitsPerFrame = hDecoder.numberOfBitsPerFrame;
|
|
778
|
+
const numberOfCoefs = hDecoder.frameSize;
|
|
779
|
+
const rmltScaleFactor = hDecoder.rmltScaleFactor;
|
|
780
|
+
const numRateControlBits = hDecoder.numRateControlBits;
|
|
781
|
+
const numRateControlPossibilities = hDecoder.numRateControlPossibilities;
|
|
782
|
+
|
|
783
|
+
const numberOfValidCoefs = numberOfRegions * regionSize;
|
|
784
|
+
|
|
785
|
+
if (frameErrorFlag === 0) {
|
|
786
|
+
const decInfo = hDecoder.decInfo;
|
|
787
|
+
|
|
788
|
+
decInfo.numberOfBitsLeft = numberOfBitsPerFrame;
|
|
789
|
+
decInfo.codeWords = bitstream;
|
|
790
|
+
decInfo.codeWordIndex = 0;
|
|
791
|
+
decInfo.codeBitCount = 0;
|
|
792
|
+
|
|
793
|
+
decodeEnvelope(decInfo, numberOfRegions, decoderRegionStandardDeviation, absoluteRegionPowerIndex);
|
|
794
|
+
|
|
795
|
+
let rateControl = 0;
|
|
796
|
+
for (let i = 0; i < numRateControlBits; i++) {
|
|
797
|
+
getNextBit(decInfo);
|
|
798
|
+
rateControl <<= 1;
|
|
799
|
+
rateControl += decInfo.nextBit;
|
|
800
|
+
}
|
|
801
|
+
decInfo.numberOfBitsLeft -= numRateControlBits;
|
|
802
|
+
|
|
803
|
+
categorize(
|
|
804
|
+
numberOfRegions,
|
|
805
|
+
numRateControlPossibilities,
|
|
806
|
+
decInfo.numberOfBitsLeft,
|
|
807
|
+
absoluteRegionPowerIndex,
|
|
808
|
+
decoderPowerCategories,
|
|
809
|
+
decoderCategoryBalances,
|
|
810
|
+
hDecoder.maxRateCategories,
|
|
811
|
+
hDecoder.minRateCategories,
|
|
812
|
+
hDecoder.tempCategoryBalances
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
rateAdjustCategories(rateControl, decoderPowerCategories, decoderCategoryBalances);
|
|
816
|
+
|
|
817
|
+
decodeVectorQuantizedMltIndices(
|
|
818
|
+
hDecoder,
|
|
819
|
+
numberOfRegions,
|
|
820
|
+
decoderRegionStandardDeviation,
|
|
821
|
+
decoderPowerCategories,
|
|
822
|
+
decoderMltCoefs,
|
|
823
|
+
rmltScaleFactor
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
// 检测比特流错误
|
|
827
|
+
if (decInfo.numberOfBitsLeft > 0) {
|
|
828
|
+
for (let i = 0; i < decInfo.numberOfBitsLeft; i++) {
|
|
829
|
+
getNextBit(decInfo);
|
|
830
|
+
if (decInfo.nextBit === 0) {
|
|
831
|
+
frameErrorFlag = 1;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
} else {
|
|
835
|
+
if (rateControl < numRateControlPossibilities - 1) {
|
|
836
|
+
if (decInfo.numberOfBitsLeft < 0) {
|
|
837
|
+
frameErrorFlag |= 2;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// 验证功率索引
|
|
843
|
+
for (let region = 0; region < numberOfRegions; region++) {
|
|
844
|
+
if (
|
|
845
|
+
absoluteRegionPowerIndex[region] + ESF_ADJUSTMENT_TO_RMS_INDEX > 31 ||
|
|
846
|
+
absoluteRegionPowerIndex[region] + ESF_ADJUSTMENT_TO_RMS_INDEX < -8
|
|
847
|
+
) {
|
|
848
|
+
frameErrorFlag |= 4;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// 错误隐藏
|
|
854
|
+
if (frameErrorFlag !== 0) {
|
|
855
|
+
decoderMltCoefs.set(hDecoder.oldDecoderMltCoefs.subarray(0, numberOfValidCoefs));
|
|
856
|
+
hDecoder.oldDecoderMltCoefs.fill(0, 0, numberOfValidCoefs);
|
|
857
|
+
} else {
|
|
858
|
+
hDecoder.oldDecoderMltCoefs.set(decoderMltCoefs.subarray(0, numberOfValidCoefs));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// 将频谱的高频部分置零
|
|
862
|
+
decoderMltCoefs.fill(0, numberOfValidCoefs, numberOfCoefs);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* 解码一帧
|
|
867
|
+
*/
|
|
868
|
+
export function g722DecDecode(
|
|
869
|
+
hG722Dec: G722Decoder,
|
|
870
|
+
inBytes: Uint8Array,
|
|
871
|
+
outputSample: Int16Array,
|
|
872
|
+
numInBytes: { value: number },
|
|
873
|
+
numOut: { value: number },
|
|
874
|
+
isGoodPkt: number
|
|
875
|
+
): void {
|
|
876
|
+
hG722Dec.frameCnt++;
|
|
877
|
+
|
|
878
|
+
// 将输入字节转换为16位字 (little-endian)
|
|
879
|
+
const numWords = Math.floor(inBytes.length / 2);
|
|
880
|
+
const inWords = new Int16Array(numWords);
|
|
881
|
+
for (let i = 0; i < numWords; i++) {
|
|
882
|
+
inWords[i] = (inBytes[i * 2 + 1] << 8) | inBytes[i * 2];
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
const decoderMltCoefs = hG722Dec.decoderMltCoefs;
|
|
886
|
+
const floatOutSamples = hG722Dec.floatOutSamples;
|
|
887
|
+
const frameSize = hG722Dec.frameSize;
|
|
888
|
+
|
|
889
|
+
// 解码MLT系数
|
|
890
|
+
decoder(hG722Dec, inWords, decoderMltCoefs, isGoodPkt ? 0 : 1);
|
|
891
|
+
|
|
892
|
+
// 将RMLT系数转换为输出采样
|
|
893
|
+
rmltCoefsToSamples(hG722Dec, decoderMltCoefs, floatOutSamples);
|
|
894
|
+
|
|
895
|
+
// 将浮点输出转换为16位整数输出
|
|
896
|
+
for (let i = 0; i < frameSize; i++) {
|
|
897
|
+
let ftemp0 = floatOutSamples[i];
|
|
898
|
+
|
|
899
|
+
if (ftemp0 >= 0.0) {
|
|
900
|
+
outputSample[i] = ftemp0 < 32767.0 ? Math.floor(ftemp0 + 0.5) : 32767;
|
|
901
|
+
} else {
|
|
902
|
+
outputSample[i] = ftemp0 > -32768.0 ? Math.floor(ftemp0 - 0.5) : -32768;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// ITU测试:清除最低2位
|
|
906
|
+
outputSample[i] &= 0xfffc;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
numInBytes.value = hG722Dec.numberOfWords16PerFrame << 1;
|
|
910
|
+
numOut.value = frameSize;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* 关闭解码器
|
|
915
|
+
*/
|
|
916
|
+
export function g722DecClose(hG722Dec: G722Decoder): void {
|
|
917
|
+
// TypeScript中不需要手动释放内存
|
|
918
|
+
// 此函数保留以保持API兼容性
|
|
919
|
+
}
|