diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart index c437be87..ad32bc41 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart @@ -1,3 +1,4 @@ + import 'dart:async'; import 'package:flutter/services.dart'; diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart index ad539497..69e908b0 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart @@ -1,5 +1,10 @@ +import 'dart:async'; +import 'dart:convert'; import 'dart:io'; +import 'dart:isolate'; +import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -7,8 +12,10 @@ import 'package:flutter_sound/flutter_sound.dart'; import 'package:get/get.dart'; import 'package:network_info_plus/network_info_plus.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:flutter_audio_capture/flutter_audio_capture.dart'; import '../../../../app_settings/app_colors.dart'; +import '../../../../blue/io_tool/io_tool.dart'; import '../../../../talk/udp/udp_manage.dart'; import '../../../../talk/udp/udp_senderManage.dart'; import '../../../../talk/udp/udp_talkClass.dart'; @@ -28,9 +35,10 @@ class _LockMonitoringPageState extends State { final logic = Get.put(LockMonitoringLogic()); final state = Get.find().state; - late FlutterSoundRecorder recorder; - late FlutterSoundPlayer player; - late String filePath; + late FlutterAudioCapture audioCapture; + // late FlutterSoundRecorder recorder; + // late FlutterSoundPlayer player; + // late String filePath; @override void initState() { @@ -198,10 +206,10 @@ class _LockMonitoringPageState extends State { print("onLongPressUp"); // _playRecording(); + // _stopCapture(); if (state.udpStatus.value == 9) { state.udpStatus.value = 8; } - _stopRecording(); } ) ), @@ -334,104 +342,323 @@ class _LockMonitoringPageState extends State { //录音处理 _initRecorder() { - recorder = FlutterSoundRecorder(); + // recorder = FlutterSoundRecorder(); + audioCapture = FlutterAudioCapture(); } + // Future _startRecording(List dataList) async { + // try { + // await recorder.openAudioSession(); + // /// 监听录音 + // recorder.onProgress!.listen((e) { + // print("onProgress:$e"); + // }); + // + // await recorder.startRecorder( + // onProgress: (StreamController progress) { + // progress.stream.listen((FooderData fooData) { + // // 在这里处理 PCM 数据(fooData.buffer) + // print('Received PCM data: ${fooData.buffer.length} bytes'); + // }); + // }, + // ); + // setState(() { + // _isRecording = true; + // }); + // } catch (e) { + // print('Error starting recording: $e'); + // } + // } + + // Future _stopRecording() async { + // try { + // await recorder.stopRecorder(); + // await _recorder.closeAudioSession(); + // setState(() { + // _isRecording = false; + // }); + // } catch (e) { + // print('Error stopping recording: $e'); + // } + // } + + //开始录音 _startRecording() async { - getFilePath().then((value) { - filePath = value; - }); - await recorder.openRecorder(); - await recorder.startRecorder( - toFile: filePath, - codec: Codec.pcm16WAV, - bitRate: 8000, - numChannels: 1, - sampleRate: 8000, + try { + // _getFilePath().then((value) { + // filePath = value; + // }); + // await recorder.openRecorder(); + // // 监听录音 + // recorder.onProgress!.listen((e) { + // print("onProgress:$e"); + // }); + // await recorder.startRecorder( + // toFile: filePath, + // codec: Codec.pcm16WAV, + // bitRate: 8000, + // numChannels: 1, + // sampleRate: 8000, + // ); + + _startCapture(); + } catch (e) { + print('Error starting recording: $e'); + } + + // getFilePath().then((value) { + // filePath = value; + // }); + // await recorder.openRecorder(); + // await recorder.startRecorder( + // toFile: filePath, + // codec: Codec.pcm16WAV, + // bitRate: 8000, + // numChannels: 1, + // sampleRate: 8000, + // ); + } + + Future _startCapture() async { + await audioCapture.start( + _listener, + onError, + sampleRate: 8000, + bufferSize: 3000 ); } + Future _stopCapture() async { + await audioCapture.stop(); + } + + Future _listener(dynamic obj) async { + print('data.length:${obj.length} Received data:$obj'); + var buffer = Float64List.fromList(obj.cast()); + Int16List list = float64ListToInt16List(buffer); + print('Get data.length:${list.length} Received data:$list'); + for (int i = 0; i < list.length; i++) { + list[i] = linearToULaw(list[i]); + } + print('change Get data.length:${list.length} change Received data:$list'); + List sendList = list.toList(); + + Isolate isolate = await Isolate.spawn(_sendRecordData, { + "bytes": sendList, + "udpSendDataFrameNumber": 0, + "lockID": UDPManage().lockId, + "lockIP": UDPManage().host, + "userMobile": await Storage.getMobile(), + "userMobileIP": await NetworkInfo().getWifiIP(), + }); + + // 在主线程中监听子线程发送的数据 + // receivePort.listen((data) { + // print('Received data: $data'); + // }); + } + + void onError(Object e) { + print(e); + } + + 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) { + List table = [0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF]; + int size = 8; + for (int i = 0; i < size; i++) { + if (val <= table[i]) { + return i; + } + } + return size; + } + + Int16List float64ListToInt16List(Float64List float64List) { + Int16List int16List = Int16List(float64List.length); + for (int i = 0; i < float64List.length; i++) { + double sample = float64List[i]; + // Make sure the sample value is within the int16 range + if (sample > 1.0) { + sample = 1.0; + } else if (sample < -1.0) { + sample = -1.0; + } + // Convert the sample to int16 by scaling it to the full int16 range + int16List[i] = (sample * 32767).toInt(); + } + return int16List; + } + //停止录音 - _stopRecording() async { - await recorder.stopRecorder(); + // _stopRecording() async { + // try { + // await recorder.stopRecorder(); + // } catch (e) { + // print('Error stopping recording: $e'); + // } + // await recorder.stopRecorder(); + // + // // final file = File(filePath); + // File file = File(filePath); // 使用 create 方法创建文件 + // + // print('filePathfilePath:$filePath file:$file await file.exists():${await file.exists()}'); + // if (await file.exists()) { + // final List bytes = await file.readAsBytes(); + // print('Recorded audio bytes.length:${bytes.length} bytes: $bytes'); + // + // _sendRecordData(bytes); + // } + // } + + // Future _getFilePath() async { + // final directory = await getApplicationDocumentsDirectory(); + // final filePath = '${directory.path}/recording.wav'; + // + // // 创建文件 + // File file = File(filePath); + // await file.create(); // 使用 create 方法创建文件 + // + // return filePath; + // } + + + // Future _getRecordedAudioBytes() async { // final file = File(filePath); - File file = File(filePath); // 使用 create 方法创建文件 - - print('filePathfilePath:$filePath file:$file await file.exists():${await file.exists()}'); - if (await file.exists()) { - final List bytes = await file.readAsBytes(); - print('Recorded audio bytes.length:${bytes.length} bytes: $bytes'); - - _sendRecordData(bytes); - } - } - - Future getFilePath() async { - final directory = await getApplicationDocumentsDirectory(); - final filePath = '${directory.path}/recording.wav'; - - // 创建文件 - File file = File(filePath); - await file.create(); // 使用 create 方法创建文件 - - return filePath; - } - - - Future _getRecordedAudioBytes() async { - final file = File(filePath); - if (await file.exists()) { - final List bytes = await file.readAsBytes(); - print('Recorded audio bytes: $bytes'); - } - } + // if (await file.exists()) { + // final List bytes = await file.readAsBytes(); + // print('Recorded audio bytes: $bytes'); + // } + // } //播放录音 - _playRecording() async { - player = FlutterSoundPlayer(); - player.openPlayer(); - - await player.startPlayer( - fromURI: filePath, - codec: Codec.pcm16WAV, - ); + // _playRecording() async { + // player = FlutterSoundPlayer(); + // player.openPlayer(); + // + // await player.startPlayer( + // fromURI: filePath, + // codec: Codec.pcm16WAV, + // ); // Toast.show(msg: "储存录音播放了"); - print('_playRecording() 储存录音播放了'); - } + // print('_playRecording() 储存录音播放了'); + // } //停止播放 // _stopPlaying() async { // await player.stopPlayer(); // } - _sendRecordData(List bytes) async { - // 刚进来是接听状态,然后改为长按对讲 - var userMobileIP = await NetworkInfo().getWifiIP(); - var userMobile = await Storage.getMobile(); + // var udpSendDataFrameNumber = 0; + _sendRecordData(Map args) async { - // 57 - List topBytes = [ - 1, 1, 1, 1, // 时间戳 - 1, 0, // 音频 - 1, 0, // 帧序号 - 64, 0, 0, 0, // 帧长度 - 1, 0, // 总包数 - 1, 0, // 当前包号 - 64, 1, // 数据长度 - 176, 4, // 保留 - ]; - UDPSenderManage.sendMainProtocol( - command: 150, - commandTypeIsCalling: 1, - subCommand: 8, - lockID: UDPManage().lockId, - lockIP: UDPManage().host, - userMobile: userMobile, - userMobileIP: userMobileIP, - endData: bytes - ); + List bytes = args["bytes"]; + int udpSendDataFrameNumber = args["udpSendDataFrameNumber"]; + String? lockID = args["lockID"]; + String? lockIP = args["lockIP"]; + String? userMobile = args["userMobile"]; + String? userMobileIP = args["userMobileIP"]; + + int length = 320; // 每个子List的长度 + for (int i = 0; i < bytes.length; i += length) { + int end = (i + length < bytes.length) ? i + length : bytes.length; + bytes.sublist(i, end); + // _sendRecordData(bytes.sublist(i, end)); + // // 刚进来是接听状态,然后改为长按对讲 + // var userMobileIP = await NetworkInfo().getWifiIP(); + // var userMobile = await Storage.getMobile(); + + while(true) { + udpSendDataFrameNumber++; + if (udpSendDataFrameNumber >= 65536) udpSendDataFrameNumber=1; + // 57 + List topBytes = [ + 1, 1, 1, 1, // 时间戳 + 1, 0, // 音频 + 1, 0, // 帧序号 + 64, 0, 0, 0, // 帧长度 + 1, 0, // 总包数 + 1, 0, // 当前包号 + 64, 1, // 数据长度 + 176, 4, // 保留 + ]; + + ByteData byteData = ByteData(2); + byteData.setUint16(0, udpSendDataFrameNumber, Endian.little); + topBytes[6] = byteData.getUint8(0); + topBytes[7] = byteData.getUint8(1); + + topBytes.addAll(bytes); + // print("topBytes:$topBytes"); + // UDPSenderManage.sendMainProtocol( + // command: 150, + // commandTypeIsCalling: 1, + // subCommand: 8, + // lockID: lockID, + // lockIP: lockIP, + // userMobile: userMobile, + // userMobileIP: userMobileIP, + // endData: topBytes + // ); + + // 命令 + topBytes.add(150); + + // 命令类型 + topBytes.add(1); + + // 子命令 + topBytes.add(8); + + // lockID + List lockIDData = utf8.encode(lockID!); + topBytes.addAll(lockIDData); + topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length); + + // lockIP + var lockIPList = lockIP!.split("."); + lockIPList.forEach((element) { + topBytes.add(int.parse(element)); + }); + + // userMobile + List userMobileData = utf8.encode(userMobile!); + topBytes.addAll(userMobileData); + topBytes = getFixedLengthList(topBytes, 20 - userMobileData.length); + + // userMobileIP + var userMobileIPList = lockIP!.split("."); + userMobileIPList.forEach((element) { + topBytes.add(int.parse(element)); + }); + + UDPManage().sendData(topBytes); + } + } } } diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart index 67cce56e..3e70b79c 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; class LockMonitoringState { var isOpenVoice = false.obs; + var udpSendDataFrameNumber = 0;// 帧序号 var udpStatus = 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话 var passwordTF = TextEditingController(); diff --git a/star_lock/lib/talk/udp/udp_reciverData.dart b/star_lock/lib/talk/udp/udp_reciverData.dart index 9fea6034..52c1e380 100644 --- a/star_lock/lib/talk/udp/udp_reciverData.dart +++ b/star_lock/lib/talk/udp/udp_reciverData.dart @@ -19,7 +19,7 @@ class CommandUDPReciverManager { if (dataSize < 4) { return; } - print("appReceiveUDPData:$data"); + // print("appReceiveUDPData:$data"); Uint8List data1 = Uint8List.fromList(data); if (data1.length == 1) { diff --git a/star_lock/linux/flutter/generated_plugin_registrant.cc b/star_lock/linux/flutter/generated_plugin_registrant.cc index 05d9a9b9..f03aaf40 100644 --- a/star_lock/linux/flutter/generated_plugin_registrant.cc +++ b/star_lock/linux/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -21,6 +22,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_audio_capture_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterAudioCapturePlugin"); + flutter_audio_capture_plugin_register_with_registrar(flutter_audio_capture_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/star_lock/linux/flutter/generated_plugins.cmake b/star_lock/linux/flutter/generated_plugins.cmake index b6e600e9..01b1e1e7 100644 --- a/star_lock/linux/flutter/generated_plugins.cmake +++ b/star_lock/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST aj_captcha_flutter audioplayers_linux file_selector_linux + flutter_audio_capture url_launcher_linux ) diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index 2ecfba90..fcd0b488 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -127,6 +127,7 @@ dependencies: flutter_sound: ^9.2.13 ffmpeg_kit_flutter: 5.1.0-LTS fast_gbk: ^1.0.0 + flutter_audio_capture: ^1.1.6 dev_dependencies: flutter_test: