app-starlock/star_lock/lib/talk/call/g711Encode.dart
2023-12-21 17:41:06 +08:00

70 lines
1.6 KiB
Dart

import 'dart:typed_data';
enum G711Type {
uLaw,
aLaw,
}
class G711Decoder {
Uint8List g711Encode(Uint8List pcmData, G711Type g711Type) {
List<int> g711Data = [];
for (int sample in pcmData) {
int sign = (sample < 0) ? 0x80 : 0;
int magnitude = (sample < 0) ? -sample : sample;
int exponent = 7;
while (magnitude < (1 << exponent) && exponent > 0) {
exponent--;
}
int mantissa = (magnitude >> (exponent - 4)) & 0x0F;
if (g711Type == G711Type.uLaw) {
// μ-law encoding
int value = ~(sign | ((exponent << 4) & 0x70) | (mantissa >> 4));
g711Data.add(value & 0xFF);
} else {
// A-law encoding
int value = sign | ((exponent << 4) & 0x70) | (mantissa >> 4);
g711Data.add(value & 0xFF);
}
}
return Uint8List.fromList(g711Data);
}
List<int> pcm16ToG711u(List<int> pcm16Data) {
List<int> g711uData = [];
for (int i = 0; i < pcm16Data.length; i += 2) {
int pcmSample = (pcm16Data[i + 1] << 8) | pcm16Data[i];
int g711Sample = pcmToG711u(pcmSample);
// 将 G.711 样本拆分成两个字节
g711uData.add(g711Sample & 0xFF);
g711uData.add((g711Sample >> 8) & 0xFF);
}
return g711uData;
}
int pcmToG711u(int pcmSample) {
const int MULAW_BIAS = 0x84;
const int CLIP = 32635;
// 剪裁 PCM 样本
if (pcmSample > CLIP) {
pcmSample = CLIP;
} else if (pcmSample < -CLIP) {
pcmSample = -CLIP;
}
// 增加偏置并取反
pcmSample += MULAW_BIAS;
pcmSample = ~pcmSample & 0xFF;
return pcmSample;
}
}