diff --git a/lib/talk/starChart/views/talkView/talk_view_logic.dart b/lib/talk/starChart/views/talkView/talk_view_logic.dart index 5033bca3..4a64ebe9 100644 --- a/lib/talk/starChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/starChart/views/talkView/talk_view_logic.dart @@ -46,6 +46,8 @@ class TalkViewLogic extends BaseGetXController { int audioFrameIntervalMs = 20; // 初始帧间隔设置为45毫秒(约22FPS) int minFrameIntervalMs = 30; // 最小帧间隔(约33 FPS) int maxFrameIntervalMs = 100; // 最大帧间隔(约1 FPS) + // 定义音频帧缓冲和发送函数 + List _bufferedAudioFrames = []; /// 初始化音频播放器 void _initFlutterPcmSound() { @@ -533,15 +535,17 @@ class TalkViewLogic extends BaseGetXController { //开始录音 Future startProcessingAudio() async { - // 增加录音帧监听器和错误监听器 - state.voiceProcessor?.addFrameListener(_onFrame); - state.voiceProcessor?.addErrorListener(_onError); try { if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) { await state.voiceProcessor?.start(state.frameLength, state.sampleRate); final bool? isRecording = await state.voiceProcessor?.isRecording(); state.isRecordingAudio.value = isRecording!; state.startRecordingAudioTime.value = DateTime.now(); + + // 增加录音帧监听器和错误监听器 + state.voiceProcessor + ?.addFrameListeners([_onFrame]); + state.voiceProcessor?.addErrorListener(_onError); } else { // state.errorMessage.value = 'Recording permission not granted'; } @@ -576,23 +580,23 @@ class TalkViewLogic extends BaseGetXController { // 音频帧处理 Future _onFrame(List frame) async { - // 预处理和转码操作放到异步计算线程 - // final processedFrame = await compute(preprocessAudio, frame); - // final list = listLinearToALaw(processedFrame); final List processedFrame = preprocessAudio(frame); final List list = listLinearToALaw(processedFrame); + _bufferedAudioFrames.addAll(list); final int ms = DateTime.now().millisecondsSinceEpoch - state.startRecordingAudioTime.value.millisecondsSinceEpoch; - // 发送音频数据到UDP - await StartChartManage().sendTalkDataMessage( - talkData: TalkData( - content: list, - contentType: TalkData_ContentTypeE.G711, - durationMs: ms, - ), - ); + Future.delayed(const Duration(milliseconds: 1000)).whenComplete(() async { + // 发送音频数据到UDP + await StartChartManage().sendTalkDataMessage( + talkData: TalkData( + content: list, + contentType: TalkData_ContentTypeE.G711, + durationMs: ms, + ), + ); + }); } // 错误监听 @@ -662,9 +666,31 @@ class TalkViewLogic extends BaseGetXController { // return processedList; // } - List listLinearToALaw(List pcmList) { - final List aLawList = []; + List adjustVolume(List pcmList, double volume) { + final List adjustedPcmList = []; for (int pcmVal in pcmList) { + // 调整音量 + int adjustedPcmVal = (pcmVal * volume).round(); + + // 裁剪到 16-bit PCM 范围 + if (adjustedPcmVal > 32767) { + adjustedPcmVal = 32767; + } else if (adjustedPcmVal < -32768) { + adjustedPcmVal = -32768; + } + + adjustedPcmList.add(adjustedPcmVal); + } + return adjustedPcmList; + } + + List listLinearToALaw(List pcmList) { + // 先调节音量 + final List adjustedPcmList = adjustVolume(pcmList, 5.0); + + // 再进行 A-law 编码 + final List aLawList = []; + for (int pcmVal in adjustedPcmList) { final int aLawVal = linearToALaw(pcmVal); aLawList.add(aLawVal); } diff --git a/lib/talk/starChart/views/talkView/talk_view_state.dart b/lib/talk/starChart/views/talkView/talk_view_state.dart index 7e56836a..25538093 100644 --- a/lib/talk/starChart/views/talkView/talk_view_state.dart +++ b/lib/talk/starChart/views/talkView/talk_view_state.dart @@ -37,7 +37,7 @@ class TalkViewState { RxList listAudioData = [].obs; //得到的音频流字节数据 GlobalKey globalKey = GlobalKey(); - Timer? oneMinuteTimeTimer; // 定时器超过60秒关闭当前界面 + Timer? oneMinuteTimeTimer; // 定时器超过60秒关闭当前界面 RxInt oneMinuteTime = 0.obs; // 定时器秒数 // 定时器如果发送了接听的命令 而没收到回复就每秒重复发送10次 @@ -89,4 +89,4 @@ class TalkViewState { RxBool isLongPressing = false.obs; // 旋转角度(以弧度为单位) RxBool hasAudioData = false.obs; // 是否有音频数据 RxInt lastAudioTimestamp = 0.obs; // 最后接收到的音频数据的时间戳 -} \ No newline at end of file +}