public var codeCallback:((Int)->Void)?
/// 录音文件回调
public var filePathCallBack:((String?)->Void)?
+ /// 设置录音文件路径
+ public var filePath:String?
var asrList : [(String,Int)] = []
var asrText = ""
var translateList : [(String,Int)] = []
var translateText = ""
+
init() {
setupRecord()
}
config.isTTs = isTTs
config.ttsFormat = ttsFormat
- StarburstSdk.shared().setupDeviceRecord(with: nil, asrConfig: config) { config in
+ StarburstSdk.shared().setupDeviceRecord(with: filePath, asrConfig: config) { config in
DCLogger.debug("录音类型 \(config!.type == 0x00 ? "实时录音" : "通话录音")")
} recognizeText: { [weak self] model in
guard let self = self else {return}
guard let model = model else {return}
- if let text = model.textResult{
+ if let text = model.textResult,!text.isEmpty{
DCLogger.debug("asr = \(text)")
asrSplitCallback?(DCResponseModel(text: text, index: model.definiteIndex, definite: model.definite))
let msg = asrList.firstIndex (where: { (str,idx) in
asrCallback?(asrText)
}
- if let translate = model.translateResult,let text = translate.text{
+ if let translate = model.translateResult,let text = translate.text,!text.isEmpty{
DCLogger.debug("translate = \(text)")
translateSplitCallback?(DCResponseModel(text: text, index: Int(translate.definiteIndex), definite: translate.definite))
let msg = translateList.firstIndex (where: { (str,idx) in
}
/// 0x00实时录音,0x0c通话录音
- public func start(type:Int){
- asrList = []
- asrText = ""
+ public func start(type:Int,recordPath:String?){
- translateList = []
- translateText = ""
+ asrList = []
+ asrText = ""
+
+ translateList = []
+ translateText = ""
+ filePath = recordPath
+ DCLogger.debug("设置地址 \(filePath ?? "")")
setupRecord()
let config = StarburstBleAsrConfig()
--- /dev/null
+//
+// DCCallRecord.swift
+// Example
+//
+// Created by liangshi on 2025/12/30.
+//
+
+import StarburstSdk
+
+public class DCCallRecord {
+ public static let shared = DCCallRecord()
+ /// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
+ public var fromLanguage:String = "auto_lang"
+ /// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
+ public var toLanguage:String = "auto_lang"
+ /// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
+ public var isTranslate = false
+ /// 是否进⾏Tts,默认false
+ public var isTTs = false
+ /// 默认pcm ⽀持pcm / ogg_opus / mp3
+ public var ttsFormat = "mp3"
+ /// 识别回调
+ public var asrCallback:((String)->Void)?
+
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 录音文件回调
+ public var filePathCallBack:((String?)->Void)?
+ /// 设置录音文件路径
+ public var filePath:String?
+
+ var asrList : [(String,Int)] = []
+ var asrText = ""
+
+
+
+ init() {
+ setupRecord()
+ }
+
+ func setupRecord(){
+ let config = StarburstAsrConfig()
+ config.isTranslate = isTranslate
+ config.fromLanguage = fromLanguage
+ config.toLanguage = toLanguage
+ config.isTTs = isTTs
+ config.ttsFormat = ttsFormat
+
+ StarburstSdk.shared().setupDeviceRecord(with: filePath, asrConfig: config) { config in
+ DCLogger.debug("录音类型 \(config!.type == 0x00 ? "实时录音" : "通话录音")")
+ } recognizeText: { [weak self] model in
+ guard let self = self else {return}
+ guard let model = model else {return}
+
+ if let text = model.textResult,!text.isEmpty{
+ DCLogger.debug("asr = \(text)")
+ let msg = asrList.firstIndex (where: { (str,idx) in
+ return idx == model.definiteIndex;
+ })
+ if (msg == nil) {
+ asrList.append((text,model.definiteIndex))
+ } else {
+ asrList[msg!] = (text,model.definiteIndex)
+ }
+ asrText = asrList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ asrCallback?(asrText)
+ }
+ } stateChange: { [weak self] code in
+ DCLogger.debug("状态改变",code)
+ self?.codeCallback?(code.rawValue)
+ } finished: {[weak self] filePath in
+ DCLogger.debug("文件录音保存路径 \(filePath ?? "")")
+ self?.filePathCallBack?(filePath)
+ }
+ }
+
+ /// 0x00实时录音,0x0c通话录音
+ public func start(type:Int,recordPath:String?){
+
+ asrList = []
+ asrText = ""
+
+ filePath = recordPath
+ DCLogger.debug("设置地址 \(filePath ?? "")")
+
+ setupRecord()
+ let config = StarburstBleAsrConfig()
+ config.type = type
+ StarburstSdk.shared().startDeviceRecord(config)
+
+ }
+ public func stop(){
+ StarburstSdk.shared().stopDeviceRecord()
+ }
+}
}
extension DCChat{
public func getVcSpeekerList(finished:@escaping ([DCRole]?,Bool)->Void){
- StarburstSdk.shared().getVcSpeekerList { [weak self] (list, success) in
- guard let self = self else { return }
+ StarburstSdk.shared().getVcSpeekerList { (list, success) in
if success,let list = list {
var temp = [DCRole]()
for item in list {
- var role = DCRole()
+ let role = DCRole()
role.sid = item.sid
role.name = item.name
role.type = item.type
let sender = BleSender()
sender.data = total
- sender.completion = { result in
+ sender.completion = {[weak self] result in
DCLogger.debug("\(result.description)")
if result.isSuccess{
finished(true)
}
else{
+ DCLogger.debug("握手失败")
finished(false)
+ self?.handShake(finished: finished)
}
}
DCBleManager.shared.send(sender)
guard let self = self else {return}
guard let model = model else {return}
- if let text = model.textResult{
+ if let text = model.textResult,!text.isEmpty{
DCLogger.debug("asr = \(text)")
let msg = asrList.firstIndex (where: { (str,idx) in
return idx == model.definiteIndex;
asrCallback?(asrText)
}
- if let translate = model.translateResult,let text = translate.text{
+ if let translate = model.translateResult,let text = translate.text,!text.isEmpty{
DCLogger.debug("translate = \(text)")
let msg = translateList.firstIndex (where: { (str,idx) in
return idx == translate.definiteIndex;
StarburstConfig.shared().enableEarbudsSwitchSync = true
//耳机仓表情下发开关
StarburstConfig.shared().enableEmotionSyncToDevice = false
+ // 通话录音声道数。1:单声道 ;2:⽴体声;默认单声道
+ StarburstConfig.shared().callRecordChannel = 2
//添加调试信息
// StarburstConfig.shared().debugInfo = [
// "x-use-ppe":"1",
let format = DateFormatter()
format.dateFormat = "yyyyMMddHHmmss"
let text = format.string(from: Date())
- return NSHomeDirectory() + "/Documents/\(text).log"
+ return NSHomeDirectory() + "/Documents/StarburstSdk_\(text).log"
}
}
}
public func sumary(text:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
+
StarburstSdk.shared().summaryByText(withSplit: text) { model in
guard let model = model else{return}
finished((model.llmResponse,model.complete))
} error: { error in
finished(nil)
}
-
-
+ }
+ public func cancelTranslateByTextWithSplit(){
+ StarburstSdk.shared().cancelTranslateByTextWithSplit()
+ }
+ public func cancelSummaryByTextWithSplit(){
+ StarburstSdk.shared().cancelSummaryByTextWithSplit()
+ }
+ public func getDeviceName()->String?{
+ let dn = StarburstSdk.shared().getDeviceName()
+ return dn
}
}
"$(PROJECT_DIR)/ShenYin/Sdk/DcSdk/opus/code_opus/lib",
);
MARKETING_VERSION = 1.0.2;
- PRODUCT_BUNDLE_IDENTIFIER = com.deepchords.app1;
+ PRODUCT_BUNDLE_IDENTIFIER = com.deepchords.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
"$(PROJECT_DIR)/ShenYin/Sdk/DcSdk/opus/code_opus/lib",
);
MARKETING_VERSION = 1.0.2;
- PRODUCT_BUNDLE_IDENTIFIER = com.deepchords.app1;
+ PRODUCT_BUNDLE_IDENTIFIER = com.deepchords.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
Logger.debug(DCFolder.user)
Logger.debug(DCFolder.record)
self.window?.rootViewController = BaseTC()
- if CCAiManager.isJoy {
- JoySdkManager.shared.setupSdk()
- }
- else{
- DcSdkManager.shared.initSdk()
- }
}
func goToLogin(){
window?.rootViewController = BaseNC(rootViewController: LoginVC())
//
// Created by liangshi on 2025/12/25.
//
-import JoyGemAI
-import DeepChordsSdk
+
class CCAiManager {
- static var isJoy = false
-
- static func translate(text:String,from:String,to:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
- if isJoy {
- JoyGemAIManager.shared().cancelTranslateRequest()
- JoyGemAIManager.shared().translate(text, from: from, to: to) { result, finish in
- finished((result,finish))
- } error: { error in
- finished(nil)
- }
- }
- else{
- DeepChordsAiSdk.shared.translate(text: text, from: from, to: to) { result in
- finished(result)
- }
- }
- }
- static func summary(text:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
- if isJoy {
- JoyGemAIManager.shared().cancelSummaryRequest()
- JoyGemAIManager.shared().summary(text) { text, finish in
- finished((text,finish))
- } error: { error in
- finished(nil)
- }
- }
- else{
- DeepChordsAiSdk.shared.sumary(text: text) { result in
- finished(result)
- }
- }
- }
+
}
extension CCAiManager{
static func preparePlayBlueTooth(){
//
import Foundation
-import JoyGemAI
enum CCAiLanguage:String{
case chinse = "chinse"
static var chinse2english:[CCAiLanguage]{
return [.chinse,.english]
}
- static var translate:[CCAiLanguage]{
- return [.chinse,.english,.japanese,.korean,.french,.spanish,.portuguese,.indonesian,.russian,.malay,German,Filipino,thai,Arabic,Vietnam]
+ static var all:[CCAiLanguage]{
+ let list = [.chinse,.english,.japanese,.korean,.french,.spanish,.portuguese,.indonesian,.russian,.malay,German,Filipino,thai,Arabic,Vietnam]
+// Logger.debug(list.map{$0.value})
+ return list
}
var title:String{
switch self {
return "越南文".l10n
}
}
+// var value:String{
+// switch self {
+// case .chinse:
+// return kJoyGemAILocalizationZH
+// case .english:
+// return kJoyGemAILocalizationEN
+// case .japanese:
+// return kJoyGemAILocalizationJA
+// case .korean:
+// return kJoyGemAILocalizationKO
+// case .french:
+// return kJoyGemAILocalizationFR
+// case .spanish:
+// return kJoyGemAILocalizationES
+// case .portuguese:
+// return kJoyGemAILocalizationPT
+// case .indonesian:
+// return kJoyGemAILocalizationID
+// case .russian:
+// return kJoyGemAILocalizationRU_Target
+// case .malay:
+// return kJoyGemAILocalizationMS
+// case .German:
+// return kJoyGemAILocalizationDE
+// case .Filipino:
+// return kJoyGemAILocalizationFIL
+// case .thai:
+// return kJoyGemAILocalizationTH
+// case .Arabic:
+// return kJoyGemAILocalizationAR
+// case .Vietnam:
+// return kJoyGemAILocalizationVI
+// }
+// }
var value:String{
switch self {
case .chinse:
- return kJoyGemAILocalizationZH
+ return "zh-CN"
case .english:
- return kJoyGemAILocalizationEN
+ return "en-US"
case .japanese:
- return kJoyGemAILocalizationJA
+ return "ja-JP"
case .korean:
- return kJoyGemAILocalizationKO
+ return "ko-KR"
case .french:
- return kJoyGemAILocalizationFR
+ return "fr-FR"
case .spanish:
- return kJoyGemAILocalizationES
+ return "es-MX"
case .portuguese:
- return kJoyGemAILocalizationPT
+ return "pt-BR"
case .indonesian:
- return kJoyGemAILocalizationID
+ return "id-ID"
case .russian:
- return kJoyGemAILocalizationRU_Target
+ return "ru"
case .malay:
- return kJoyGemAILocalizationMS
+ return "ms-MY"
case .German:
- return kJoyGemAILocalizationDE
+ return "de-DE"
case .Filipino:
- return kJoyGemAILocalizationFIL
+ return "fil-PH"
case .thai:
- return kJoyGemAILocalizationTH
+ return "th-TH"
case .Arabic:
- return kJoyGemAILocalizationAR
+ return "ar-SA"
case .Vietnam:
- return kJoyGemAILocalizationVI
+ return "vi"
}
}
}
}
Logger.debug(peripheral)
- if CCAiManager.isJoy{
- let mac = JoySdkManager.getMac(advertisementData) ?? ""
+ if let name = peripheral.name,name.hasPrefix("AI") {
+ let mac = DcSdkManager.getMac(advertisementData) ?? ""
devices.append(DCPeripheral(device: peripheral,mac: mac))
discoverDeviceCallback?(devices)
}
else{
- let mac = DcSdkManager.getMac(advertisementData) ?? ""
+ let mac = JoySdkManager.getMac(advertisementData) ?? ""
devices.append(DCPeripheral(device: peripheral,mac: mac))
discoverDeviceCallback?(devices)
}
+// if CCDevice.isJoy{
+// let mac = JoySdkManager.getMac(advertisementData) ?? ""
+// devices.append(DCPeripheral(device: peripheral,mac: mac))
+// discoverDeviceCallback?(devices)
+// }
+// else{
+// let mac = DcSdkManager.getMac(advertisementData) ?? ""
+// devices.append(DCPeripheral(device: peripheral,mac: mac))
+// discoverDeviceCallback?(devices)
+// }
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
stopScanDevice()
Logger.debug("蓝牙已连接 \(peripheral)")
peripheral.delegate = self
- if CCAiManager.isJoy{
+ if CCDevice.isJoy{
peripheral.discoverServices([CBUUID(string: JoySdkManager.serviceUUID),CBUUID(string: OtaMananger.otaServiceUUId)]);
}
else{
Logger.debug("蓝牙已断开 \(peripheral)")
YLprogressHUD.showAutoHiden("蓝牙已断开".l10n)
self.isConnetd = false
- if CCAiManager.isJoy{
+ if CCDevice.isJoy{
DCBleManager.shared.centralManager(central, didDisconnectPeripheral: peripheral, error: nil)
}
NotificationManager.post(type: .deviceValidChange, objtect: nil)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
- if CCAiManager.isJoy{
+ if CCDevice.isJoy{
if (service.uuid.uuidString == JoySdkManager.serviceUUID) {
JoySdkManager.shared.peripheral(peripheral, didDiscoverCharacteristicsFor: service, error: error)
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: (any Error)?) {
- if CCAiManager.isJoy{
+ if CCDevice.isJoy{
if (characteristic.isNotifying == true && characteristic.service?.uuid.uuidString == JoySdkManager.serviceUUID && characteristic.uuid.uuidString == JoySdkManager.notifyUUID) {
Logger.debug("特征使能成功")
JoySdkManager.shared.bleConnected()
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
// Logger.debug("收到数据 ===uUId ",characteristic.uuid)
- if CCAiManager.isJoy{
+ if CCDevice.isJoy{
if OtaMananger.isOtadata(characteristic){
if let _ = characteristic.value,error == nil {
OtaMananger.shared.otaManager.peripheral(peripheral, didUpdateValueFor: characteristic)
// devices.append(DCPeripheral(device: item,mac: mac))
// }
// }
- if CCAiManager.isJoy{
+ if CCDevice.isJoy{
centralManager.scanForPeripherals(withServices: [CBUUID(string: JoySdkManager.serviceUUID)],options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
}
else{
func connectPeripheral(_ peripheral: DCPeripheral) {
connectPeripheral = peripheral
- Logger.debug("连接中...")
+ if let name = peripheral.device.name,name.hasPrefix("AI") {
+ CCDevice.isJoy = false
+ }
+ else{
+ CCDevice.isJoy = true
+ }
+ CCDevice.initSdk()
+ Logger.debug(peripheral.device.name ?? "","连接中...")
centralManager.connect(peripheral.device, options: [CBConnectPeripheralOptionEnableTransportBridgingKey:true])
}
// Created by liangshi on 2025/12/25.
//
import JoyGemAI
-
-enum ModeEffectsType:Int{
- case normal
- case fashion
- case classic
- case rock
- case jazz
- case custom
-
- var title:String{
- switch self {
- case .normal:
- return "正常".l10n
- case .fashion:
- return "流行".l10n
- case .classic:
- return "经典".l10n
- case .rock:
- return "摇滚".l10n
- case .jazz:
- return "爵士".l10n
- case .custom:
- return "自定义".l10n
+import DeepChordsSdk
+class CCDevice{
+ static var isJoy = true
+ static func initSdk(){
+ if CCDevice.isJoy {
+ JoySdkManager.shared.setupSdk()
}
- }
- var img:String{
- switch self {
- case .normal:
- return "mode_normal"
- case .fashion:
- return "mode_fashion"
- case .classic:
- return "mode_classic"
- case .rock:
- return "mode_rock"
- case .jazz:
- return "mode_jazz"
- case .custom:
- return "mode_custom"
+ else{
+ DcSdkManager.shared.initSdk()
}
}
- var value:JoyGemEQMode{
- switch self {
- case .normal:
- return .normal
- case .fashion:
- return .pop
- case .classic:
- return .classic
- case .rock:
- return .rock
- case .jazz:
- return .jazz
- case .custom:
- return .custom
+ static func translate(text:String,from:String,to:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
+ if isJoy {
+ JoyGemAIManager.shared().cancelTranslateRequest()
+ JoyGemAIManager.shared().translate(text, from: from, to: to) { result, finish in
+ finished((result,finish))
+ } error: { error in
+ finished(nil)
+ }
+ }
+ else{
+ DeepChordsAiSdk.shared.cancelTranslateByTextWithSplit()
+ DeepChordsAiSdk.shared.translate(text: text, from: from, to: to) { result in
+ finished(result)
+ }
}
}
-
- static var all:[ModeEffectsType]{
- return [.normal,.fashion,.classic,.rock,.jazz,.custom]
- }
-}
-
-enum FindType:Int{
- case left
- case right
- case all
- case cancel
- var value:JoyGemFindHeadphoneMode{
- switch self {
- case .left:
- return .left
- case .right:
- return .right
- case .cancel:
- return .cancel
- case .all:
- return .all
+ static func summary(text:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
+ if isJoy {
+ JoyGemAIManager.shared().cancelSummaryRequest()
+ JoyGemAIManager.shared().summary(text) { text, finish in
+ finished((text,finish))
+ } error: { error in
+ finished(nil)
+ }
+ }
+ else{
+ DeepChordsAiSdk.shared.cancelSummaryByTextWithSplit()
+ DeepChordsAiSdk.shared.sumary(text: text) { result in
+ finished(result)
+ }
}
}
}
-
-class CCDevice{
+extension CCDevice{
static func findHeadphone(_ mode:FindType){
- JoyGemAIManager.shared().device.findHeadphone(mode.value) { err in
- Logger.debug("findHeadphone:\(err)");
+ if CCDevice.isJoy {
+ var value:JoyGemFindHeadphoneMode = .all
+ switch mode {
+ case .left:
+ value = .left
+ case .right:
+ value = .right
+ case .cancel:
+ value = .cancel
+ case .all:
+ value = .all
+ }
+ JoyGemAIManager.shared().device.findHeadphone(value) { err in
+ Logger.debug("findHeadphone:\(err)");
+ }
+ }
+ else{
+ let value:UInt8 = mode == .cancel ? 0:1
+ DCDevice.shared.findDevice(state: value) { result in
+ }
}
}
static func getEQMode(finished:@escaping (ModeEffectsType?)->Void){
- JoyGemAIManager.shared().device.getEQMode { mode in
- let type = ModeEffectsType.all.first(where: {$0.value == mode}) ?? .normal
- finished(type)
- } error: { err in
- Logger.debug("getEQMode:\(err)");
- finished(nil)
+ if CCDevice.isJoy {
+ JoyGemAIManager.shared().device.getEQMode { mode in
+ var value:ModeEffectsType = .normal
+ switch mode {
+ case .normal:
+ value = .normal
+ case .pop:
+ value = .pop
+ case .classic:
+ value = .classic
+ case .rock:
+ value = .rock
+ case .jazz:
+ value = .jazz
+ case .custom:
+ value = .custom
+ }
+ finished(value)
+ } error: { err in
+ Logger.debug("getEQMode:\(err)");
+ finished(nil)
+ }
+ }
+ else{
+ /// type, 0x00(正常模式)
+ // 0x01(流行)
+ // 0x02(经典)
+ // 0x03(爵士)
+ // 0x04(摇滚)
+ // 0x05(自定义)
+ DCDevice.shared.getEQ { (arg0,result) in
+ guard let (type,list) = arg0 else{
+ finished(nil)
+ return
+ }
+ switch type{
+ case 0:
+ finished(.normal)
+ case 1:
+ finished(.pop)
+ case 2:
+ finished(.classic)
+ case 3:
+ finished(.jazz)
+ case 4:
+ finished(.rock)
+ case 5:
+ finished(.custom)
+ default:
+ finished(nil)
+ }
+ }
}
}
static func setEQMode(_ type:ModeEffectsType){
- JoyGemAIManager.shared().device.setEQMode(type.value) { err in
- Logger.debug("setEQMode:\(err)");
+ if CCDevice.isJoy {
+ var value:JoyGemEQMode = .normal
+ switch type {
+ case .normal:
+ value = .normal
+ case .pop:
+ value = .pop
+ case .classic:
+ value = .classic
+ case .rock:
+ value = .rock
+ case .jazz:
+ value = .jazz
+ case .custom:
+ value = .custom
+ }
+
+ JoyGemAIManager.shared().device.setEQMode(value) { err in
+ Logger.debug("setEQMode:\(err)");
+ }
+ }else{
+ let value:UInt8 = UInt8(type.rawValue)
+ DCDevice.shared.setEQ(type: value) { success in
+
+ }
}
}
static func getCustomEQ(finished:@escaping ([NSNumber]?)->Void){
- JoyGemAIManager.shared().device.getCustomEQ { eq in
- Logger.debug("getCustomEQ:\(eq)");
- finished(eq.bands)
- } error: { err in
- Logger.debug("getCustomEQ:\(err)");
- finished(nil)
+ if CCDevice.isJoy {
+ JoyGemAIManager.shared().device.getCustomEQ { eq in
+ Logger.debug("getCustomEQ:\(eq)");
+ finished(eq.bands)
+ } error: { err in
+ Logger.debug("getCustomEQ:\(err)");
+ finished(nil)
+ }
+ }
+ else{
+ DCDevice.shared.getEQ { (arg0,result) in
+ guard let (type,list) = arg0 else{
+ finished(nil)
+ return
+ }
+ if type == 5{
+ let nums = list.map { NSNumber(value: $0) }
+ finished(nums)
+ }
+ else{
+ finished(nil)
+ }
+ }
}
}
static func resetCustomEQ(){
- JoyGemAIManager.shared().device.resetCustomEQ { err in
- Logger.debug("resetCustomEQ:\(err)");
+ if CCDevice.isJoy {
+ JoyGemAIManager.shared().device.resetCustomEQ { err in
+ Logger.debug("resetCustomEQ:\(err)");
+ }
+ }
+ else{
+ let list = [
+ 0,0,0,0,0,0,0,0,0,0,0,0
+ ]
+ let dispatchGroup = DispatchGroup()
+ for (index,item) in list.enumerated() {
+ dispatchGroup.enter()
+ DCDevice.shared.setCustomEQ(index: UInt8(index), value: item) {result in
+ dispatchGroup.leave()
+ }
+ }
+ dispatchGroup.notify(queue:.main) {
+ DCDevice.shared.setEQ(type: 0x05) {result in
+ }
+ }
}
}
static func setCustomEQ(index:Int,value:Int){
- JoyGemAIManager.shared().device.setCustomEQ(UInt(index), withGain: value) { err in
- Logger.debug("setCustomEQ:\(err)");
+ if CCDevice.isJoy {
+ JoyGemAIManager.shared().device.setCustomEQ(UInt(index), withGain: value) { err in
+ Logger.debug("setCustomEQ:\(err)");
+ }
+ }
+ else{
+// DCDevice.shared.setCustomEQ(index: UInt8(index), value: value) {result in
+// }
}
}
}
extension CCDevice{
- static func getMac(finished:@escaping ((_ mac:String?)->Void)) {
- JoyGemAIManager.shared().device.macAddress { edr, ble in
- Logger.debug("edr:\(edr),ble:\(ble)");
- finished(edr.uppercased())
- } error: { error in
- Logger.debug("\(error!.localizedDescription)")
- finished(nil)
- }
- }
+// static func getMac(finished:@escaping ((_ mac:String?)->Void)) {
+// if CCDevice.isJoy {
+// JoyGemAIManager.shared().device.macAddress { edr, ble in
+// Logger.debug("edr:\(edr),ble:\(ble)");
+// finished(edr.uppercased())
+// } error: { error in
+// Logger.debug("\(error!.localizedDescription)")
+// finished(nil)
+// }
+// }
+// else{
+//// DCDevice.shared.getSoftVersion {result in
+//// finished(result)
+//// }
+// }
+// }
static func getDN(finished:@escaping ((_ mac:String?)->Void)) {
- JoyGemAIManager.shared().device.getDN { deviceName in
- finished(deviceName)
- } error: { error in
- Logger.debug("获取dn失败","\(error!.localizedDescription)")
- finished(nil)
+ if CCDevice.isJoy {
+ JoyGemAIManager.shared().device.getDN { deviceName in
+ finished(deviceName)
+ } error: { error in
+ Logger.debug("获取dn失败","\(error!.localizedDescription)")
+ finished(nil)
+ }
+ }
+ else{
+ let dn = DeepChordsAiSdk.shared.getDeviceName()
+ finished(dn)
}
}
static func getVersion(finished:@escaping ((_ version:String?)->Void)) {
- JoyGemAIManager.shared().device.software { version in
- finished(version)
- } error: { error in
- Logger.debug("\(error!.localizedDescription)");
- finished(nil)
+ if CCDevice.isJoy {
+ JoyGemAIManager.shared().device.software { version in
+ finished(version)
+ } error: { error in
+ Logger.debug("\(error!.localizedDescription)");
+ finished(nil)
+ }
+ }
+ else{
+ DCDevice.shared.getSoftVersion {result in
+ finished(result)
+ }
}
}
}
class CCPage{
static func gotoChat(){
- if CCAiManager.isJoy {
+ if CCDevice.isJoy {
App.shared.goToPage(JoyChatVC())
}
else{
}
}
static func gotoFieldRecord(){
- if CCAiManager.isJoy {
+ if CCDevice.isJoy {
App.shared.goToPage(JoyXclyVC())
}
else{
}
}
static func gotoCallRecord(){
- if CCAiManager.isJoy {
+ if CCDevice.isJoy {
if JoySdkManager.shared.callRecord.supportStereo{
App.shared.goToPage(JoyStereoCallVC())
}
}
else{
// if JoySdkManager.shared.callRecord.supportStereo{
-// App.shared.goToPage(JoyStereoCallVC())
+// App.shared.goToPage(DcStereoCallVC())
// }
// else{
App.shared.goToPage(DcCallingRecordVC())
}
}
static func gotoChinese2Enlgish(){
- if CCAiManager.isJoy {
+ if CCDevice.isJoy {
App.shared.goToPage(JoyChinese2EnglishVC())
}
else{
}
}
static func gotoTcty(){
- if CCAiManager.isJoy {
+ if CCDevice.isJoy {
App.shared.goToPage(JoyTctyVC())
}
else{
}
}
static func gotoDialogTranslate(){
- if CCAiManager.isJoy {
+ if CCDevice.isJoy {
App.shared.goToPage(JoyDialogTranslateVC())
}
else{
}
extension DcSdkManager{
static func getMac(_ dict:[String:Any])->String?{
-
if let advMsd = dict[CBAdvertisementDataManufacturerDataKey] as? Data {
if (advMsd.count >= 6) {
let mac = advMsd;
override init(){
super.init()
-
-
}
func setupSdk(){
recordText = text
recordNeedReloadData?(text)
}
- // DCBleRecord.shared.translateCallback = { [weak self] text in
- // guard let self = self else{return}
- // self.toTextView.text = text
- // let range = NSMakeRange(toTextView.text.count - 1, 1)
- // self.toTextView.scrollRangeToVisible(range)
- // }
DCBleRecord.shared.codeCallback = { [weak self] code in
guard let self = self else{return}
codeCallback?(code)
}
DCBleRecord.shared.filePathCallBack = { [weak self] path in
guard let self = self else{return}
- // self.recordBtn.isSelected = false
if recordText.isEmpty{
return
}
return
}
Logger.debug("开启通话录音")
- DCBleRecord.shared.start(type: 0x00 )
+ DCBleRecord.shared.start(type: 0x00, recordPath: nil )
}
func recordResume(){
// JoyGemRecordManager.shared().resume()
var recordNeedReloadData:((String)->Void)?
var recordList : [(String,UInt)] = []
var recordText = ""
+ private var pausText = ""
+ private var recordPath:String?
+ private var wavPath:String?
/// 状态码回调
public var codeCallback:((Int)->Void)?
func setupSdk(){
DCBleRecord.shared.asrCallback = { [weak self] text in
guard let self = self else{return}
- recordText = text
- recordNeedReloadData?(text)
+ recordText = pausText + text
+ recordNeedReloadData?(recordText)
}
DCBleRecord.shared.codeCallback = { [weak self] code in
guard let self = self else{return}
}
DCBleRecord.shared.filePathCallBack = { [weak self] path in
guard let self = self else{return}
- // self.recordBtn.isSelected = false
if recordText.isEmpty{
return
}
}
let path1 = OpusTool.opusFile(toWAVFile: path)
guard let wavPath = DCFolder.recordFileResave(srcPath: path1) else{return}
+ self.wavPath = wavPath
+ if path == recordPath {
+ return
+ }
recordFinish?(wavPath)
}
}
Logger.debug("开启录音")
recordList.removeAll()
recordText = ""
+ pausText = ""
+ wavPath = nil
setupSdk()
- DCBleRecord.shared.start(type: 0x0c )
+ recordPath = DcXcly.getFilePath()
+ DCBleRecord.shared.start(type: 0x0c, recordPath: recordPath )
}
func recordResume(){
-// JoyGemRecordManager.shared().resume()
+ wavPath = nil
+ pausText = recordText
+ DCBleRecord.shared.start(type: 0x0c, recordPath: recordPath )
}
func recordPause(){
-// JoyGemRecordManager.shared().pause()
+ DCBleRecord.shared.stop()
}
func recordStop(){
+ recordPath = nil
DCBleRecord.shared.stop()
+ if let path = wavPath {
+ recordFinish?(path)
+ }
+ }
+}
+
+extension DcXcly{
+ static func getFilePath()->String?{
+ // 获取缓存目录路径
+ guard let cacheDirectory = FileManager.default.urls(for:.cachesDirectory, in:.userDomainMask).first else {
+ print("无法获取缓存目录")
+ return nil
+ }
+ // 构建压缩文件路径
+ let name = "\(Int(Date().timeIntervalSince1970*1000)).opus"
+ let path = cacheDirectory.appendingPathComponent(name).path
+ return path
}
}
DCBleRecord.shared.toLanguage = toolBar.languageView.rightItem.language.value
DCBleRecord.shared.isTranslate = true
DCBleRecord.shared.isTTs = true
- DCBleRecord.shared.start(type: 0x00)
+ DCBleRecord.shared.start(type: 0x00,recordPath: nil)
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker])
}
func setupSdk(){
- JoySdkManager.shared.callRecord.recordFinish = {[weak self] path in
- guard let self = self else { return }
- if !needSave {
- return
- }
- let v = PopTextField()
- v.show()
- v.cancelTap = {
- App.shared.popPage()
- }
- v.okTap = { [weak self] text in
- guard let self = self else{return}
- gotoDetail(fileName: text, wavPath: path, language: toolBar.leftItem.language)
- }
- }
- JoySdkManager.shared.callRecord.stereoNeedReloadData = {[weak self] (text,index) in
- guard let self = self else { return }
- if (index == 1) {
- selfTextView.text = text
- selfTextView.scrollToBottom()
- } else if (index == 2) {
- otherTextView.text = text
- otherTextView.scrollToBottom()
- }
- }
- JoySdkManager.shared.callRecord.callRecordAutoFinish = {[weak self] in
- guard let self = self else { return }
- stopAction()
- }
- JoySdkManager.shared.callRecord.callRecordNotOnCall = {[weak self] in
- guard let self = self else { return }
- YLprogressHUD.showAutoHiden("未处于通话状态".l10n)
- rhythView.reset()
- toolBar.recordBtn.isSelected = false
- toolBar.leftItem.alpha = 1
- }
- if autoStart{
- startRecord()
- }
+// JoySdkManager.shared.callRecord.recordFinish = {[weak self] path in
+// guard let self = self else { return }
+// if !needSave {
+// return
+// }
+// let v = PopTextField()
+// v.show()
+// v.cancelTap = {
+// App.shared.popPage()
+// }
+// v.okTap = { [weak self] text in
+// guard let self = self else{return}
+// gotoDetail(fileName: text, wavPath: path, language: toolBar.leftItem.language)
+// }
+// }
+// JoySdkManager.shared.callRecord.stereoNeedReloadData = {[weak self] (text,index) in
+// guard let self = self else { return }
+// if (index == 1) {
+// selfTextView.text = text
+// selfTextView.scrollToBottom()
+// } else if (index == 2) {
+// otherTextView.text = text
+// otherTextView.scrollToBottom()
+// }
+// }
+// JoySdkManager.shared.callRecord.callRecordAutoFinish = {[weak self] in
+// guard let self = self else { return }
+// stopAction()
+// }
+// JoySdkManager.shared.callRecord.callRecordNotOnCall = {[weak self] in
+// guard let self = self else { return }
+// YLprogressHUD.showAutoHiden("未处于通话状态".l10n)
+// rhythView.reset()
+// toolBar.recordBtn.isSelected = false
+// toolBar.leftItem.alpha = 1
+// }
+// if autoStart{
+// startRecord()
+// }
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
func start(){
startIndex += 100000
- // JoyGemSIManager.shared().originalLanguage = bar.leftItem.language.value
- // JoyGemSIManager.shared().targetLanguage = bar.rightItem.language.value
+// JoyGemSIManager.shared().originalLanguage = kJoyGemAILocalizationAuto
+// JoyGemSIManager.shared().targetLanguage = kJoyGemAILocalizationAuto
JoyGemSIManager.shared().start()
// do {
// try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker])
+++ /dev/null
-////
-//// CCDevice.swift
-//// ShenYin
-////
-//// Created by liangshi on 2025/12/5.
-////
-//import JoyGemAI
-//
-//enum ModeEffectsType:Int{
-// case normal
-// case fashion
-// case classic
-// case rock
-// case jazz
-// case custom
-//
-// var title:String{
-// switch self {
-// case .normal:
-// return "正常".l10n
-// case .fashion:
-// return "流行".l10n
-// case .classic:
-// return "经典".l10n
-// case .rock:
-// return "摇滚".l10n
-// case .jazz:
-// return "爵士".l10n
-// case .custom:
-// return "自定义".l10n
-// }
-// }
-// var img:String{
-// switch self {
-// case .normal:
-// return "mode_normal"
-// case .fashion:
-// return "mode_fashion"
-// case .classic:
-// return "mode_classic"
-// case .rock:
-// return "mode_rock"
-// case .jazz:
-// return "mode_jazz"
-// case .custom:
-// return "mode_custom"
-// }
-// }
-// var value:JoyGemEQMode{
-// switch self {
-// case .normal:
-// return .normal
-// case .fashion:
-// return .pop
-// case .classic:
-// return .classic
-// case .rock:
-// return .rock
-// case .jazz:
-// return .jazz
-// case .custom:
-// return .custom
-// }
-// }
-//
-// static var all:[ModeEffectsType]{
-// return [.normal,.fashion,.classic,.rock,.jazz,.custom]
-// }
-//}
-//
-//enum FindType:Int{
-// case left
-// case right
-// case all
-// case cancel
-// var value:JoyGemFindHeadphoneMode{
-// switch self {
-// case .left:
-// return .left
-// case .right:
-// return .right
-// case .cancel:
-// return .cancel
-// case .all:
-// return .all
-// }
-// }
-//}
-//
-//class CCDevice{
-// static func findHeadphone(_ mode:FindType){
-// JoyGemAIManager.shared().device.findHeadphone(mode.value) { err in
-// Logger.debug("findHeadphone:\(err)");
-// }
-// }
-// static func getEQMode(finished:@escaping (ModeEffectsType?)->Void){
-// JoyGemAIManager.shared().device.getEQMode { mode in
-// let type = ModeEffectsType.all.first(where: {$0.value == mode}) ?? .normal
-// finished(type)
-// } error: { err in
-// Logger.debug("getEQMode:\(err)");
-// finished(nil)
-// }
-// }
-// static func setEQMode(_ type:ModeEffectsType){
-// JoyGemAIManager.shared().device.setEQMode(type.value) { err in
-// Logger.debug("setEQMode:\(err)");
-// }
-// }
-//
-//
-// static func getCustomEQ(finished:@escaping ([NSNumber]?)->Void){
-// JoyGemAIManager.shared().device.getCustomEQ { eq in
-// Logger.debug("getCustomEQ:\(eq)");
-// finished(eq.bands)
-// } error: { err in
-// Logger.debug("getCustomEQ:\(err)");
-// finished(nil)
-// }
-// }
-// static func resetCustomEQ(){
-// JoyGemAIManager.shared().device.resetCustomEQ { err in
-// Logger.debug("resetCustomEQ:\(err)");
-// }
-// }
-// static func setCustomEQ(index:Int,value:Int){
-// JoyGemAIManager.shared().device.setCustomEQ(UInt(index), withGain: value) { err in
-// Logger.debug("setCustomEQ:\(err)");
-// }
-// }
-//}
-//extension CCDevice{
-// static func getMac(finished:@escaping ((_ mac:String?)->Void)) {
-// JoyGemAIManager.shared().device.macAddress { edr, ble in
-// Logger.debug("edr:\(edr),ble:\(ble)");
-// finished(edr.uppercased())
-// } error: { error in
-// Logger.debug("\(error!.localizedDescription)")
-// finished(nil)
-// }
-// }
-// static func getDN(finished:@escaping ((_ mac:String?)->Void)) {
-// // DispatchQueue.main.asyncAfter(deadline:.now() + 2) {
-// // print("延迟2秒后执行")
-// //
-// // }
-// JoyGemAIManager.shared().device.getDN { deviceName in
-// finished(deviceName)
-// } error: { error in
-// Logger.debug("获取dn失败","\(error!.localizedDescription)")
-// finished(nil)
-// }
-// }
-// static func getVersion(finished:@escaping ((_ version:String?)->Void)) {
-// JoyGemAIManager.shared().device.software { version in
-// finished(version)
-// } error: { error in
-// Logger.debug("\(error!.localizedDescription)");
-// finished(nil)
-// }
-// }
-//}
//
// Created by liangshi on 2025/12/29.
//
+//1、先暂停后停止,结束不了
+//2、暂停后,音频只有后半部分
import JoyGemAI
if recordView.isBusy {
return
}
- let v = LanguagePickerView(languages: CCAiLanguage.translate,isLeft: true,left: languageView.leftItem.language,right: languageView.rightItem.language)
+ let v = LanguagePickerView(languages: CCAiLanguage.all,isLeft: true,left: languageView.leftItem.language,right: languageView.rightItem.language)
v.selectedIndex = v.list.firstIndex(where: {$0.title == languageView.leftItem.language.title}) ?? 0
v.show()
v.didSelected = {[weak self] (index,value) in
if recordView.isBusy{
return
}
- let v = LanguagePickerView(languages: CCAiLanguage.translate,isLeft: false,left: languageView.leftItem.language,right: languageView.rightItem.language)
+ let v = LanguagePickerView(languages: CCAiLanguage.all,isLeft: false,left: languageView.leftItem.language,right: languageView.rightItem.language)
v.selectedIndex = v.list.firstIndex(where: {$0.title == languageView.rightItem.language.title}) ?? 0
v.show()
v.didSelected = {[weak self] (index,value) in
if recordBtn.isSelected || recordBtn.activeView.animating {
return
}
- let list = CCAiLanguage.translate.map{$0.title}
+ let list = CCAiLanguage.all.map{$0.title}
let v = CustomPicker(title: "请选择语言".l10n, list:list )
v.selectedIndex = list.firstIndex(where: {leftItem.language.title == $0})!
v.show()
v.didSelected = {[weak self] (index,value) in
guard let self = self else { return }
- leftItem.language = CCAiLanguage.translate.first(where: {$0.title == value})!
+ leftItem.language = CCAiLanguage.all.first(where: {$0.title == value})!
delegate?.fieldRecordBar(self, languageChange:leftItem.language)
}
return
if recordBtn.isSelected {
return
}
- let v = LanguagePickerView(languages: CCAiLanguage.translate,isLeft: true,left: leftItem.language,right: rightItem.language)
+ let v = LanguagePickerView(languages: CCAiLanguage.all,isLeft: true,left: leftItem.language,right: rightItem.language)
v.selectedIndex = v.list.firstIndex(where: {$0.title == leftItem.language.title}) ?? 0
v.show()
v.didSelected = {[weak self] (index,value) in
if recordBtn.isSelected {
return
}
- let v = LanguagePickerView(languages: CCAiLanguage.translate,isLeft: false,left: leftItem.language,right: rightItem.language)
+ let v = LanguagePickerView(languages: CCAiLanguage.all,isLeft: false,left: leftItem.language,right: rightItem.language)
v.selectedIndex = v.list.firstIndex(where: {$0.title == rightItem.language.title}) ?? 0
v.show()
v.didSelected = {[weak self] (index,value) in
class HistoryBottonView: BaseView {
let titleLabel = UILabel()
- var type = ModeEffectsType.fashion{
+ var type = ModeEffectsType.pop{
didSet{
titleLabel.text = type.title
}
}
extension RecordDetailVC:RecordDetailBarDelegate{
func recordDetailBarTranstlateAction(_ bar: RecordDetailBar) {
- var list = CCAiLanguage.translate.map{$0.title}
+ var list = CCAiLanguage.all.map{$0.title}
// list = list.filter { $0 != data!.from.title }
let v = CustomPicker(title: "请选择语言".l10n, list:list )
v.show()
v.didSelected = {[weak self] (index,value) in
guard let self = self else { return }
- data!.to = CCAiLanguage.translate.first(where: {$0.title == value})!
+ data!.to = CCAiLanguage.all.first(where: {$0.title == value})!
translateAction()
if !topBar.tranlateItem.isSelected {
topBar.tralateAction()
func translateAction(){
translateView.content = ""
- CCAiManager.translate(text: originView.content, from: data!.from.value, to: data!.to.value) {[weak self] result in
+ CCDevice.translate(text: originView.content, from: data!.from.value, to: data!.to.value) {[weak self] result in
guard let self = self else{return}
guard let (text, finish) = result else {return}
translateView.content += text
}
func summaryAction(){
summaryView.content = ""
- CCAiManager.summary(text: originView.content) {[weak self] result in
+ CCDevice.summary(text: originView.content) {[weak self] result in
guard let self = self else{return}
guard let (text, finish) = result else {return}
summaryView.content += text
let from = languageItem.leftLabel.language.value
let to = languageItem.rightLabel.language.value
- CCAiManager.translate(text:text, from: from, to: to) { [weak self] response in
+ CCDevice.translate(text:text, from: from, to: to) { [weak self] response in
guard let self = self else{return}
guard let (result, finish) = response else{return}
if !finish{
--- /dev/null
+//
+// Mode.swift
+// ShenYin
+//
+// Created by liangshi on 2025/12/30.
+//
+
+enum ModeEffectsType:Int{
+ case normal = 0
+ case pop = 1
+ case classic = 2
+ case jazz = 3
+ case rock = 4
+ case custom = 5
+
+ var title:String{
+ switch self {
+ case .normal:
+ return "正常".l10n
+ case .pop:
+ return "流行".l10n
+ case .classic:
+ return "经典".l10n
+ case .rock:
+ return "摇滚".l10n
+ case .jazz:
+ return "爵士".l10n
+ case .custom:
+ return "自定义".l10n
+ }
+ }
+ var img:String{
+ switch self {
+ case .normal:
+ return "mode_normal"
+ case .pop:
+ return "mode_fashion"
+ case .classic:
+ return "mode_classic"
+ case .rock:
+ return "mode_rock"
+ case .jazz:
+ return "mode_jazz"
+ case .custom:
+ return "mode_custom"
+ }
+ }
+
+
+ static var all:[ModeEffectsType]{
+ return [.normal,.pop,.classic,.rock,.jazz,.custom]
+ }
+}
+
+enum FindType:Int{
+ case left
+ case right
+ case all
+ case cancel
+}
let icon = UIImageView()
let titleLabel = UILabel()
let selectedIcon = UIImageView()
- var type = ModeEffectsType.fashion{
+ var type = ModeEffectsType.pop{
didSet{
titleLabel.text = type.title
icon.image = UIImage(named:type.img)
rightLabel.language = text1
}
@objc func leftAction(){
- let v = LanguagePickerView(languages: CCAiLanguage.translate,isLeft: true,left: leftLabel.language,right: rightLabel.language)
+ let v = LanguagePickerView(languages: CCAiLanguage.all,isLeft: true,left: leftLabel.language,right: rightLabel.language)
v.selectedIndex = v.list.firstIndex(where: {$0.title == leftLabel.language.title}) ?? 0
v.show()
v.didSelected = {[weak self] (index,value) in
}
}
@objc func rightAction(){
- let v = LanguagePickerView(languages: CCAiLanguage.translate,isLeft: false,left: leftLabel.language,right: rightLabel.language)
+ let v = LanguagePickerView(languages: CCAiLanguage.all,isLeft: false,left: leftLabel.language,right: rightLabel.language)
v.selectedIndex = v.list.firstIndex(where: {$0.title == rightLabel.language.title}) ?? 0
v.show()
v.didSelected = {[weak self] (index,value) in