133 lines
3.8 KiB
Dart
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'dart:math';
import 'package:flutter/services.dart';
class G711 {
Future<List<int>> readAssetFile(String assetPath) async {
final ByteData data = await rootBundle.load(assetPath);
final List<int> bytes = data.buffer.asUint8List();
return bytes;
}
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 ^= 0x55; // 反转最高位
int sign = encodedValue & 0x80; // 符号位
int exponent = (encodedValue & 0x70) >> 4; // 指数位
int mantissa = encodedValue & 0x0F; // 尾数位
int pcmSample = (mantissa << 4) + 0x84; // 计算量化值
pcmSample <<= exponent; // 根据指数位移位
pcmSample = (sign == 0) ? pcmSample : -pcmSample; // 处理符号位
return pcmSample;
} else {
// μ律解码
encodedValue ^= 0xFF; // 反转最高位
int sign = encodedValue & 0x80; // 符号位
int exponent = (encodedValue & 0x70) >> 4; // 指数位
int mantissa = encodedValue & 0x0F; // 尾数位
int pcmSample = (mantissa << 3) + 0x84; // 计算量化值
pcmSample <<= exponent + 1; // 根据指数位移位μ律需要额外加1
pcmSample = (sign == 0) ? pcmSample : -pcmSample; // 处理符号位
return pcmSample;
}
}
/// 高通滤波
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> removeEcho(List<int> audioData, int delaySamples, double decay) {
final List<int> processedData = [];
for (int i = 0; i < audioData.length; i++) {
int sample = audioData[i];
if (i >= delaySamples) {
sample -= (audioData[i - delaySamples] * decay).round();
}
processedData.add(sample);
}
return processedData;
}
/// 解码并降噪
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);
// 回声消除处理
final List<int> processedData = removeEcho(denoisedData, 160, 0.5);
return processedData;
}
//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);
}
}