148 lines
4.1 KiB
Dart
Executable File

import 'dart:async';
import 'dart:math';
import 'package:flutter/services.dart';
class G711 {
List<int> _aLawTable = [
1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
];
Future<List<int>> readAssetFile(String assetPath) async {
final ByteData data = await rootBundle.load(assetPath);
final List<int> bytes = data.buffer.asUint8List();
return bytes;
}
List<int> encodeALaw(List<int> pcmSamples) {
final List<int> aLawSamples = [];
for (final sample in pcmSamples) {
// 将 16 位 PCM 样本归一化为 13 位有符号整数
int normalizedSample = sample >> 3;
// 获取样本的符号位
int sign = (normalizedSample & 0x8000) != 0 ? 0x80 : 0x00;
// 取绝对值
normalizedSample = normalizedSample.abs();
// 查找编码表中的段
int segment = _aLawTable[normalizedSample >> 8];
// 计算量化值
int quantizedValue = (normalizedSample >> (segment + 3)) & 0x0F;
// 生成 A-law 编码
int aLawSample = sign | (segment << 4) | quantizedValue;
// 添加到结果列表
aLawSamples.add(aLawSample);
}
return aLawSamples;
}
int ALawToLinear(int aVal) {
// 取反
aVal = ~aVal;
// 计算偏移
int t = ((aVal & 0x0F) << 3) + 0x84;
t <<= (aVal & 0x70) >> 4;
// 根据符号位决定返回值的正负
return (aVal & 0x80) != 0 ? 0x84 - t : t - 0x84;
}
int decodeG711(int encodedValue, bool isALaw) {
if (isALaw) {
// A律解码
encodedValue = ~encodedValue;
int t = ((encodedValue & 0x0F) << 3) + 0x84;
t <<= (encodedValue & 0x70) >> 4;
return (encodedValue & 0x80) != 0 ? 0x84 - t : t - 0x84;
} else {
// μ律解码
encodedValue = ~encodedValue;
int t = ((encodedValue & 0x0F) << 3) + 0x84;
t <<= (encodedValue & 0x70) >> 4;
return (encodedValue & 0x80) != 0 ? 0x84 - t : t - 0x84;
}
}
/// 高通滤波
List<int> highPassFilter(
List<int> audioData, int sampleRate, double cutoffFreq) {
final double rc = 1.0 / (2 * pi * cutoffFreq);
final double dt = 1.0 / sampleRate;
final double alpha = rc / (rc + dt);
List<int> filteredData = [];
int prevInput = 0;
int prevOutput = 0;
for (int sample in audioData) {
int output = (alpha * (prevOutput + sample - prevInput)).round();
filteredData.add(output);
prevInput = sample;
prevOutput = output;
}
return filteredData;
}
/// 噪声门
List<int> noiseGate(List<int> audioData, int threshold) {
return audioData
.map((sample) => sample.abs() > threshold ? sample : 0)
.toList();
}
/// 解码并降噪
List<int> decodeAndDenoise(List<int> encodedData, bool isALaw, int sampleRate,
double cutoffFreq, int threshold) {
// 解码 G.711 数据
List<int> decodedData =
encodedData.map((value) => decodeG711(value, isALaw)).toList();
// 高通滤波
List<int> filteredData =
highPassFilter(decodedData, sampleRate, cutoffFreq);
// 噪声门
List<int> denoisedData = noiseGate(filteredData, threshold);
return denoisedData;
}
//711解码为pcm数据
List<int> convertList(List<int> aLawList) {
// 将 ALawToLinear 函数应用于 List<int>
final List<int> linearList = aLawList.map(ALawToLinear).toList();
return linearList;
}
//List<int>转为Uint8List
Uint8List convertToInt8ListLittleEndian(List<int> intList) {
final List<int> int8List = [];
for (int intValue in intList) {
intValue = intValue * 2;
// 将 int 拆分为两个字节,采用小端序
int8List.add(intValue & 0xFF); // 低 8 位
int8List.add((intValue & 0xFF00) >> 8); // 高 8 位
}
return Uint8List.fromList(int8List);
}
}