ContentView.swift
3.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//
// ContentView.swift
// SherpaOnnxTts
//
// Created by fangjun on 2023/11/23.
//
// Text-to-speech with Next-gen Kaldi on iOS without Internet connection
import SwiftUI
import AVFoundation
struct ContentView: View {
@State private var sid = "0"
@State private var speed = 1.0
@State private var text = ""
@State private var showAlert = false
@State var filename: URL = NSURL() as URL
@State var audioPlayer: AVAudioPlayer!
private var tts = createOfflineTts()
var body: some View {
VStack(alignment: .leading) {
HStack {
Spacer()
Text("Next-gen Kaldi: TTS").font(.title)
Spacer()
}
HStack{
Text("Speaker ID")
TextField("Please input a speaker ID", text: $sid).textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
}
HStack{
Text("Speed \(String(format: "%.1f", speed))")
.padding(.trailing)
Slider(value: $speed, in: 0.5...2.0, step: 0.1) {
Text("Speech speed")
}
}
Text("Please input your text below").padding([.trailing, .top, .bottom])
TextEditor(text: $text)
.font(.body)
.opacity(self.text.isEmpty ? 0.25 : 1)
.disableAutocorrection(true)
.border(Color.black)
Spacer()
HStack {
Spacer()
Button(action: {
let speakerId = Int(self.sid) ?? 0
let t = self.text.trimmingCharacters(in: .whitespacesAndNewlines)
if t.isEmpty {
self.showAlert = true
return
}
let audio = tts.generate(text: t, sid: speakerId, speed: Float(self.speed))
if self.filename.absoluteString.isEmpty {
let tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
self.filename = tempDirectoryURL.appendingPathComponent("test.wav")
}
let _ = audio.save(filename: filename.path)
self.audioPlayer = try! AVAudioPlayer(contentsOf: filename)
self.audioPlayer.play()
}) {
Text("Generate")
}.alert(isPresented: $showAlert) {
Alert(title: Text("Empty text"), message: Text("Please input your text before clicking the Generate button"))
}
Spacer()
Button (action: {
self.audioPlayer.play()
}) {
Text("Play")
}.disabled(filename.absoluteString.isEmpty)
Spacer()
}
Spacer()
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}