|
|
@ -16,6 +16,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
private var synthesizer: SPXSpeechSynthesizer? |
|
|
private var synthesizer: SPXSpeechSynthesizer? |
|
|
private var isInitialized = false |
|
|
private var isInitialized = false |
|
|
private var speaking = false |
|
|
private var speaking = false |
|
|
|
|
|
private var sessionid = "" //语音播报任务id |
|
|
|
|
|
|
|
|
// 当前配置 |
|
|
// 当前配置 |
|
|
private var currentVoice = DEFAULT_VOICE |
|
|
private var currentVoice = DEFAULT_VOICE |
|
|
@ -109,10 +110,14 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public func startspeak(sessionid sessionid: String)-> Bool { |
|
|
|
|
|
self.sessionid = sessionid |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
/** |
|
|
/** |
|
|
* 单次合成并播放 |
|
|
* 单次合成并播放 |
|
|
*/ |
|
|
*/ |
|
|
public func speakOnce(_ text: String) -> Bool { |
|
|
public func speakOnce(sessionid sessionid: String,_ text: String) -> Bool { |
|
|
if !isInitialized { |
|
|
if !isInitialized { |
|
|
os_log("语音合成未初始化", log: log, type: .error) |
|
|
os_log("语音合成未初始化", log: log, type: .error) |
|
|
notifyEvent(eventType: .error, params: [ |
|
|
notifyEvent(eventType: .error, params: [ |
|
|
@ -122,6 +127,10 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (self.sessionid != sessionid){ |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 清理文本 |
|
|
// 清理文本 |
|
|
let cleanedText = cleanTextForTTS(text) |
|
|
let cleanedText = cleanTextForTTS(text) |
|
|
if cleanedText.isEmpty { |
|
|
if cleanedText.isEmpty { |
|
|
@ -130,7 +139,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
|
|
|
|
|
|
// 异步处理 |
|
|
// 异步处理 |
|
|
enqueueSynthesisTask { |
|
|
enqueueSynthesisTask { |
|
|
self.performSynthesis(text: cleanedText) |
|
|
self.performSynthesis(sessionid: sessionid, text: cleanedText) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true |
|
|
return true |
|
|
@ -139,7 +148,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
/** |
|
|
/** |
|
|
* 流式合成文本 |
|
|
* 流式合成文本 |
|
|
*/ |
|
|
*/ |
|
|
public func speakStream(_ text: String) -> Bool { |
|
|
public func speakStream(sessionid sessionid: String,_ text: String) -> Bool { |
|
|
if !isInitialized { |
|
|
if !isInitialized { |
|
|
notifyEvent(eventType: .error, params: [ |
|
|
notifyEvent(eventType: .error, params: [ |
|
|
"errorCode": "NOT_INITIALIZED", |
|
|
"errorCode": "NOT_INITIALIZED", |
|
|
@ -147,6 +156,10 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
]) |
|
|
]) |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
if (self.sessionid != sessionid){ |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
self.sessionid = sessionid |
|
|
|
|
|
|
|
|
if text.isEmpty { |
|
|
if text.isEmpty { |
|
|
return true |
|
|
return true |
|
|
@ -184,7 +197,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
streamBuffer = String(currentText[startIndex...]) |
|
|
streamBuffer = String(currentText[startIndex...]) |
|
|
|
|
|
|
|
|
if !textToSpeak.isEmpty { |
|
|
if !textToSpeak.isEmpty { |
|
|
return speakOnce(textToSpeak) |
|
|
return speakOnce(sessionid: sessionid, textToSpeak) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -194,7 +207,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
/** |
|
|
/** |
|
|
* 刷新并播放流式文本 |
|
|
* 刷新并播放流式文本 |
|
|
*/ |
|
|
*/ |
|
|
public func flushStream() -> Bool { |
|
|
public func flushStream(sessionid sessionid: String) -> Bool { |
|
|
if !isInitialized { |
|
|
if !isInitialized { |
|
|
notifyEvent(eventType: .error, params: [ |
|
|
notifyEvent(eventType: .error, params: [ |
|
|
"errorCode": "NOT_INITIALIZED", |
|
|
"errorCode": "NOT_INITIALIZED", |
|
|
@ -210,7 +223,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
return true |
|
|
return true |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return speakOnce(remainingText) |
|
|
return speakOnce(sessionid:sessionid,remainingText) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
@ -218,14 +231,15 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
*/ |
|
|
*/ |
|
|
public func stop() -> Bool { |
|
|
public func stop() -> Bool { |
|
|
speaking = false |
|
|
speaking = false |
|
|
|
|
|
sessionid = "" |
|
|
streamBuffer = "" |
|
|
streamBuffer = "" |
|
|
|
|
|
lastSpokenText = "" |
|
|
taskLock.lock() |
|
|
taskLock.lock() |
|
|
pendingTasks.removeAll() |
|
|
pendingTasks.removeAll() |
|
|
taskLock.unlock() |
|
|
taskLock.unlock() |
|
|
|
|
|
|
|
|
synthesisQueue.async { |
|
|
|
|
|
do { |
|
|
do { |
|
|
|
|
|
print("liwei-------------停止语音合成播放") |
|
|
try self.synthesizer?.stopSpeaking() |
|
|
try self.synthesizer?.stopSpeaking() |
|
|
self.notifyEvent(eventType: .synthesisCanceled) |
|
|
self.notifyEvent(eventType: .synthesisCanceled) |
|
|
} catch { |
|
|
} catch { |
|
|
@ -235,6 +249,14 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
"errorMessage": error.localizedDescription |
|
|
"errorMessage": error.localizedDescription |
|
|
]) |
|
|
]) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
synthesisQueue.async { |
|
|
|
|
|
do { |
|
|
|
|
|
self.synthesizer = nil |
|
|
|
|
|
try self.recreateSynthesizer() |
|
|
|
|
|
}catch { |
|
|
|
|
|
os_log("重置语音合成失败: %{public}@", log: self.log, type: .error, error.localizedDescription) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true |
|
|
return true |
|
|
@ -314,7 +336,7 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
|
|
|
|
|
|
// 如果之前正在播放,恢复播放 |
|
|
// 如果之前正在播放,恢复播放 |
|
|
if wasSpeaking, let lastText = lastSpokenText { |
|
|
if wasSpeaking, let lastText = lastSpokenText { |
|
|
speakOnce(lastText) |
|
|
speakOnce(sessionid: "",lastText) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true |
|
|
return true |
|
|
@ -386,13 +408,19 @@ public class AzureTtsHelper: NSObject, ITtsService { |
|
|
/** |
|
|
/** |
|
|
* 执行语音合成 |
|
|
* 执行语音合成 |
|
|
*/ |
|
|
*/ |
|
|
private func performSynthesis(text: String) { |
|
|
private func performSynthesis(sessionid:String,text: String) { |
|
|
|
|
|
if (self.sessionid != sessionid) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
speaking = true |
|
|
speaking = true |
|
|
lastSpokenText = text |
|
|
// lastSpokenText = text |
|
|
// 生成SSML |
|
|
// 生成SSML |
|
|
let ssml = generateOptimizedSsml(text) |
|
|
let ssml = generateOptimizedSsml(text) |
|
|
|
|
|
|
|
|
do { |
|
|
do { |
|
|
|
|
|
if (self.sessionid != sessionid) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
os_log("开始合成: %{public}@", log: log, type: .debug, ssml) |
|
|
os_log("开始合成: %{public}@", log: log, type: .debug, ssml) |
|
|
let result = try synthesizer?.startSpeakingSsml(ssml) |
|
|
let result = try synthesizer?.startSpeakingSsml(ssml) |
|
|
|
|
|
|
|
|
|