func send(_ sender:BleSender){
if let connectPeripheral = connectPeripheral, let writeCha = writeCha {
DCLogger.debug("发",writeCha.uuid.uuidString,sender.data.joined())
- connectPeripheral.writeValue(sender.data, for: writeCha, type:.withoutResponse)
+
+
+// if sender.data[1] == 0x10,sender.data[2] == 0x01 {
+// let text1 = "ba100101025b7b226964223a302c226e616d65223a22e69da8e5ae97e7baac2de4b880e6aca1e5b0b1e5a5bd20284c697665292e6d7033222c2273697a65223a343233323632342c22647572223a307d2c7b226964223a312c226e616d65223a22e5bca0e7b4abe8b1aa2de58fafe4b88de58fafe4bba52e6d7033222c2273697a65223a393635383835322c22647572223a307d2c7b226964223a322c226e616d65223a224245594f4e442de79c9fe79a84e788b1e4bda02e6d7033222c2273697a65223a31313031363533372c22647572223a307d2c7b226964223a332c226e616d65223a22472e452e4d2e20e98293e7b4abe6a38b2de69c89e5bf83e4baba2e6d7033222c2273697a65223a393630333832392c22647572223a307d2c7b226964223a342c226e616d65223a2248414e41e88f8ae6a293e4b9942de68891e4b88de698afe5a5b92e6d7033222c2273697a65223a373932343138312c22647572223a307d2c7b226964223a352c226e616d65223a2248414e412de5bf98e8aeb0e68891e887aae5b7b12e6d7033222c2273697a65223a393330343938342c22647572223a307d5da701d9"
+// sender.completion?(.response.code(.success).value(Data.dataWithHexString(text1)))
+// let text2 = "ba100102025b7b226964223a362c226e616d65223a224d722e3136e7bd97e99abde6b0b82de5a484e5a484e590bb2e6d7033222c2273697a65223a383533333836302c22647572223a307d2c7b226964223a372c226e616d65223a22536f6c65722de9a2a8e79a84e5ada3e7af802e6d7033222c2273697a65223a31303031333432352c22647572223a307d2c7b226964223a382c226e616d65223a225477696e732de6818be788b1e5a4a7e8bf87e5a4a92e6d7033222c2273697a65223a393039383039362c22647572223a307d2c7b226964223a392c226e616d65223a225477696e732de6a3aee5b7b4e79a87e5908e2e6d7033222c2273697a65223a373436323832322c22647572223a307d5d0e012c"
+// sender.completion?(.response.code(.success).value(Data.dataWithHexString(text2)))
+// }
+// else{
+ connectPeripheral.writeValue(sender.data, for: writeCha, type:.withoutResponse)
+// }
}
}
func sendToStarburst(_ data:Data){
full.append(data)
full.addCrc()
if let connectPeripheral = connectPeripheral, let writeCha = writeCha {
- DCLogger.debug("发",writeCha.uuid.uuidString,full.joined())
+// DCLogger.debug("发",writeCha.uuid.uuidString,full.joined())
connectPeripheral.writeValue(full, for: writeCha, type:.withoutResponse)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
- DCLogger.debug("收 ",characteristic.uuid,characteristic.value?.joined() ?? "")
+// DCLogger.debug("收 ",characteristic.uuid,characteristic.value?.joined() ?? "")
guard let data = characteristic.value else { return }
if data.count > 4 && data[0] == 0xBA {
if let sender = BleSender.answer(data) {
/// 回复回调
public var responseCallback:((String,Int)->Void)?
/// 对话语音回调
- public var dataCallback:((Int,Data?,Bool)->Void)?
+ public var dataCallback:((Int,Data?,Bool,Int)->Void)?
/// 状态码回调
public var codeCallback:((Int)->Void)?
/// 结束对话回调
/// 是否进⾏Tts,默认false
public var tts:Bool = true
/// 默认pcm。⽀持pcm / ogg_opus / mp3
- public var ttsAudioFormat:String = "mp3"
+ public var ttsAudioFormat:String = "pcm"
/// 语⾔编码,默认为普通话(zh-CN)
public var language:String = "zh-CN"
} responseVoice: { [weak self] (dialogId,data, finish,sampleRate) in
guard let self = self else { return }
self.dialogId = dialogId
- dataCallback?(dialogId,data,finish)
+ dataCallback?(dialogId,data,finish,sampleRate)
} stateChange: {[weak self] code in
DCLogger.debug("状态改变 \(code)")
self?.codeCallback?(code.rawValue)
public class DCDevice{
public static let shared = DCDevice()
+
/// ai事件回调
/// 0x01(打开AI对话)
// 0x02(关闭AI对话)
// 0x03(打开耳机录音)
// 0x04(关闭耳机录音)
public var eventCallback:((UInt8)->Void)?
+
+ public var muiscPlayCallback:((UInt16,UInt16,UInt16)->Void)?
+ ///
func receiveNotice(_ data:Data){
if data[1] == 0x10,data[2] == 0x06{
let index = UInt16(data[3...4].int)
let pro = UInt16(data[5...6].int)
let total = UInt16(data[7...8].int)
DCLogger.debug("播放进度index = \(index),total = \(total),pro = \(pro)")
+ muiscPlayCallback?(index,total,pro)
}
}
}
extension DCDevice{
+ ///
+ ///
public func getBatery(finished:@escaping ((Int,Int)?)->Void){
var head: UInt8 = 0xBA
var cmd: UInt8 = 0x09
public class DCMusic:Codable{
/// id
- public var id = ""
+ public var id:UInt16 = 0
/// 名字
- public var name = ""
+ public var name:String = ""
/// 大小
- public var size = ""
+ public var size:Int = 0
/// 时长
- public var dur = 0
+ public var dur:Int = 0
}
extension DCDevice{
return
}
- let index = result.data[4].int
- let total = result.data[5].int
+ let index = result.data[3].int
+ let total = result.data[4].int
DCLogger.debug(total,index)
- let data = result.data.subdata(in: 6..<result.data.count - 3)
+ let data = result.data.subdata(in: 5..<result.data.count - 3)
let str = String(data: data, encoding: .utf8)
DCLogger.debug(str ?? "")
guard let list = JSON.decode([DCMusic].self, from: data) else {
DCBleManager.shared.send(sender)
}
}
- public func musicPause(finished:@escaping (UInt16?,Bool)->Void){
+ public func musicPause(finished:@escaping (Bool)->Void){
var head: UInt8 = 0xBA
var cmd: UInt8 = 0x10
var data:UInt8 = 0x04
sender.completion = { result in
DCLogger.debug("\(result.description)")
if result.isSuccess{
- let value = UInt16(result.data[3...4].int)
- DCLogger.debug(value)
- finished(value,true)
+ finished(true)
}
else{
- finished(nil,false)
+ finished(false)
}
}
DCBleManager.shared.send(sender)
deinit {
print("\(Self.self) 销毁")
}
+ public init() {
+ super.init(nibName: nil, bundle: nil)
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
("现场录音","recordAction"),
("耳机录音","bleAsrAction"),
("对话","chatAction"),
+ ("tts","ttsAction"),
]
override func viewDidLoad() {
@objc func chatAction(){
navigationController?.pushViewController(ChatVC(), animated: true)
}
+ @objc func ttsAction(){
+ navigationController?.pushViewController(TtsVC(), animated: true)
+ }
+
}
extension HomeVC{
import DeepChordsSdk
import Toast_Swift
class MusicVC: BaseVC{
- let list = [DCMusic]()
+ var dataList = [DCMusic]()
+ let tableView = UITableView(frame: .zero, style: .plain)
override func viewDidLoad() {
super.viewDidLoad()
func setupViews(){
self.title = "音乐"
- let tableView = UITableView(frame: CGRectMake(0, 80, self.view.bounds.size.width, self.view.bounds.size.height), style: .plain)
+
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
view.addSubview(tableView)
+ tableView.snp.makeConstraints { make in
+ make.edges.equalToSuperview()
+ }
}
}
return 60
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return list.count
+ return dataList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
- cell.textLabel?.text = list[indexPath.row].name
+ cell.textLabel?.text = dataList[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- let data = list[indexPath.row]
+ let data = dataList[indexPath.row]
navigationController?.pushViewController(PlayerVC(music: data), animated: true)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
- guard let id = UInt16(list[indexPath.row].id) else {return}
+ let id = dataList[indexPath.row].id
DCDevice.shared.musicDelete(list: [id]) { result in
}
extension MusicVC {
func loadData(){
- DCDevice.shared.getTotalMusic { num in
- if let num = num,num > 0{
+// DCDevice.shared.getTotalMusic { num in
+// if let num = num,num > 0{
DCDevice.shared.getMusicList(size: 10, index: 0) {[weak self] (list, result) in
guard let self = self else{return}
guard let list = list else{return}
+ self.dataList = list
+ self.tableView.reloadData()
}
- }
- }
+// }
+// }
}
}
import DeepChordsSdk
import Toast_Swift
class PlayerVC: BaseVC{
- let playBtn = UIButton(type: .custom)
+ let list = ["顺序循环","随机","单曲"]
+ let label = UILabel()
let modeBtn = UIButton(type: .custom)
+ let playBtn = UIButton(type: .custom)
let music:DCMusic
init(music:DCMusic) {
self.music = music
super.init()
}
+
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
// Do any additional setup after loading the view.
setupViews()
+ loadMode()
+ setupSDK()
+ }
+ func setupSDK(){
+ DCDevice.shared.muiscPlayCallback = { [weak self] (index,total,pro) in
+ guard let self = self else{return}
+ label.text = "歌曲名称:\(music.name)\n" + "id:\(music.id)\n" + "大小:\(music.size)\n" + "时长:\(music.dur)\n" + "进度:\(total) \(pro)"
+ }
}
-
func setupViews(){
- self.title = "eq"
+ self.title = music.name
+
+ self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: modeBtn)
+ modeBtn.do { v in
+ v.addTarget(self, action: #selector(modeAction), for: .touchUpInside)
+ v.setTitleColor(.blue, for: .normal)
+ }
+ modeBtn.frame = CGRect(x: 0, y: 0, width: 80, height: 44)
+ label.do { v in
+ v.text = "歌曲名称:\(music.name)\n" + "id:\(music.id)\n" + "大小:\(music.size)\n" + "时长:\(music.dur)\n"
+ v.numberOfLines = 0
+ }
+
playBtn.do { v in
v.setTitle("播放", for: .normal)
v.setTitle("暂停", for: .selected)
v.addTarget(self, action: #selector(playBtnAction), for: .touchUpInside)
+ v.backgroundColor = .blue
}
- playBtn.frame = CGRect(x: 0, y: 0, width: 50, height: 44)
- self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: playBtn)
- modeBtn.do { v in
- v.setTitle("播放", for: .normal)
- v.setTitle("暂停", for: .selected)
- v.addTarget(self, action: #selector(playBtnAction), for: .touchUpInside)
+ view.addSubview(label)
+ view.addSubview(playBtn)
+
+ label.snp.makeConstraints { make in
+ make.size.equalTo(300)
+ make.center.equalToSuperview()
+ }
+
+ playBtn.snp.makeConstraints { make in
+ make.width.centerX.bottom.equalToSuperview()
+ make.height.equalTo(80)
}
}
@objc func playBtnAction(){
- guard let id = UInt16(music.id) else {return}
+ let id = music.id
playBtn.isSelected = !playBtn.isSelected
if playBtn.isSelected {
- DCDevice.shared.musicPlay(index: id) { index, result in
-
+ DCDevice.shared.musicPlay(index: id) {[weak self] index, result in
+ guard let self = self else {return}
+
}
}
else{
- DCDevice.shared.musicPause { index, result in
+ DCDevice.shared.musicPause { result in
+
+ }
+ }
+ }
+ func loadMode(){
+ DCDevice.shared.getMusicPlayMode { [weak self] mode, success in
+ guard let self = self else {return}
+ if let mode = mode{
+ modeBtn.setTitle(list[Int(mode)], for: .normal)
}
}
}
+ @objc func modeAction(){
+ let vc = UIAlertController(title: nil, message: "请选择", preferredStyle: .actionSheet)
+ let action0 = UIAlertAction(title: "顺序循环", style: .default) { action in
+ self.setMuiscPlayMode(0x00)
+ }
+ let action1 = UIAlertAction(title: "随机", style: .default) { action in
+ self.setMuiscPlayMode(0x01)
+ }
+ let action2 = UIAlertAction(title: "单曲", style: .default) { action in
+ self.setMuiscPlayMode(0x02)
+ }
+ let action3 = UIAlertAction(title: "取消", style: .cancel) { action in
+
+ }
+ vc.addAction(action0)
+ vc.addAction(action1)
+ vc.addAction(action2)
+ vc.addAction(action3)
+ self.present(vc, animated: true)
+ }
+ func setMuiscPlayMode(_ mode:UInt8){
+ modeBtn.setTitle(list[Int(mode)], for: .normal)
+ DCDevice.shared.setMusicPlayMode(mode: mode) { result in
+
+ }
+ }
}
import StarburstSdk
import AVFoundation
-class TttsVC: UIViewController {
+class TtsVC: BaseVC {
private let textField = UITextField()
private let speedSlider = UISlider()
private let speedLabel = UILabel()
speedLabel.text = "语速:\(String(format: "%.1f", ttsSpeed))x"
synthButton.setTitle("合成并播放", for: .normal)
- synthButton.addTarget(self, action: #selector(startTTS), for: .touchUpInside)
+ synthButton.addTarget(self, action: #selector(starTts), for: .touchUpInside)
logView.isEditable = false
logView.font = UIFont.systemFont(ofSize: 14)
speedLabel.text = "语速:\(String(format: "%.1f", ttsSpeed))x"
}
- @objc func startTTS() {
+ @objc func starTts() {
guard let text = textField.text, !text.isEmpty else {
appendLog("请输入文本")
return
}
}
-extension TttsVC: TextToSpeechCallback {
+extension TtsVC: TextToSpeechCallback {
func onResult(_ response: String) {
appendLog("合成完成,开始播放...\n")
guard let jsonObj = try? JSONSerialization.jsonObject(with: response.data(using: .utf8)!, options: []) as? [String:Any],
}
chatNeedReloadData?()
}
- DCChat.shared.dataCallback = {[weak self] dialogId, data, finish in
- // PcmSound.sharedInstance().delegate = self
+ DCChat.shared.dataCallback = {[weak self] (dialogId, data, finish,sampleRate) in
+ PcmSound.sharedInstance().delegate = self
guard let self = self else { return }
- // if (!isTtsPlaying) {
- // isTtsPlaying = true
- // DCLogger.debug("开始播放")
- // DCChat.shared.startPlayTtsAudio()
- // }
- // DCLogger.debug("收到音频数据", data?.count ?? 0)
- // PcmSound.sharedInstance().feed(data)
+ if (!isTtsPlaying) {
+ isTtsPlaying = true
+ DCLogger.debug("开始播放")
+ DCChat.shared.startPlayTtsAudio()
+ }
+ DCLogger.debug("收到音频数据", data?.count ?? 0,sampleRate)
+ PcmSound.sharedInstance().feed(data)
- if finish {
- self.saveToFile(data: self.audioData!)
- self.audioData = nil
- } else {
- if self.audioData == nil {
- self.audioData = Data()
- }
- self.audioData?.append(data!)
- }
+// if finish {
+// self.saveToFile(data: self.audioData!)
+// self.audioData = nil
+// } else {
+// if self.audioData == nil {
+// self.audioData = Data()
+// }
+// self.audioData?.append(data!)
+// }
}
DCChat.shared.codeCallback = {[weak self] code in
- self?.codeCallback?(code)
+ guard let self = self else { return }
+ self.codeCallback?(code)
- // if code == 20001 {
- // if (self.isTtsPlaying) {
- // self.isTtsPlaying = false
- // PcmSound.sharedInstance().cleanup()
- // PcmSound.sharedInstance().setup(16000, withchannels: 1)
- //
- //// var options: AVAudioSession.CategoryOptions = [.allowBluetooth]
- //// do {
- //// try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
- //// try AVAudioSession.sharedInstance().setActive(true)
- //// } catch {
- //// DCLogger.debug(error)
- //// }
- // }
- // }
+ if code == 20001 {
+ if (self.isTtsPlaying) {
+ self.isTtsPlaying = false
+ PcmSound.sharedInstance().cleanup()
+ PcmSound.sharedInstance().setup(16000, withchannels: 1)
+
+ var options: AVAudioSession.CategoryOptions = [.allowBluetooth]
+ do {
+ try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
+ try AVAudioSession.sharedInstance().setActive(true)
+ } catch {
+ DCLogger.debug(error)
+ }
+ }
+ }
}
DCChat.shared.finishCallback = {[weak self] path in
self?.finishCallback?(path)
/// 日记管理
class Logger {
- static var isDebug: Bool = false
+ static var isDebug: Bool = true
fileprivate static let shared = Logger()
private var fileHandle:FileHandle?
func getList() -> [RecordDetailModel] {
if let data = userDefaults.data(forKey: deviceListKey),
let deviceList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [RecordDetailModel] {
+// let path = NSHomeDirectory() + "/Documents/"
+
+ for item in deviceList {
+ if let last = item.path.components(separatedBy: "Documents").last{
+ item.path = NSHomeDirectory() + "/Documents/\(last)"
+ }
+ }
+
return deviceList
}
return []
var currentProgress: Float = 0
var duration: Float = 0
+ var isReady = false
typealias ProgressCallback = (_ current: Float, _ duration: Float) -> Void
var progressCallback: ProgressCallback?
setupNowPlayingInfoCenter(url)
setupRemoteControl()
startProgressMonitoring()
+ isReady = true
} catch let error {
print("Error playing music: \(error.localizedDescription)")
+ isReady = false
}
}
func start() {
+ if isReady == false {
+ return
+ }
audioPlayer?.play()
startProgressMonitoring()
}
v.addTarget(self, action: #selector(closeAction), for: .touchUpInside)
}
+ AudioPlayView.shared.hiden()
AudioPlayerManager.shared.musicModel = nil
AudioPlayerManager.shared.progressCallback = {[weak self] current,duration in
guard let self = self else {return}