Add samples for voices

This commit is contained in:
Jackson Harper 2022-11-07 18:43:59 +08:00
parent aad1a51da8
commit b47b1ca49a
3 changed files with 60 additions and 25 deletions

View file

@ -9,6 +9,8 @@
let language: VoiceLanguage
let showLanguageChanger: Bool
@State var playbackSample: String? = nil
init(forLanguage: VoiceLanguage, showLanguageChanger: Bool) {
self.language = forLanguage
self.showLanguageChanger = showLanguageChanger
@ -45,27 +47,7 @@
ForEach(language.categories, id: \.self) { category in
Section(category.rawValue) {
ForEach(audioController.voiceList?.filter { $0.category == category } ?? [], id: \.key.self) { voice in
HStack {
Button(action: {
audioController.setPreferredVoice(voice.key, forLanguage: language.key)
audioController.currentVoice = voice.key
}, label: {
HStack {
Text(voice.name)
Spacer()
if voice.selected {
if audioController.isPlaying, audioController.isLoading {
ProgressView()
} else {
Image(systemName: "checkmark")
}
}
}
.contentShape(Rectangle())
})
.buttonStyle(PlainButtonStyle())
}
voiceRow(for: voice)
}
}
}
@ -83,6 +65,39 @@
func voiceRow(for voice: VoiceItem) -> some View {
HStack {
Button(action: {
if audioController.isPlayingSample(voice: voice.key) {
playbackSample = nil
audioController.stopVoiceSample()
} else {
playbackSample = voice.key
audioController.playVoiceSample(voice: voice.key)
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { timer in
let playing = audioController.isPlayingSample(voice: voice.key)
if playing {
playbackSample = voice.key
} else if !playing {
// If the playback sample is something else, its taken ownership
// of the value so we just ignore it and shut down our timer.
if playbackSample == voice.key {
playbackSample = nil
}
timer.invalidate()
}
}
}
}, label: {
if playbackSample == voice.key {
Image(systemName: "stop.circle")
.font(.appTitleTwo)
.padding(.trailing, 16)
} else {
Image(systemName: "play.circle")
.font(.appTitleTwo)
.padding(.trailing, 16)
}
})
Button(action: {
audioController.setPreferredVoice(voice.key, forLanguage: language.key)
audioController.currentVoice = voice.key

View file

@ -246,6 +246,8 @@
var durations: [Double]?
var lastReadUpdate = 0.0
var samplePlayer: AVAudioPlayer?
public init(dataService: DataService) {
self.dataService = dataService
@ -631,9 +633,13 @@
public func playVoiceSample(voice: String) {
do {
if let url = Bundle.main.url(forResource: "tts-voice-sample-\(voice)", withExtension: "mp3") {
let player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)
player.play()
pause()
if let url = Bundle(url: UtilsPackage.bundleURL)?.url(forResource: voice, withExtension: "mp3") {
samplePlayer = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)
if !(samplePlayer?.play() ?? false) {
throw BasicError.message(messageText: "Unable to playback audio")
}
} else {
NSNotification.operationFailed(message: "Error playing voice sample.")
}
@ -643,6 +649,20 @@
}
}
public func isPlayingSample(voice: String) -> Bool {
if let samplePlayer = self.samplePlayer, let url = Bundle(url: UtilsPackage.bundleURL)?.url(forResource: voice, withExtension: "mp3") {
return samplePlayer.url == url && samplePlayer.isPlaying
}
return false
}
public func stopVoiceSample() {
if let samplePlayer = self.samplePlayer {
samplePlayer.stop()
self.samplePlayer = nil
}
}
private func updateDurations(oldPlayback: Double, newPlayback: Double) {
if let oldDurations = durations {
durations = oldDurations.map { $0 * oldPlayback / newPlayback }

View file

@ -87,7 +87,7 @@ public enum Voices {
]
public static let UltraPairs = [
VoicePair(firstKey: "Larry", secondKey: "susan", firstName: "Larry", secondName: "Susan", language: "en-US", category: .enUS),
VoicePair(firstKey: "Larry", secondKey: "Susan", firstName: "Larry", secondName: "Susan", language: "en-US", category: .enUS),
VoicePair(firstKey: "Jordan", secondKey: "William", firstName: "Jordan", secondName: "William", language: "en-US", category: .enUS),
VoicePair(firstKey: "Adrian", secondKey: "Anthony", firstName: "Adrian", secondName: "Anthony", language: "en-US", category: .enUS),