update
This commit is contained in:
@@ -7,75 +7,124 @@
|
||||
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
//import DDLogKit_Private
|
||||
|
||||
public let DDAS = DDAudioService.default
|
||||
|
||||
open class DDAudioService {
|
||||
public static let `default` = DDAudioService()
|
||||
private var items : [DDAudioServiceItem] = []
|
||||
|
||||
private var audioSoundID : SystemSoundID = 0
|
||||
private var vibrateSoundID : SystemSoundID = 0
|
||||
private var audioNumberOfLoops : Int = 0
|
||||
private var vibrateNumberOfLoops : Int = 0
|
||||
private var endSound : Bool = false
|
||||
private var endVibrate : Bool = false
|
||||
|
||||
public func playSoundWithVibrate(audioUrl:URL,numberOfLoops:Int = 1) {
|
||||
playVibrate(numberOfLoops: -1)
|
||||
playSound(audioUrl: audioUrl,numberOfLoops: numberOfLoops) {[weak self] in
|
||||
self?.stopSound()
|
||||
self?.stopVibrate()
|
||||
public func playSoundWithVibrate(audioUrl:URL,name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
||||
let item = DDAudioServiceItem(name: name)
|
||||
items.append(item)
|
||||
item.playSoundWithVibrate(audioUrl: audioUrl,numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
}
|
||||
|
||||
public func playSound(audioUrl:URL,name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
||||
let item = DDAudioServiceItem(name: name)
|
||||
items.append(item)
|
||||
item.playSound(audioUrl: audioUrl,numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
}
|
||||
|
||||
public func playVibrate(name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
||||
let item = DDAudioServiceItem(name: name)
|
||||
items.append(item)
|
||||
item.playVibrate(numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
}
|
||||
|
||||
public func stopSoundWithVibrate(name:String) {
|
||||
if items.contains(where: { item in
|
||||
item.name == name
|
||||
}) == true {
|
||||
if let index = items.firstIndex(where: { item in
|
||||
item.name == name
|
||||
}) {
|
||||
let item = items[index]
|
||||
item.stopSoundWithVibrate {[weak self] in
|
||||
self?.items.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func stopSoundWithVibrate() {
|
||||
stopSound()
|
||||
stopVibrate()
|
||||
public func stopSound(name:String) {
|
||||
if items.contains(where: { item in
|
||||
item.name == name
|
||||
}) == true {
|
||||
if let index = items.firstIndex(where: { item in
|
||||
item.name == name
|
||||
}) {
|
||||
let item = items[index]
|
||||
item.stopSound {[weak self] in
|
||||
self?.items.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func playSound(audioUrl:URL,numberOfLoops:Int = 1, endCompletionBlock: (() -> Void)? = nil) {
|
||||
self.audioNumberOfLoops = numberOfLoops
|
||||
public func stopVibrate(name:String) {
|
||||
if items.contains(where: { item in
|
||||
item.name == name
|
||||
}) == true {
|
||||
if let index = items.firstIndex(where: { item in
|
||||
item.name == name
|
||||
}) {
|
||||
let item = items[index]
|
||||
item.stopVibrate {[weak self] in
|
||||
self?.items.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class DDAudioServiceItem {
|
||||
fileprivate var name : String
|
||||
private var audioSoundID : SystemSoundID = 0
|
||||
private var vibrateSoundID : SystemSoundID = 0
|
||||
private var endSound : Bool = false
|
||||
private var endVibrate : Bool = false
|
||||
private var stopSoundCompletionHander : (() -> Void)?
|
||||
private var stopVibrateCompletionHander : (() -> Void)?
|
||||
|
||||
init(name:String) {
|
||||
self.name = name
|
||||
}
|
||||
|
||||
public func playSoundWithVibrate(audioUrl:URL,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0, eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
||||
playVibrate(numberOfLoops: -1)
|
||||
playSound(audioUrl: audioUrl,numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock) {[weak self] in
|
||||
self?.stopVibrate {
|
||||
if endCompletionBlock != nil {
|
||||
endCompletionBlock!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func stopSoundWithVibrate(completionHander:@escaping (() -> Void)) {
|
||||
stopSound {[weak self] in
|
||||
self?.stopVibrate {
|
||||
completionHander()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func playSound(audioUrl:URL,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
||||
|
||||
var audioSoundID:SystemSoundID = 0
|
||||
AudioServicesCreateSystemSoundID(audioUrl as CFURL, &audioSoundID)
|
||||
self.audioSoundID = audioSoundID
|
||||
DispatchQueue.global().async {[weak self] in
|
||||
self?.playSound(audioSoundID: audioSoundID,leftNumberOfLoops: numberOfLoops,endCompletionBlock: {
|
||||
if endCompletionBlock != nil {
|
||||
endCompletionBlock!()
|
||||
}
|
||||
})
|
||||
self?.playSound(audioSoundID: audioSoundID,leftNumberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
public func playVibrate(numberOfLoops:Int = 1, endCompletionBlock: (() -> Void)? = nil) {
|
||||
self.audioNumberOfLoops = numberOfLoops
|
||||
|
||||
var vibrateSoundID : SystemSoundID = 0
|
||||
vibrateSoundID = kSystemSoundID_Vibrate
|
||||
self.vibrateSoundID = vibrateSoundID
|
||||
DispatchQueue.global().async {[weak self] in
|
||||
self?.playVibrate(vibrateSoundID: vibrateSoundID, leftNumberOfLoops: numberOfLoops,endCompletionBlock: {
|
||||
if endCompletionBlock != nil {
|
||||
endCompletionBlock!()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func stopSound() {
|
||||
endSound = true
|
||||
AudioServicesDisposeSystemSoundID(audioSoundID)
|
||||
}
|
||||
|
||||
public func stopVibrate() {
|
||||
endVibrate = true
|
||||
AudioServicesDisposeSystemSoundID(vibrateSoundID)
|
||||
}
|
||||
|
||||
private func playSound(audioSoundID:SystemSoundID,leftNumberOfLoops:Int,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil, endCompletionBlock: (() -> Void)? = nil) {
|
||||
private func playSound(audioSoundID:SystemSoundID,leftNumberOfLoops:Int,timeInterval:TimeInterval,eachLoopCompletionBlock: (() -> Void)?, endCompletionBlock: (() -> Void)?) {
|
||||
var changeLeftNumberOfLoops = leftNumberOfLoops
|
||||
AudioServicesPlaySystemSoundWithCompletion(audioSoundID) {[weak self] in
|
||||
// 每次loop后回调
|
||||
if eachLoopCompletionBlock != nil {
|
||||
eachLoopCompletionBlock!()
|
||||
}
|
||||
@@ -83,22 +132,61 @@ open class DDAudioService {
|
||||
// 当前的剩余为0就结束
|
||||
changeLeftNumberOfLoops-=1
|
||||
if changeLeftNumberOfLoops == 0 || self?.endSound == true {
|
||||
self?.stopSound()
|
||||
if endCompletionBlock != nil {
|
||||
// 结束播放
|
||||
AudioServicesDisposeSystemSoundID(audioSoundID)
|
||||
// DDLog(message: "name = \(self?.name ?? "")的sound播放结束")
|
||||
|
||||
// 清除数据
|
||||
self?.audioSoundID = 0
|
||||
self?.endSound = false
|
||||
|
||||
// stop后回调
|
||||
if self?.stopSoundCompletionHander != nil {
|
||||
self?.stopSoundCompletionHander!()
|
||||
}else if endCompletionBlock != nil {
|
||||
// play所有loops后回调
|
||||
endCompletionBlock!()
|
||||
}
|
||||
print("sound播放结束")
|
||||
}else{
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + timeInterval, execute: {
|
||||
self?.playSound(audioSoundID: audioSoundID, leftNumberOfLoops: changeLeftNumberOfLoops,timeInterval: timeInterval)
|
||||
self?.playSound(audioSoundID: audioSoundID, leftNumberOfLoops: changeLeftNumberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func playVibrate(vibrateSoundID:SystemSoundID,leftNumberOfLoops:Int,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil, endCompletionBlock: (() -> Void)? = nil) {
|
||||
public func stopSound(completionHandler:@escaping (() -> Void)) {
|
||||
stopSoundCompletionHander = completionHandler
|
||||
|
||||
// 先尝试关闭
|
||||
let status = AudioServicesDisposeSystemSoundID(audioSoundID)
|
||||
// DDLog(message: "sound dispose status = \(status)")
|
||||
if status != 0 {
|
||||
// 假如没有关闭成功的话会来到结束
|
||||
endSound = true
|
||||
}else {
|
||||
audioSoundID = 0
|
||||
// DDLog(message: "name = \(name)的sound播放结束")
|
||||
completionHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func playVibrate(numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
||||
self.endVibrate = false
|
||||
|
||||
var vibrateSoundID : SystemSoundID = 0
|
||||
vibrateSoundID = kSystemSoundID_Vibrate
|
||||
self.vibrateSoundID = vibrateSoundID
|
||||
DispatchQueue.global().async {[weak self] in
|
||||
self?.playVibrate(vibrateSoundID: vibrateSoundID, leftNumberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
private func playVibrate(vibrateSoundID:SystemSoundID,leftNumberOfLoops:Int,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)?, endCompletionBlock: (() -> Void)?) {
|
||||
var changeLeftNumberOfLoops = leftNumberOfLoops
|
||||
AudioServicesPlayAlertSoundWithCompletion(vibrateSoundID) {[weak self] in
|
||||
// 每次loop后回调
|
||||
if eachLoopCompletionBlock != nil {
|
||||
eachLoopCompletionBlock!()
|
||||
}
|
||||
@@ -106,17 +194,43 @@ open class DDAudioService {
|
||||
// 当前的剩余为0就结束
|
||||
changeLeftNumberOfLoops-=1
|
||||
if changeLeftNumberOfLoops == 0 || self?.endVibrate == true {
|
||||
self?.stopVibrate()
|
||||
if endCompletionBlock != nil {
|
||||
// 结束
|
||||
AudioServicesDisposeSystemSoundID(vibrateSoundID)
|
||||
// DDLog(message: "name = \(self?.name ?? "")的vibrate播放结束")
|
||||
|
||||
// 清除数据
|
||||
self?.vibrateSoundID = 0
|
||||
self?.endVibrate = false
|
||||
|
||||
// stop后的回调
|
||||
if self?.stopVibrateCompletionHander != nil {
|
||||
self?.stopVibrateCompletionHander!()
|
||||
}else if endCompletionBlock != nil {
|
||||
// play完所有loops后回调
|
||||
endCompletionBlock!()
|
||||
}
|
||||
print("vibrate播放结束")
|
||||
}else{
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + timeInterval, execute: {
|
||||
self?.playVibrate(vibrateSoundID: vibrateSoundID, leftNumberOfLoops: changeLeftNumberOfLoops,timeInterval: timeInterval)
|
||||
self?.playVibrate(vibrateSoundID: vibrateSoundID, leftNumberOfLoops: changeLeftNumberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func stopVibrate(completionHandler:@escaping (() -> Void)) {
|
||||
stopVibrateCompletionHander = completionHandler
|
||||
|
||||
// 先尝试关闭
|
||||
let status = AudioServicesDisposeSystemSoundID(vibrateSoundID)
|
||||
// DDLog(message: "vibrate dispose status = \(status)")
|
||||
// if status != 0 {
|
||||
// // 假如没有关闭成功的话会来到结束
|
||||
endVibrate = true
|
||||
// }else{
|
||||
// vibrateSoundID = 0
|
||||
// DDLog(message: "name = \(name)的vibrate播放结束")
|
||||
// completionHandler()
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
93
Pods/DDAudioPlayerKit_Private/DDAudioPlayerKit_Private/Classes/DDSpeechSynthesizer.swift
generated
Normal file
93
Pods/DDAudioPlayerKit_Private/DDAudioPlayerKit_Private/Classes/DDSpeechSynthesizer.swift
generated
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// DDSpeechSynthesizer.swift
|
||||
// DDAudioPlayerKit_Private
|
||||
//
|
||||
// Created by 中道 on 2023/9/5.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
|
||||
public let DDSS = DDSpeechSynthesizer.default
|
||||
|
||||
open class DDSpeechSynthesizer {
|
||||
public static let `default` = DDSpeechSynthesizer()
|
||||
private var items : [DDSpeechSynthesizerItem] = []
|
||||
|
||||
public func play(text:String,name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil, endCompletionBlock: (() -> Void)? = nil) {
|
||||
let item = DDSpeechSynthesizerItem(name: name)
|
||||
items.append(item)
|
||||
item.play(text: text,numberOfLoops:numberOfLoops,timeInterval:timeInterval,eachLoopCompletionBlock:eachLoopCompletionBlock,endCompletionBlock:endCompletionBlock)
|
||||
}
|
||||
|
||||
public func stop(name:String) {
|
||||
if items.contains(where: { item in
|
||||
item.name == name
|
||||
}) == true {
|
||||
if let index = items.firstIndex(where: { item in
|
||||
item.name == name
|
||||
}) {
|
||||
let item = items[index]
|
||||
item.stop()
|
||||
items.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DDSpeechSynthesizerItem: NSObject, AVSpeechSynthesizerDelegate {
|
||||
private var synthesizer : AVSpeechSynthesizer?
|
||||
private var utterance : AVSpeechUtterance?
|
||||
public var name : String
|
||||
private var numberOfLoops : Int = 0
|
||||
private var timeInterval : TimeInterval = 0
|
||||
private var eachLoopCompletionBlock : (() -> Void)?
|
||||
private var endCompletionBlock : (() -> Void)?
|
||||
|
||||
init(name:String) {
|
||||
self.name = name
|
||||
}
|
||||
|
||||
func play(text:String,numberOfLoops:Int,timeInterval:TimeInterval,eachLoopCompletionBlock: (() -> Void)?, endCompletionBlock: (() -> Void)?) {
|
||||
self.numberOfLoops = numberOfLoops
|
||||
self.timeInterval = timeInterval
|
||||
self.eachLoopCompletionBlock = eachLoopCompletionBlock
|
||||
self.endCompletionBlock = endCompletionBlock
|
||||
|
||||
synthesizer = AVSpeechSynthesizer()
|
||||
synthesizer?.delegate = self
|
||||
utterance = AVSpeechUtterance(string: text)
|
||||
utterance?.voice = AVSpeechSynthesisVoice(language: "zh-Hans")
|
||||
utterance?.rate = AVSpeechUtteranceDefaultSpeechRate
|
||||
if let utterance {
|
||||
synthesizer?.speak(utterance)
|
||||
}
|
||||
}
|
||||
|
||||
public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
|
||||
if eachLoopCompletionBlock != nil {
|
||||
eachLoopCompletionBlock!()
|
||||
}
|
||||
|
||||
numberOfLoops-=1
|
||||
|
||||
if numberOfLoops == 0 {
|
||||
if endCompletionBlock != nil {
|
||||
endCompletionBlock!()
|
||||
}
|
||||
}else{
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + timeInterval, execute: {[weak self] in
|
||||
if let utterance = self?.utterance {
|
||||
self?.synthesizer?.speak(utterance)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func stop() {
|
||||
synthesizer?.stopSpeaking(at: .immediate)
|
||||
synthesizer?.delegate = nil
|
||||
synthesizer = nil
|
||||
utterance = nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user