fix:调整发送g711音频数据、增加回声消除、增大缓冲区、调整A律解码效果

This commit is contained in:
liyi 2025-01-16 15:55:14 +08:00
parent b876f608e4
commit 911396e1f3
3 changed files with 65 additions and 41 deletions

View File

@ -24,16 +24,28 @@ class G711 {
int decodeG711(int encodedValue, bool isALaw) { int decodeG711(int encodedValue, bool isALaw) {
if (isALaw) { if (isALaw) {
// A律解码 // A律解码
encodedValue = ~encodedValue; encodedValue ^= 0x55; //
int t = ((encodedValue & 0x0F) << 3) + 0x84; int sign = encodedValue & 0x80; //
t <<= (encodedValue & 0x70) >> 4; int exponent = (encodedValue & 0x70) >> 4; //
return (encodedValue & 0x80) != 0 ? 0x84 - t : t - 0x84; int mantissa = encodedValue & 0x0F; //
int pcmSample = (mantissa << 4) + 0x84; //
pcmSample <<= exponent; //
pcmSample = (sign == 0) ? pcmSample : -pcmSample; //
return pcmSample;
} else { } else {
// μ // μ
encodedValue = ~encodedValue; encodedValue ^= 0xFF; //
int t = ((encodedValue & 0x0F) << 3) + 0x84; int sign = encodedValue & 0x80; //
t <<= (encodedValue & 0x70) >> 4; int exponent = (encodedValue & 0x70) >> 4; //
return (encodedValue & 0x80) != 0 ? 0x84 - t : t - 0x84; int mantissa = encodedValue & 0x0F; //
int pcmSample = (mantissa << 3) + 0x84; //
pcmSample <<= exponent + 1; // μ1
pcmSample = (sign == 0) ? pcmSample : -pcmSample; //
return pcmSample;
} }
} }

View File

@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart';
@ -34,6 +35,7 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle
talkDataOverTimeTimerManager.cancel(); talkDataOverTimeTimerManager.cancel();
EasyLoading.showToast('已挂断'); EasyLoading.showToast('已挂断');
Get.back();
} }
@override @override

View File

