Merge branch 'develop_liyi' into 'canary_release'

Develop liyi

See merge request StarlockTeam/app-starlock!14
This commit is contained in:
李仪 2025-04-03 02:52:21 +00:00
commit 13a3ac8ab9
14 changed files with 395 additions and 262 deletions

View File

@ -245,7 +245,7 @@
"摸亮触摸屏": "कीपैड को सक्रिय करने के लिए किसी भी कुंजी को स्पर्श करें",
"摸亮触摸屏,锁进入可添加状态,点击下一步": "लॉक को सक्रिय करने के लिए कृपया किसी भी कुंजी को स्पर्श करें और उसे युग्मन मोड में रखें। अगला दबाओ",
"附近的锁": "पास के ताले",
"如需修改名字请重新命名,点击确定添加锁": "यदि आप नाम बदलना चाहते हैं, तो कृपया नाम बदलें, लॉक जोड़ने के लिए OK पर क्लिक करें।",
"如需修改名字请重新命名,点击确定添加锁": "यदि आपको नाम बदलने की जरूरत है, कृपया इसे नाम बदलें और ताला जोड़ने के लिए ठीक है क्लिक करें",
"添加锁时,手机必须在锁旁边": "लॉक जोड़ते समय, फ़ोन लॉक के बगल में होना चाहिए।",
"登录": "प्रवेश करना",
"注册": "रजिस्टर",
@ -1044,42 +1044,42 @@
"导出锁数据": "निर्यात लॉक डेटा",
"一键开锁": "एक क्लिक अनलॉक",
"已开通": "खुल गया",
"英文": "अंग्रेज़ी",
"简体中文": "पर",
"繁体中文": "पर",
"法语": "फ़्रैंकैइस",
"俄语": "सांद्रता सांद्रता सांद्रता",
"德语": "काटकर अलग कर देना",
"日语": "सोच।",
"韩语": "सोच।",
"意大利语": "इटालियनो",
"乌克兰语": "टाइप टाइप टाइप",
"葡萄牙语": "पुर्तगाओं",
"西班牙语": "स्पैनिश",
"阿拉伯语": "ए ए सेंटर सेंटर सेंटर सेंटर सेंटर।",
"越南语": "तिवारी पॅटर्न Vi पेंट टी",
"马来语": "बाहास मेलायु",
"荷兰语": "नेडरलैंड्स",
"罗马尼亚语": "रोमन पैन",
"立陶宛语": "लिटूवी हदीन",
"瑞典语": "स्का",
"爱沙尼亚语": "ईस्टी",
"波兰语": "पोल्की",
"斯洛伐克语": "चेपक",
"捷克语": "पुरआपसे",
"希腊语": "मोम मोम निर्देशिकाएँ",
"希伯来语": "",
"塞尔维亚语": "टाइप टाइप",
"土耳其语": "तुरकी",
"匈牙利语": "माँजू",
"保加利亚语": "टाइप ने वाई",
"哈萨克斯坦语": "और और और और",
"孟加拉语": "कितना पैसा",
"克罗地亚语": "ह्रवत्स्की",
"泰语": "सोच।",
"印度尼西亚语": "बाहसा इंडोनेशिया",
"芬兰语": "सूमी",
"丹麦语": "मूर्ख व्यक्ति",
"英文": "English",
"简体中文": "简体中文",
"繁体中文": "繁體中文",
"法语": "Français",
"俄语": "Русский",
"德语": "Deutsch",
"日语": "日本語",
"韩语": "한국어",
"意大利语": "Italiano",
"乌克兰语": "Українська",
"葡萄牙语": "Português",
"西班牙语": "Español",
"阿拉伯语": "العربية",
"越南语": "Tiếng Việt",
"马来语": "Bahasa Melayu",
"荷兰语": "Nederlands",
"罗马尼亚语": "Română",
"立陶宛语": "Lietuvių",
"瑞典语": "Svenska",
"爱沙尼亚语": "Eesti",
"波兰语": "Polski",
"斯洛伐克语": "Slovenčina",
"捷克语": "Čeština",
"希腊语": "Ελληνικά",
"希伯来语": "עברית",
"塞尔维亚语": "Српски",
"土耳其语": "Türkçe",
"匈牙利语": "Magyar",
"保加利亚语": "Български",
"哈萨克斯坦语": "Қазақ",
"孟加拉语": "বাংলা",
"克罗地亚语": "Hrvatski",
"泰语": "ไทย",
"印度尼西亚语": "Bahasa Indonesia",
"芬兰语": "Suomi",
"丹麦语": "Dansk",
"印地语": "हिंदीName",
"乌尔都语": "اوردو",
"重置后,该锁的掌静脉都将被删除哦,确认要重置吗?": "रीसेट के बाद, लॉक के मेटाकार्पल नसों को हटा दिया जाएगा। क्या आप निश्चित रूप से रीसेट करना चाहते हैं?",
@ -1097,8 +1097,8 @@
"支持的国家值": "यूएसए, कनाडा, यूके, ऑस्ट्रेलिया, भारत, जर्मनी, जर्मनी, इटली, स्पेन, जापान",
"操作流程": "ऑपरेशन प्रक्रिया",
"操作流程值": "1 स्मार्ट लॉक ऐप के साथ लॉक और गेटवे जोड़ें\n\n2 एप्लिकेशन में लॉक का रिमोट अनलॉकिंग फ़ंक्शन सक्षम करें (यह फ़ंक्शन डिफ़ॉल्ट रूप से बंद है). अगर आपके पास यह विकल्प नहीं है, लॉक एलेक्सा का समर्थन नहीं करता है\n\n3 एलेक्सा के लिए कौशल जोड़ें और उन्हें स्मार्ट लॉक ऐप के खाते और पासवर्ड के साथ अधिकृत करें। प्राधिकरण सफल होने के बाद, आप खाते के अंतर्गत उपकरणों की खोज कर सकते हैं।\n\n4 एलेक्सए ऐप में लॉक का पता लगाएं, वॉयस अनलॉक फ़ंक्शन चालू करें, और भाषा का पासवर्ड सेट करें।\n\n5 लॉक को एलेक्सा के माध्यम से संचालित किया जा सकता है",
"Google Home": "गूगल होम",
"Action name": "क्रिया नाम",
"Google Home": "Google Home",
"Action name": "Action name",
"ScienerSmart": "विज्ञानचतुर",
"支持的语言": "समर्थित भाषाएं",
"英语": "अंग्रेज़ी",

