import 'dart:async'; import 'dart:math'; import 'package:flutter/services.dart'; import 'package:flutter_voice_processor/flutter_voice_processor.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/talk/call/callTalk.dart'; import '../../../../talk/call/g711.dart'; import '../../../../talk/udp/udp_manage.dart'; import '../../../../talk/udp/udp_senderManage.dart'; import '../../../../tools/baseGetXController.dart'; import '../../../../tools/eventBusEventManage.dart'; import '../../../app_settings/app_settings.dart'; import 'realTimePicture_state.dart'; class RealTimePictureLogic extends BaseGetXController { final RealTimePictureState state = RealTimePictureState(); /// 初始化发送声音 initRecorder() { state.voiceProcessor = VoiceProcessor.instance; } /// 收到视频流数据 StreamSubscription? _getTVDataRefreshUIEvent; void _getTVDataRefreshUIAction() { // 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus _getTVDataRefreshUIEvent = eventBus.on().listen((event) { if (event.tvList.isNotEmpty) { // 预加载图片数据 final Uint8List imageData = Uint8List.fromList(event.tvList); // 更新状态 state.listData.value = imageData; } }); } /// 收到UDP发送的状态 StreamSubscription? _getUDPStatusRefreshUIEvent; void _getUDPStatusRefreshUIAction() { _getUDPStatusRefreshUIEvent = eventBus.on().listen((event) { state.udpStatus.value = event.udpStatus; }); } /// 监视 udpMonitorAction() async { UDPSenderManage.sendMainProtocol( command: 152, commandTypeIsCalling: 1, subCommand: 1, lockID: state.getLockName.value, lockIP: UDPManage().host, userMobile: await state.userUid, userMobileIP: await state.userMobileIP, endData: []); } /// 挂断 udpHangUpAction() async { UDPSenderManage.sendMainProtocol( command: 152, commandTypeIsCalling: 1, subCommand: 30, lockID: UDPManage().lockId, lockIP: UDPManage().host, userMobile: await state.userUid, userMobileIP: await state.userMobileIP, endData: []); } /// 开门 udpOpenDoorAction(List list) async { UDPSenderManage.sendMainProtocol( command: 152, commandTypeIsCalling: 1, subCommand: 10, lockID: UDPManage().lockId, lockIP: UDPManage().host, userMobile: await state.userUid, userMobileIP: await state.userMobileIP, endData: list); Get.back(); } Future _readG711Data() async { final String filePath = 'assets/s10-g711.bin'; final List audioData = await G711().readAssetFile(filePath); // AppLog.log('发送读取711文件数据为:$audioData');// 数据为:$audioData // return; // AppLog.log('发送读取711文件数据长度为:${audioData.length}');// 数据为:$audioData if (audioData.isNotEmpty) { // 在这里处理你的音频数据 // pcmBytes = G711().convertList(audioData); // AppLog.log('发送转换pcmBytes数据长度为:${pcmBytes.length}'); int start = 0; final int length = 320; while (start < audioData.length) { // await Future.delayed(const Duration(milliseconds: 50)); final int end = (start + length > audioData.length) ? audioData.length : start + length; final List sublist = audioData.sublist(start, end); sendRecordData({ 'bytes': sublist, // "udpSendDataFrameNumber": 0, 'lockID': UDPManage().lockId, 'lockIP': UDPManage().host, 'userMobile': await state.userUid, 'userMobileIP': await state.userMobileIP, }); AppLog.log(sublist.toString()); start += length; } AppLog.log('G711数据发送完成'); } else { AppLog.log('Failed to read audio data.'); } } Future startProcessing() async { frameListener(List frame) async { // AppLog.log('Get data.length:${frame.length} Received data:$frame'); for (int i = 0; i < frame.length; i++) { frame[i] = linearToULaw(frame[i]); } // AppLog.log('change Get data.length:${frame.length} change Received data:$frame'); await Future.delayed(const Duration(milliseconds: 50)); sendRecordData({ 'bytes': frame, // "udpSendDataFrameNumber": 0, 'lockID': UDPManage().lockId, 'lockIP': UDPManage().host, 'userMobile': await state.userUid, 'userMobileIP': await state.userMobileIP, }); } errorListener(VoiceProcessorException error) { AppLog.log('VoiceProcessorException: $error'); } state.voiceProcessor?.addFrameListener(frameListener); state.voiceProcessor?.addErrorListener(errorListener); try { if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) { await state.voiceProcessor?.start(320, 8000); final bool? isRecording = await state.voiceProcessor?.isRecording(); } else {} } on PlatformException catch (ex) { AppLog.log('PlatformException: $ex'); } finally {} } Future stopProcessing() async { try { await state.voiceProcessor?.stop(); } on PlatformException catch (ex) { AppLog.log('PlatformException: $ex'); } finally {} } void onError(Object e) { AppLog.log(e.toString()); } sendRecordData(Map args) async { final List bytes = args['bytes']; // int udpSendDataFrameNumber = args["udpSendDataFrameNumber"]; final String? lockID = args['lockID']; final String? lockIP = args['lockIP']; final String? userMobile = args['userMobile']; final String? userMobileIP = args['userMobileIP']; state.udpSendDataFrameNumber++; if (state.udpSendDataFrameNumber >= 65536) state.udpSendDataFrameNumber = 1; // 57 final List topBytes = []; topBytes.addAll([ 1, 1, 1, 1, // 时间戳 1, 0, // 音频 1, 0, // 帧序号 64, 0, 0, 0, // 帧长度 1, 0, // 总包数 1, 0, // 当前包号 64, 1, // 数据长度 176, 4, // 保留 ]); topBytes[6] = state.udpSendDataFrameNumber & 0x000000FF; topBytes[7] = (state.udpSendDataFrameNumber & 0x0000FF00) >> 8; topBytes.addAll(bytes); AppLog.log('setVoiceBytes:$topBytes'); UDPSenderManage.sendMainProtocol( command: 152, commandTypeIsCalling: 1, subCommand: 8, lockID: lockID, lockIP: lockIP, userMobile: userMobile, userMobileIP: userMobileIP, endData: topBytes); // UDPManage().sendData(topBytes); } // 拿到的音频转化成pcm int linearToULaw(int pcmVal) { int mask; int seg; int uval; if (pcmVal < 0) { pcmVal = 0x84 - pcmVal; mask = 0x7F; } else { pcmVal += 0x84; mask = 0xFF; } seg = search(pcmVal); if (seg >= 8) { return 0x7F ^ mask; } else { uval = seg << 4; uval |= (pcmVal >> (seg + 3)) & 0xF; return uval ^ mask; } } int search(int val) { final List table = [ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF ]; final int size = 8; for (int i = 0; i < size; i++) { if (val <= table[i]) { return i; } } return size; } double _calculateVolumeLevel(List frame) { double rms = 0.0; for (int sample in frame) { rms += pow(sample, 2); } rms = sqrt(rms / frame.length); final double dbfs = 20 * log(rms / 32767.0) / log(10); final double normalizedValue = (dbfs + 50) / 50; return normalizedValue.clamp(0.0, 1.0); } Future getPermissionStatus() async { final Permission permission = Permission.microphone; //granted 通过,denied 被拒绝,permanentlyDenied 拒绝且不在提示 final PermissionStatus status = await permission.status; if (status.isGranted) { return true; } else if (status.isDenied) { requestPermission(permission); } else if (status.isPermanentlyDenied) { openAppSettings(); } else if (status.isRestricted) { requestPermission(permission); } else {} return false; } ///申请权限 void requestPermission(Permission permission) async { final PermissionStatus status = await permission.request(); if (status.isPermanentlyDenied) { openAppSettings(); } } @override void onReady() { super.onReady(); _getTVDataRefreshUIAction(); _getUDPStatusRefreshUIAction(); initRecorder(); } @override void onInit() { super.onInit(); } @override void onClose() { CallTalk().finishAVData(); _getTVDataRefreshUIEvent!.cancel(); _getUDPStatusRefreshUIEvent!.cancel(); if (state.oneMinuteTimeTimer != null) { state.oneMinuteTimeTimer.cancel(); } stopProcessing(); state.listData.value = Uint8List(0); } }