Browse Source

opus日记打印

weicu
fdp 1 year ago
parent
commit
2671f5d137
  1. 2
      lib/modules/opus_test/controllers/opus_test_controller.dart
  2. 44
      lib/modules/settings/views/settings_view.dart
  3. 80
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

2
lib/modules/opus_test/controllers/opus_test_controller.dart

@ -140,7 +140,7 @@ class OpusTestController extends GetxController {
for (var entity in files) {
if (entity is File) {
final path = entity.path.toLowerCase();
if (path.endsWith('.opus')) {
if (path.endsWith('.opus') || path.endsWith('.txt')) {
final fileSize = await entity.length();
externalFiles.add(PlatformFile(
name: entity.path.split('/').last,

44
lib/modules/settings/views/settings_view.dart

@ -514,28 +514,28 @@ class SettingsView extends GetView<SettingsController> {
// color: isDarkMode
// ? Colors.white.withOpacity(0.1)
// : Colors.grey[200]),
// //BLE测试
// _buildSimpleNavigationSetting(
// title: 'opus解码测试',
// subtitle: '测试opus解码',
// icon: Icons.bluetooth_searching,
// iconBgColor: isDarkMode
// ? Colors.green[900]!.withOpacity(0.3)
// : Colors.green[100]!,
// iconColor:
// isDarkMode ? Colors.green[300]! : Colors.green[600]!,
// titleColor: isDarkMode ? Colors.white : null,
// subtitleColor: isDarkMode ? Colors.white70 : null,
// onTap: () {
// Get.toNamed(Routes.opusTest);
// },
// isDarkMode: isDarkMode,
// ),
// Divider(
// height: 1,
// color: isDarkMode
// ? Colors.white.withOpacity(0.1)
// : Colors.grey[200]),
//BLE测试
_buildSimpleNavigationSetting(
title: 'opus解码测试',
subtitle: '测试opus解码',
icon: Icons.bluetooth_searching,
iconBgColor: isDarkMode
? Colors.green[900]!.withOpacity(0.3)
: Colors.green[100]!,
iconColor:
isDarkMode ? Colors.green[300]! : Colors.green[600]!,
titleColor: isDarkMode ? Colors.white : null,
subtitleColor: isDarkMode ? Colors.white70 : null,
onTap: () {
Get.toNamed(Routes.opusTest);
},
isDarkMode: isDarkMode,
),
Divider(
height: 1,
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[200]),
// BLE测试
// _buildSimpleNavigationSetting(

80
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

@ -1360,7 +1360,7 @@ startBytesStatistics()
if (data != null) {
// 编码完成的数据处理:
// 1. 保存到WAV文件
recordfile1?.saveAudioDataToWav(data)
// 2. 将编码后的数据加入发送队列进行分块发送
addAudioDataToSendQueue(data)
} else {
@ -1493,13 +1493,16 @@ startBytesStatistics()
audioSendHandler.post {
try {
callWriteChar?.value = chunk
recordfile1?.saveAudioDataAsUtf8Hex(chunk, true)
val isSuccess = bluetoothGatt?.writeCharacteristic(callWriteChar)
if (isSuccess == true) {
recordfile1?.saveAudioDataToWav("发送成功,大小: ${chunk.size} 字节")
// 累加发送成功的字节数
bytesSentInCurrentSecond += chunk.size
Log.d(TAG, "成功发送音频数据块,大小: ${chunk.size} 字节")
} else {
recordfile1?.saveAudioDataToWav("发送失败,大小: ${chunk.size} 字节")
Log.e(TAG, "发送音频数据块失败,大小: ${chunk.size} 字节")
// 详细的失败原因分析
val failureReason = StringBuilder("发送音频数据块失败,大小: ${chunk.size} 字节")
@ -1636,7 +1639,6 @@ startBytesStatistics()
*/
fun closeCodec(): Boolean {
Log.i(TAG, "关闭编解码...")
return sendCommand(
BleConst.CMD_CONTROL_CODEC.toByte(),
byteArrayOf(
@ -1646,12 +1648,7 @@ startBytesStatistics()
) // 或其他默认声道
)
}
fun closeCodec1(): Boolean {
recordfile1!!.closeFile()
recordfile!!.closeFile()
return true
}
/**
* 控制编解码 - 打开解码
*/
@ -1682,6 +1679,7 @@ startBytesStatistics()
*/
fun openA2DPDecoder(): Boolean {
Log.i(TAG, "打开编码 0xA2")
startOpusEncodeStream()
//双声道 80字节
startOpusStreamDecoding(false, 2, 16000, 80)
@ -1724,10 +1722,7 @@ startBytesStatistics()
*/
fun openEncoder(): Boolean {
Log.i(TAG, "打开编码0xB1")
recordfile1!!.closeFile()
recordfile1!!.creatingFiles()
recordfile!!.closeFile()
recordfile!!.creatingFiles()
startOpusStreamDecoding(false, 1, 16000, 40)
// // 目前仅发送命令通知设备开始编码。
// return sendCommand(
@ -2096,7 +2091,7 @@ class RecordingFile(private val context: Context) {
val timestamp = dateFormat.format(Date())
val filePath =
File(context.getExternalFilesDir(null), "${fileName}_${timestamp}.opus").absolutePath
File(context.getExternalFilesDir(null), "${fileName}_${timestamp}.txt").absolutePath
currentAudioFile = File(filePath)
currentAudioFile?.createNewFile()
// 追加音频数据到文件
@ -2124,17 +2119,18 @@ class RecordingFile(private val context: Context) {
/**
* 保存音频数据到 opus 文件(异步)
* @param buffer 音频数据字节数组
*/
internal fun saveAudioDataToWav(buffer: ByteArray) {
if (fos == null || currentAudioFile == null) return
// 放入队列,由写线程写入
// 1. 将字节数据转换为十六进制字符串
// val hexData = buildString {
// buffer.forEachIndexed { index, byte ->
// append("%02X".format(byte))
// // 1. 将字节数据转换为十六进制字符串
// val hexData = buildString {
// buffer.forEachIndexed { index, byte ->
// append("%02X".format(byte))
// }
// }
// }
// }
// 2. 写入十六进制字符串
@ -2142,6 +2138,52 @@ class RecordingFile(private val context: Context) {
totalBytesWritten += buffer.size
}
/**
* 保存日志信息到文件(重载方法)
* 使用UTF-8编码处理字符串
* @param logMessage 日志消息字符串
*/
internal fun saveAudioDataToWav(logMessage: String) {
if (fos == null || currentAudioFile == null) return
try {
// 使用UTF-8编码将字符串转换为字节数组,并添加换行符
val logBytes = (logMessage + "\n").toByteArray(Charsets.UTF_8)
writeQueue.offer(logBytes)
totalBytesWritten += logBytes.size
Log.d("RecordingFile", "保存日志信息: ${logMessage.length} 字符, ${logBytes.size} 字节 (UTF-8)")
} catch (e: Exception) {
Log.e("RecordingFile", "UTF-8编码转换失败: ${e.message}")
}
}
/**
* 将音频数据转换为UTF-8编码的十六进制字符串格式并保存
* @param buffer 音频数据字节数组
* @param addTimestamp 是否添加时间戳,默认为true
*/
internal fun saveAudioDataAsUtf8Hex(buffer: ByteArray, addTimestamp: Boolean = true) {
if (fos == null || currentAudioFile == null) return
try {
val timestamp = if (addTimestamp) {
"[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(Date())}] "
} else ""
// 将字节数组转换为十六进制字符串
val hexString = buffer.joinToString(" ") { "%02X".format(it) }
val dataLine = "${timestamp}音频数据 (${buffer.size} 字节): $hexString\n"
// 使用UTF-8编码转换为字节数组
val utf8Bytes = dataLine.toByteArray(Charsets.UTF_8)
writeQueue.offer(utf8Bytes)
totalBytesWritten += utf8Bytes.size
Log.d("RecordingFile", "保存UTF-8格式音频数据: ${buffer.size} 字节 -> ${utf8Bytes.size} UTF-8字节")
} catch (e: Exception) {
Log.e("RecordingFile", "UTF-8格式保存失败: ${e.message}")
}
}
internal fun closeFile() {
try {

Loading…
Cancel
Save