View File

@ -1043,6 +1043,7 @@
"一键开锁": "一鍵解鎖",
"已开通": "打開",
"英文": "English",
"英文": "English",
"简体中文": "简体中文",
"繁体中文": "繁體中文",
"法语": "Français",

View File

@ -1044,23 +1044,23 @@
"导出锁数据": "ایکسپورٹ لاک ڈیٹا",
"一键开锁": "ایک کلک ان لاک",
"已开通": "کھولی",
"英文": "انگريزی",
"简体中文": "ساده چینی",
"繁体中文": "سنتی چینی",
"法语": "فرانسوی",
"俄语": "روسی",
"德语": "جرمن",
"日语": "جاپانی",
"韩语": "کوریا",
"意大利语": "ایتالیایی",
"乌克兰语": "Ukrainian",
"英文": "English",
"简体中文": "简体中文",
"繁体中文": "繁體中文",
"法语": "Français",
"俄语": "Русский",
"德语": "Deutsch",
"日语": "日本語",
"韩语": "한국어",
"意大利语": "Italiano",
"乌克兰语": "Українська",
"葡萄牙语": "Português",
"西班牙语": "Español",
"阿拉伯语": "العربية",
"越南语": "Tiếng Việt",
"马来语": "Bahasa Melayu",
"荷兰语": "Nederlands",
"罗马尼亚语": "Romunaă",
"罗马尼亚语": "Română",
"立陶宛语": "Lietuvių",
"瑞典语": "Svenska",
"爱沙尼亚语": "Eesti",