@ -41,11 +41,12 @@ class TalkViewLogic extends BaseGetXController {
final TalkViewState state = TalkViewState(); final TalkViewState state = TalkViewState();
final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state; final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state;
Timer? _syncTimer; // Timer? _syncTimer; //
Timer? _audioTimer; //
int _startTime = 0; // int _startTime = 0; //
int bufferSize = 20; // int bufferSize = 50; //
int audioBufferSize = 640; //
final List<int> frameTimestamps = []; // FPS int frameIntervalMs = 45; // 4522FPS
int frameIntervalMs = 35; // 4522FPS int audioFrameIntervalMs = 20; // 4522FPS
int minFrameIntervalMs = 30; // 33 FPS int minFrameIntervalMs = 30; // 33 FPS
int maxFrameIntervalMs = 100; // 1 FPS int maxFrameIntervalMs = 100; // 1 FPS
// int maxFrameIntervalMs = 100; // 10 FPS // int maxFrameIntervalMs = 100; // 10 FPS
@ -53,11 +54,11 @@ class TalkViewLogic extends BaseGetXController {
/// ///
void _initFlutterPcmSound() { void _initFlutterPcmSound() {
const int sampleRate = 8000; const int sampleRate = 8000;
FlutterPcmSound.setLogLevel(LogLevel.verbose); FlutterPcmSound.setLogLevel(LogLevel.none);
FlutterPcmSound.setup(sampleRate: sampleRate, channelCount: 1); FlutterPcmSound.setup(sampleRate: sampleRate, channelCount: 1);
// feed // feed
if (Platform.isAndroid) { if (Platform.isAndroid) {
FlutterPcmSound.setFeedThreshold(sampleRate ~/ 2); // Android FlutterPcmSound.setFeedThreshold(1024); // Android
} else { } else {
FlutterPcmSound.setFeedThreshold(sampleRate ~/ 32); // Android FlutterPcmSound.setFeedThreshold(sampleRate ~/ 32); // Android
} }
@ -88,7 +89,7 @@ class TalkViewLogic extends BaseGetXController {
// //
switch (contentType) { switch (contentType) {
case TalkData_ContentTypeE.G711: case TalkData_ContentTypeE.G711:
if (state.audioBuffer.length >= audioBufferSize) { if (state.audioBuffer.length >= bufferSize) {
state.audioBuffer.removeAt(0); // state.audioBuffer.removeAt(0); //
// readAudioBufferSize.removeAt(0); // // readAudioBufferSize.removeAt(0); //
} }
@ -130,14 +131,17 @@ class TalkViewLogic extends BaseGetXController {
/// ///
void _playAudioData(TalkData talkData) async { void _playAudioData(TalkData talkData) async {
// final list = G711().convertList(talkData.content); if (state.isOpenVoice.value) {
final list = G711().decodeAndDenoise(talkData.content, true, 8000, 300, 50); // final list = G711().convertList(talkData.content);
// // PCM PcmArrayInt16 final list = G711().convertList(talkData.content);
final PcmArrayInt16 fromList = PcmArrayInt16.fromList(list); // final list = G711().decodeAndDenoise(talkData.content, true,8000, 300, 50);
FlutterPcmSound.feed(fromList); // // PCM PcmArrayInt16
if (!state.isPlaying.value) { final PcmArrayInt16 fromList = PcmArrayInt16.fromList(list);
FlutterPcmSound.play(); FlutterPcmSound.feed(fromList);
state.isPlaying.value = true; if (!state.isPlaying.value) {
FlutterPcmSound.play();
state.isPlaying.value = true;
}
} }
} }
@ -154,8 +158,6 @@ class TalkViewLogic extends BaseGetXController {
Timer.periodic(Duration(milliseconds: frameIntervalMs), (timer) { Timer.periodic(Duration(milliseconds: frameIntervalMs), (timer) {
// //
_adjustFrameInterval(); _adjustFrameInterval();
_playFrames();
}); });
}); });
} }
@ -184,29 +186,37 @@ class TalkViewLogic extends BaseGetXController {
_syncTimer?.cancel(); _syncTimer?.cancel();
_syncTimer = _syncTimer =
Timer.periodic(Duration(milliseconds: frameIntervalMs), (timer) { Timer.periodic(Duration(milliseconds: frameIntervalMs), (timer) {
_playFrames(); //
_playVideoFrames();
});
_audioTimer?.cancel();
_audioTimer =
Timer.periodic(Duration(milliseconds: audioFrameIntervalMs), (timer) {
final currentTime = DateTime.now().millisecondsSinceEpoch;
final elapsedTime = currentTime - _startTime;
//
if (state.audioBuffer.isNotEmpty &&
state.audioBuffer.first.durationMs <= elapsedTime) {
//
if (state.isOpenVoice.value) {
_playAudioData(state.audioBuffer.removeAt(0));
} else {
//
//
//
state.audioBuffer.removeAt(0);
}
}
}); });
} }
} }
void _playFrames() { void _playVideoFrames() {
final currentTime = DateTime.now().millisecondsSinceEpoch; final currentTime = DateTime.now().millisecondsSinceEpoch;
final elapsedTime = currentTime - _startTime; final elapsedTime = currentTime - _startTime;
//
if (state.audioBuffer.isNotEmpty &&
state.audioBuffer.first.durationMs <= elapsedTime) {
//
if (state.isOpenVoice.value) {
_playAudioData(state.audioBuffer.removeAt(0));
} else {
//
//
//
state.audioBuffer.removeAt(0);
}
}
// //
// //
int maxFramesToProcess = 5; // 5 int maxFramesToProcess = 5; // 5