View File

@ -1163,5 +1163,6 @@
"国家地区的选择将影响数据安全,你当前选择的是": "国家地区的选择将影响数据安全,你当前选择的是",
"请确认后再继续": "请确认后再继续",
"需要相机权限": "需要相机权限",
"一键登录": "一键登录",
"网关添加成功": "网关添加成功"
}

View File

@ -283,7 +283,7 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
width: 10.sp,
)),
Obx(() => Visibility(
visible: state.isCheckVerifyEnable.value,
visible: state.isCheckVerifyEnable.value && state.currentLanguage == 'zh_CN',
child: GestureDetector(
child: SizedBox(
// width: 150.w,

View File

@ -46,7 +46,8 @@ class StarLockLoginState {
}.obs;
RxBool isCheckVerifyEnable = false.obs;
RxString currentLanguage =
CurrentLocaleTool.getCurrentLocaleString().obs; //
void onClose() {
// emailOrPhoneController.dispose();
// pwdController.dispose();

View File

@ -16,6 +16,7 @@ import 'package:star_lock/blue/io_protocol/io_updataLockSet.dart';
import 'package:star_lock/login/login/entity/LoginEntity.dart';
import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart';
import 'package:star_lock/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifiEntity.dart';
import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/gatewayConfigurationWifi_page.dart';
import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/getGatewayConfiguration_entity.dart';
import 'package:star_lock/mine/gateway/addGateway/selectGateway/getGatewayInfo_model.dart';
import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart';
@ -45,7 +46,7 @@ class ConfiguringWifiLogic extends BaseGetXController {
}
}
Future<void> updateNetworkInfo({
void updateNetworkInfo({
required String peerId,
required String wifiName,
required String secretKey,
@ -82,17 +83,19 @@ class ConfiguringWifiLogic extends BaseGetXController {
void _initReplySubscription() {
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
AppLog.log('收到蓝牙回调${EasyLoading.isShow}');
// WIFI配网结果
if (reply is GatewayConfiguringWifiResultReply) {
_replySenderConfiguringWifiResult(reply);
}
if (reply is GatewayConfiguringWifiReply) {
_replySenderConfiguringWifiResult(reply);
}
if (reply is GatewayGetStatusReply) {
_replyGatewayGetStatusReply(reply);
}
if (reply is GatewayGetStatusReply) {
_replyStatusInfo(reply);
}
// if (reply is GatewayGetStatusReply) {
// _replyStatusInfo(reply);
// }
//
if (reply is UpdataLockSetReply) {
_replyUpdataLockSetReply(reply);
@ -132,7 +135,7 @@ class ConfiguringWifiLogic extends BaseGetXController {
//
await Storage.saveLockNetWorkInfo(jsonMap);
//
updateNetworkInfo(
updateNetworkInfo(
peerId: peerId ?? '',
wifiName: wifiName ?? '',
secretKey: secretKey ?? '',
@ -482,6 +485,7 @@ class ConfiguringWifiLogic extends BaseGetXController {
@override
void dispose() {
dismissEasyLoading();
// TODO: implement dispose
super.dispose();
state.isLoading.value = false;
@ -489,5 +493,6 @@ class ConfiguringWifiLogic extends BaseGetXController {
state.loadingTimer!.cancel();
state.loadingTimer = null;
}
}
}

View File

@ -486,7 +486,7 @@ class SaveLockLogic extends BaseGetXController {
// }
void backAction() async {
// eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true));
// BlueManage().disconnect();
//
@ -503,6 +503,7 @@ class SaveLockLogic extends BaseGetXController {
'pageName': 'saveLock'
});
} else {
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
Future<void>.delayed(const Duration(seconds: 1), () {
Get.close(state.isFromMap == 1
? (CommonDataManage().seletLockType == 0 ? 4 : 5)
@ -518,6 +519,7 @@ class SaveLockLogic extends BaseGetXController {
});
}
} else {
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
Future<void>.delayed(const Duration(seconds: 1), () {
Get.close(state.isFromMap == 1
? (CommonDataManage().seletLockType == 0 ? 4 : 5)

View File

@ -143,8 +143,8 @@ class MineSetLogic extends BaseGetXController {
// UdpHelp().closeUDP();
logOut();
StoreService.to.saveLanguageCode('');
Get.updateLocale(Get.deviceLocale!);
// StoreService.to.saveLanguageCode('');
// Get.updateLocale(Get.deviceLocale!);
BlueManage().disconnect();
StartChartManage().destruction();

View File

@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/talk/starChart/constant/message_type_constant.dart';
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
@ -26,13 +27,13 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
@override
void handleReq(ScpMessage scpMessage) async {
//
replySuccessMessage(scpMessage);
//
final loginData = await Storage.getLoginData();
//
if (loginData != null &&
(talkStatus.status != TalkStatus.passiveCallWaitingAnswer && talkStatus.status!=TalkStatus.answeredSuccessfully)) {
(talkStatus.status != TalkStatus.passiveCallWaitingAnswer ||
talkStatus.status != TalkStatus.answeredSuccessfully)) {
//
final TalkReq talkReq = scpMessage.Payload;
startChartManage.FromPeerId = scpMessage.ToPeerId!;
@ -40,6 +41,12 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
startChartManage.lockPeerId = scpMessage.FromPeerId!;
//
_talkRequestEvent(talkObjectName: talkReq.callerName);
//
replySuccessMessage(scpMessage);
} else {
// ,
replyErrorMessage(scpMessage);
}
}

View File

@ -71,6 +71,15 @@ class ScpMessageBaseHandle {
messageId: scpMessage.MessageId!,
);
}
//
void replyErrorMessage(ScpMessage scpMessage) {
startChartManage.sendGenericRespErrorMessage(
ToPeerId: scpMessage.FromPeerId!,
FromPeerId: scpMessage.ToPeerId!,
PayloadType: scpMessage.PayloadType!,
messageId: scpMessage.MessageId!,
);
}
bool checkGenericRespSuccess(GenericResp genericResp) {
if (genericResp == null) return false;

View File

@ -650,10 +650,15 @@ class StartChartManage {
}
//
void sendGenericRespErrorMessage(
{required String ToPeerId,
required String FromPeerId,
required int PayloadType}) async {
void sendGenericRespErrorMessage({
required String ToPeerId,
required String FromPeerId,
required int PayloadType,
required int messageId,
}) async {
if (messageId == null) {
messageId = MessageCommand.getNextMessageId(ToPeerId, increment: false);
}
final message = MessageCommand.genericRespErrorMessage(
ToPeerId: ToPeerId,
FromPeerId: FromPeerId,

View File

@ -28,6 +28,7 @@ import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart';
import 'package:star_lock/tools/G711Tool.dart';
import 'package:star_lock/tools/bugly/bugly_tool.dart';
import '../../../../tools/baseGetXController.dart';
@ -658,42 +659,20 @@ class TalkViewLogic extends BaseGetXController {
//
Future<void> _onFrame(List<int> frame) async {
//
int maxVal = 0;
int minVal = 0;
int sum = 0;
for (int val in frame) {
maxVal = max(maxVal, val);
minVal = min(minVal, val);
sum += val;
}
double average = sum / frame.length;
AppLog.log('音频数据特征 - 最大值: $maxVal, 最小值: $minVal, 平均值: $average');
final List<int> processedFrame = preprocessAudio(frame);
//
final List<int> smoothedFrame = smoothAudio(processedFrame);
final List<int> list = listLinearToALaw(smoothedFrame);
_bufferedAudioFrames.addAll(list);
//
List<int> amplifiedFrame = _applyGain(frame, 1.6);
// G711数据
List<int> encodedData = G711Tool.encode(amplifiedFrame, 0); // 0A-law
_bufferedAudioFrames.addAll(encodedData);
final int ms = DateTime.now().millisecondsSinceEpoch -
state.startRecordingAudioTime.value.millisecondsSinceEpoch;
int getFrameLength = state.frameLength;
if (Platform.isIOS) {
getFrameLength = state.frameLength * 2;
}
if (_bufferedAudioFrames.length >= getFrameLength) {
//
int maxVal = 0;
int minVal = 255;
for (int val in _bufferedAudioFrames) {
maxVal = max(maxVal, val);
minVal = min(minVal, val);
}
AppLog.log(
'发送音频数据 - G711编码后 - 最大值: $maxVal, 最小值: $minVal, 长度: ${_bufferedAudioFrames.length}');
// UDP
await StartChartManage()
.sendTalkDataMessage(
@ -714,177 +693,27 @@ class TalkViewLogic extends BaseGetXController {
AppLog.log(error.message!);
}
//
List<int> preprocessAudio(List<int> pcmList) {
final List<int> processedList = [];
final int noiseThreshold = 300; //
//
List<int> _applyGain(List<int> pcmData, double gainFactor) {
List<int> result = List<int>.filled(pcmData.length, 0);
for (int pcmVal in pcmList) {
//
if (pcmVal.abs() < noiseThreshold) {
pcmVal = (pcmVal * 0.3).round(); //
for (int i = 0; i < pcmData.length; i++) {
// PCM数据通常是有符号的16位整数
int sample = pcmData[i];
//
double amplified = sample * gainFactor;
//
if (amplified > 32767) {
amplified = 32767;
} else if (amplified < -32768) {
amplified = -32768;
}
//
if (pcmVal.abs() > 20000) {
double factor = 1.0 - ((pcmVal.abs() - 20000) / 12768) * 0.3;
pcmVal = (pcmVal * factor).round();
}
processedList.add(pcmVal);
result[i] = amplified.toInt();
}
return processedList;
}
//
List<int> smoothAudio(List<int> pcmList) {
final List<int> smoothedList = [];
for (int i = 0; i < pcmList.length; i++) {
if (i > 0 && i < pcmList.length - 1) {
//
int avg = (pcmList[i - 1] + pcmList[i] * 2 + pcmList[i + 1]) ~/ 4;
smoothedList.add(avg);
} else {
smoothedList.add(pcmList[i]);
}
}
return smoothedList;
}
//test测试降噪算法
// List<int> preprocessAudio(List<int> pcmList) {
// final List<int> processedList = [];
// final int windowSize = 5;
// final int thresholdFactor = 2; //
// for (int i = 0; i < pcmList.length; i++) {
// int pcmVal = pcmList[i];
// //
// int sum = 0;
// int count = 0;
// for (int j = i; j < i + windowSize && j < pcmList.length; j++) {
// sum += pcmList[j];
// count++;
// }
// int mean = sum ~/ count;
// //
// int varianceSum = 0;
// for (int j = i; j < i + windowSize && j < pcmList.length; j++) {
// varianceSum += (pcmList[j] - mean) * (pcmList[j] - mean);
// }
// double standardDeviation =
// sqrt(varianceSum / count); // Use sqrt from dart:math
// //
// int dynamicThreshold = (standardDeviation * thresholdFactor).toInt();
// // 0
// if (pcmVal.abs() < dynamicThreshold) {
// pcmVal = 0;
// }
// //
// int sumFilter = 0;
// int countFilter = 0;
// for (int j = i; j < i + windowSize && j < pcmList.length; j++) {
// sumFilter += pcmList[j];
// countFilter++;
// }
// int average = sumFilter ~/ countFilter;
// processedList.add(average);
// }
// return processedList;
// }
//
List<int> adjustVolume(List<int> pcmList, double volume) {
final List<int> adjustedPcmList = <int>[];
for (final int pcmVal in pcmList) {
int adjustedPcmVal = (pcmVal * volume).round();
adjustedPcmVal = adjustedPcmVal.clamp(-32768, 32767);
adjustedPcmList.add(adjustedPcmVal);
}
return adjustedPcmList;
}
// A-law编码
List<int> listLinearToALaw(List<int> pcmList) {
// 使
final List<int> adjustedPcmList = adjustVolume(pcmList, 2.2);
// A-law编码
final List<int> aLawList = <int>[];
for (final int pcmVal in adjustedPcmList) {
final int aLawVal = linearToALaw(pcmVal);
aLawList.add(aLawVal);
}
return aLawList;
}
int linearToALaw(int pcmVal) {
const int alawMax = 0x7FFF; // 32767
const int alawBias = 0x84; // 132
int mask;
int seg;
int aLawVal;
// Handle sign
if (pcmVal < 0) {
pcmVal = -pcmVal;
mask = 0x7F; // 127 (sign bit is 1)
} else {
mask = 0xFF; // 255 (sign bit is 0)
}
// Add bias and clamp to ALAW_MAX
pcmVal += alawBias;
if (pcmVal > alawMax) {
pcmVal = alawMax;
}
// Determine segment
seg = search(pcmVal);
// Calculate A-law value
if (seg >= 8) {
aLawVal = 0x7F ^ mask; // Clamp to maximum value
} else {
final int quantized = (pcmVal >> (seg + 3)) & 0xF;
aLawVal = (seg << 4) | quantized;
aLawVal ^= 0xD5; // XOR with 0xD5 to match standard A-law table
}
return aLawVal;
}
int search(int val) {
final List<int> table = <int>[
0xFF, // Segment 0
0x1FF, // Segment 1
0x3FF, // Segment 2
0x7FF, // Segment 3
0xFFF, // Segment 4
0x1FFF, // Segment 5
0x3FFF, // Segment 6
0x7FFF // Segment 7
];
const int size = 8;
for (int i = 0; i < size; i++) {
if (val <= table[i]) {
return i;
}
}
return size;
return result;
}
}

273
lib/tools/G711Tool.dart Normal file
View File

@ -0,0 +1,273 @@
/**
* G711Tool - G.711
*
* G.711ITU-T标准
* A-lawμ-law
*
* PCM线性音频数据与G.711 A-law/μ-law格式之间的转换功能
* 16线PCM样本压缩为8位
*/
class G711Tool {
//
static const int SIGN_BIT = 0x80; // A-law字节的符号位
static const int QUANT_MASK = 0xf; //
static const int NSEGS = 8; // A-law段数
static const int SEG_SHIFT = 4; //
static const int SEG_MASK = 0x70; //
static const int BIAS = 0x84; // 线
//
/**
* μ-law到A-law的转换表
* 线PCM
*/
static final List<int> _u2a = [
// u- to A-law conversions
1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 29, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
128
];
/**
* A-law到μ-law的转换表
* 线PCM
*/
static final List<int> _a2u = [
// A- to u-law conversions
1, 3, 5, 7, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 34, 34, 35, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
127
];
/**
*
* PCM值应该映射到哪个段
*
*/
static final List<int> _segEnd = [
0xFF,
0x1FF,
0x3FF,
0x7FF,
0xFFF,
0x1FFF,
0x3FFF,
0x7FFF
];
/**
*
*
* @param val
* @param table
* @param size
* @return
*/
static int _search(int val, List<int> table, int size) {
for (int i = 0; i < size; i++) {
if (val <= table[i]) return i;
}
return size;
}
/**
* 线PCM值转换为A-law编码值
*
* :
* 1.
* 2.
* 3.
* 4. A-law值
*
* @param pcmVal 16线PCM值
* @return 8A-law编码值
*/
static int _linear2alaw(int pcmVal) {
int mask;
int seg;
int aval;
if (pcmVal >= 0) {
mask = 0xD5; // sign (7th) bit = 1
} else {
mask = 0x55; // sign bit = 0
pcmVal = -pcmVal - 1;
if (pcmVal < 0) pcmVal = 32767;
}
seg = _search(pcmVal, _segEnd, 8);
if (seg >= 8) return 0x7F ^ mask;
aval = seg << SEG_SHIFT;
if (seg < 2) {
aval |= (pcmVal >> 4) & QUANT_MASK;
} else {
aval |= (pcmVal >> (seg + 3)) & QUANT_MASK;
}
return aval ^ mask;
}
/**
* A-law编码值转换为线性PCM值
*
* :
* 1.
* 2.
* 3. 线
* 4.
*
* @param aVal 8A-law编码值
* @return 16线PCM值
*/
static int _alaw2linear(int aVal) {
int t;
int seg;
aVal ^= 0x55;
t = (aVal & QUANT_MASK) << 4;
seg = (aVal & SEG_MASK) >> SEG_SHIFT;
switch (seg) {
case 0:
t += 8;
break;
case 1:
t += 0x108;
break;
default:
t += 0x108;
t <<= seg - 1;
}
return (aVal & SIGN_BIT) != 0 ? t : -t;
}
/**
* 线PCM值转换为μ-law编码值
*
* A-law类似使
*
* @param pcmVal 16线PCM值
* @return 8μ-law编码值
*/
static int _linear2ulaw(int pcmVal) {
int mask;
int seg;
int uval;
if (pcmVal < 0) {
pcmVal = BIAS - pcmVal;
mask = 0x7F;
} else {
pcmVal += BIAS;
mask = 0xFF;
}
seg = _search(pcmVal, _segEnd, 8);
if (seg >= 8) return 0x7F ^ mask;
uval = (seg << 4) | ((pcmVal >> (seg + 3)) & 0xF);
return uval ^ mask;
}
/**
* μ-law编码值转换为线性PCM值
*
* @param uVal 8μ-law编码值
* @return 16线PCM值
*/
static int _ulaw2linear(int uVal) {
uVal = ~uVal;
int t = ((uVal & QUANT_MASK) << 3) + BIAS;
t <<= (uVal & SEG_MASK) >> SEG_SHIFT;
return (uVal & SIGN_BIT) != 0 ? (BIAS - t) : (t - BIAS);
}
/**
* A-law编码值转换为μ-law编码值
*
* 使
*
* @param aval 8A-law编码值
* @return 8μ-law编码值
*/
static int alaw2ulaw(int aval) {
aval &= 0xff;
return (aval & 0x80) != 0
? (0xFF ^ _a2u[aval ^ 0xD5])
: (0x7F ^ _a2u[aval ^ 0x55]);
}
/**
* μ-law编码值转换为A-law编码值
*
* 使
*
* @param uval 8μ-law编码值
* @return 8A-law编码值
*/
static int ulaw2alaw(int uval) {
uval &= 0xff;
return (uval & 0x80) != 0
? (0xD5 ^ (_u2a[0xFF ^ uval] - 1))
: (0x55 ^ (_u2a[0x7F ^ uval] - 1));
}
/**
* PCM数据编码为G.711
*
* @param pcm PCM数据
* @param lawFlag : 0A-law, 1μ-law
* @return G.711
*/
static List<int> encode(List<int> pcm, int lawFlag) {
List<int> code = List<int>.filled(pcm.length, 0);
if (lawFlag == 0) {
for (int i = 0; i < pcm.length; i++) {
code[i] = _linear2alaw(pcm[i]);
}
} else {
for (int i = 0; i < pcm.length; i++) {
code[i] = _linear2ulaw(pcm[i]);
}
}
return code;
}
/**
* G.711PCM格式
*
* @param code G.711
* @param lawFlag : 0A-law, 1μ-law
* @return PCM数据
*/
static List<int> decode(List<int> code, int lawFlag) {
List<int> pcm = List<int>.filled(code.length, 0);
if (lawFlag == 0) {
for (int i = 0; i < code.length; i++) {
pcm[i] = _alaw2linear(code[i]);
}
} else {
for (int i = 0; i < code.length; i++) {
pcm[i] = _ulaw2linear(code[i]);
}
}
return pcm;
}
}