Browse Source
refactor: completely purge custom wake-word engine and dylibs; rely exclusively on Siri and Push-to-Talk
main
refactor: completely purge custom wake-word engine and dylibs; rely exclusively on Siri and Push-to-Talk
main
16 changed files with 26 additions and 5501 deletions
-
BINFrameworks/libonnxruntime.dylib
-
BINFrameworks/libsherpa-onnx-c-api.dylib
-
4723include/SherpaOnnx/c-api.h
-
4include/SherpaOnnx/module.modulemap
-
48package.sh
-
BINresources/wakeword_models/decoder-epoch-12-avg-2-chunk-16-left-64.int8.onnx
-
BINresources/wakeword_models/encoder-epoch-12-avg-2-chunk-16-left-64.int8.onnx
-
BINresources/wakeword_models/joiner-epoch-12-avg-2-chunk-16-left-64.int8.onnx
-
7resources/wakeword_models/keywords.txt
-
500resources/wakeword_models/tokens.txt
-
40src/AppDelegate.swift
-
32src/AudioRecorder.swift
-
9src/SonioxSettings.swift
-
13src/StatusBarController.swift
-
10src/TextProcessor.swift
-
135src/WakeWordEngine.swift
4723
include/SherpaOnnx/c-api.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,4 +0,0 @@ |
|||
module SherpaOnnx { |
|||
header "c-api.h" |
|||
export * |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
▁JA R VI S |
|||
▁HE Y ▁JA R VI S |
|||
▁COMP U TER |
|||
▁HE Y ▁COMP U TER |
|||
▁A LE X A |
|||
▁G HO LA M |
|||
▁GO LA M |
|||
@ -1,500 +0,0 @@ |
|||
<blk> 0 |
|||
<sos/eos> 1 |
|||
<unk> 2 |
|||
S 3 |
|||
T 4 |
|||
▁THE 5 |
|||
▁A 6 |
|||
▁TO 7 |
|||
▁AND 8 |
|||
N 9 |
|||
E 10 |
|||
D 11 |
|||
ING 12 |
|||
' 13 |
|||
▁OF 14 |
|||
▁I 15 |
|||
▁IN 16 |
|||
Y 17 |
|||
ED 18 |
|||
M 19 |
|||
▁ 20 |
|||
▁THAT 21 |
|||
O 22 |
|||
C 23 |
|||
R 24 |
|||
A 25 |
|||
P 26 |
|||
▁YOU 27 |
|||
U 28 |
|||
RE 29 |
|||
▁IT 30 |
|||
▁S 31 |
|||
G 32 |
|||
L 33 |
|||
B 34 |
|||
▁IS 35 |
|||
I 36 |
|||
AL 37 |
|||
ER 38 |
|||
▁RE 39 |
|||
▁C 40 |
|||
▁WE 41 |
|||
▁SO 42 |
|||
▁BE 43 |
|||
OR 44 |
|||
AR 45 |
|||
IN 46 |
|||
▁FOR 47 |
|||
F 48 |
|||
▁HE 49 |
|||
LE 50 |
|||
LY 51 |
|||
▁E 52 |
|||
▁WAS 53 |
|||
K 54 |
|||
▁F 55 |
|||
W 56 |
|||
VE 57 |
|||
RI 58 |
|||
CH 59 |
|||
LL 60 |
|||
▁THIS 61 |
|||
▁T 62 |
|||
EN 63 |
|||
▁ON 64 |
|||
IT 65 |
|||
CE 66 |
|||
▁WITH 67 |
|||
▁B 68 |
|||
▁W 69 |
|||
▁ME 70 |
|||
▁DO 71 |
|||
▁DE 72 |
|||
▁HAVE 73 |
|||
▁BUT 74 |
|||
ENT 75 |
|||
▁P 76 |
|||
UR 77 |
|||
ON 78 |
|||
▁AS 79 |
|||
IC 80 |
|||
TER 81 |
|||
TE 82 |
|||
▁THEY 83 |
|||
ES 84 |
|||
RA 85 |
|||
▁NOT 86 |
|||
TH 87 |
|||
▁ARE 88 |
|||
RO 89 |
|||
IL 90 |
|||
ATION 91 |
|||
AN 92 |
|||
▁ST 93 |
|||
▁WHAT 94 |
|||
SE 95 |
|||
LI 96 |
|||
V 97 |
|||
▁CAN 98 |
|||
▁G 99 |
|||
▁OR 100 |
|||
▁ALL 101 |
|||
NE 102 |
|||
▁AT 103 |
|||
▁CON 104 |
|||
H 105 |
|||
▁LIKE 106 |
|||
▁MO 107 |
|||
▁HIS 108 |
|||
▁AN 109 |
|||
▁MA 110 |
|||
▁THERE 111 |
|||
▁SU 112 |
|||
▁MY 113 |
|||
NG 114 |
|||
- 115 |
|||
▁ABOUT 116 |
|||
▁SE 117 |
|||
LA 118 |
|||
▁ONE 119 |
|||
LO 120 |
|||
▁SHE 121 |
|||
CK 122 |
|||
▁HAD 123 |
|||
AD 124 |
|||
MENT 125 |
|||
VER 126 |
|||
▁CA 127 |
|||
IR 128 |
|||
▁IF 129 |
|||
▁NO 130 |
|||
EL 131 |
|||
▁O 132 |
|||
▁FROM 133 |
|||
▁PA 134 |
|||
▁YOUR 135 |
|||
▁KNOW 136 |
|||
RY 137 |
|||
ION 138 |
|||
UN 139 |
|||
▁JUST 140 |
|||
▁UP 141 |
|||
▁US 142 |
|||
▁WHO 143 |
|||
▁GO 144 |
|||
ME 145 |
|||
▁EX 146 |
|||
▁OUT 147 |
|||
ND 148 |
|||
CI 149 |
|||
▁PO 150 |
|||
▁HER 151 |
|||
▁FA 152 |
|||
▁PRO 153 |
|||
▁WHEN 154 |
|||
ATE 155 |
|||
AT 156 |
|||
▁BY 157 |
|||
PE 158 |
|||
AS 159 |
|||
▁LA 160 |
|||
GE 161 |
|||
▁CO 162 |
|||
▁PEOPLE 163 |
|||
▁K 164 |
|||
▁SOME 165 |
|||
IGHT 166 |
|||
▁THINK 167 |
|||
VI 168 |
|||
DE 169 |
|||
▁LE 170 |
|||
▁WERE 171 |
|||
▁LI 172 |
|||
OM 173 |
|||
▁WOULD 174 |
|||
▁SEE 175 |
|||
CO 176 |
|||
▁BO 177 |
|||
▁OUR 178 |
|||
▁HOW 179 |
|||
ET 180 |
|||
Z 181 |
|||
UL 182 |
|||
▁HO 183 |
|||
IG 184 |
|||
▁GET 185 |
|||
▁DON 186 |
|||
IS 187 |
|||
URE 188 |
|||
▁WHICH 189 |
|||
▁MI 190 |
|||
IES 191 |
|||
US 192 |
|||
X 193 |
|||
▁MORE 194 |
|||
▁NOW 195 |
|||
▁TIME 196 |
|||
▁UN 197 |
|||
▁FI 198 |
|||
TY 199 |
|||
▁WILL 200 |
|||
RU 201 |
|||
IVE 202 |
|||
▁THEIR 203 |
|||
▁SAY 204 |
|||
ITY 205 |
|||
▁HA 206 |
|||
LU 207 |
|||
▁RO 208 |
|||
HO 209 |
|||
OL 210 |
|||
IST 211 |
|||
AGE 212 |
|||
MA 213 |
|||
KE 214 |
|||
▁RA 215 |
|||
ID 216 |
|||
ERS 217 |
|||
▁LO 218 |
|||
▁SP 219 |
|||
▁DA 220 |
|||
▁SAID 221 |
|||
TION 222 |
|||
THER 223 |
|||
▁EN 224 |
|||
▁BECAUSE 225 |
|||
▁HAS 226 |
|||
EST 227 |
|||
TI 228 |
|||
ACT 229 |
|||
▁BA 230 |
|||
▁VERY 231 |
|||
▁THEM 232 |
|||
▁BEEN 233 |
|||
▁WA 234 |
|||
ABLE 235 |
|||
▁SA 236 |
|||
▁DID 237 |
|||
▁HIM 238 |
|||
▁DIS 239 |
|||
▁WANT 240 |
|||
▁OTHER 241 |
|||
IM 242 |
|||
▁PRE 243 |
|||
▁LOOK 244 |
|||
▁GOING 245 |
|||
▁VI 246 |
|||
▁WORK 247 |
|||
▁DR 248 |
|||
ENCE 249 |
|||
▁DI 250 |
|||
FF 251 |
|||
TA 252 |
|||
▁REALLY 253 |
|||
▁RIGHT 254 |
|||
MO 255 |
|||
ALLY 256 |
|||
▁INTO 257 |
|||
OW 258 |
|||
▁WAY 259 |
|||
▁FE 260 |
|||
▁COULD 261 |
|||
▁THEN 262 |
|||
TED 263 |
|||
▁HERE 264 |
|||
▁THESE 265 |
|||
▁OVER 266 |
|||
▁WELL 267 |
|||
▁NA 268 |
|||
▁ANY 269 |
|||
HE 270 |
|||
▁COMP 271 |
|||
▁COM 272 |
|||
▁TH 273 |
|||
▁EVEN 274 |
|||
▁TWO 275 |
|||
▁JO 276 |
|||
▁MAKE 277 |
|||
▁BACK 278 |
|||
▁WHERE 279 |
|||
SH 280 |
|||
▁QU 281 |
|||
MAN 282 |
|||
▁YEAR 283 |
|||
▁TRA 284 |
|||
▁CHA 285 |
|||
QU 286 |
|||
CA 287 |
|||
▁ALSO 288 |
|||
CTION 289 |
|||
ANCE 290 |
|||
UM 291 |
|||
PER 292 |
|||
DI 293 |
|||
▁HU 294 |
|||
▁MU 295 |
|||
FUL 296 |
|||
▁NEW 297 |
|||
ARD 298 |
|||
J 299 |
|||
ICAL 300 |
|||
ANT 301 |
|||
END 302 |
|||
▁MAR 303 |
|||
▁NE 304 |
|||
IF 305 |
|||
DER 306 |
|||
ONE 307 |
|||
▁THOSE 308 |
|||
PP 309 |
|||
▁MAN 310 |
|||
▁GOOD 311 |
|||
▁TAKE 312 |
|||
SIDE 313 |
|||
PO 314 |
|||
HA 315 |
|||
▁LITTLE 316 |
|||
▁APP 317 |
|||
▁BI 318 |
|||
UGH 319 |
|||
▁COME 320 |
|||
ISH 321 |
|||
TIC 322 |
|||
▁PER 323 |
|||
▁THINGS 324 |
|||
▁MUCH 325 |
|||
▁FIRST 326 |
|||
▁THAN 327 |
|||
IA 328 |
|||
▁AGAIN 329 |
|||
▁STA 330 |
|||
▁PART 331 |
|||
▁GA 332 |
|||
▁MEAN 333 |
|||
▁LET 334 |
|||
▁DOWN 335 |
|||
▁NEED 336 |
|||
▁GU 337 |
|||
LES 338 |
|||
▁RU 339 |
|||
ATED 340 |
|||
▁SHA 341 |
|||
VO 342 |
|||
▁TALK 343 |
|||
▁DAY 344 |
|||
▁CHI 345 |
|||
▁SOMETHING 346 |
|||
▁AFTER 347 |
|||
▁THOUGH 348 |
|||
▁CALL 349 |
|||
▁GRA 350 |
|||
▁EVERY 351 |
|||
▁KIND 352 |
|||
ROW 353 |
|||
AIN 354 |
|||
▁BU 355 |
|||
▁THROUGH 356 |
|||
▁SHOULD 357 |
|||
▁ONLY 358 |
|||
▁TA 359 |
|||
▁MIN 360 |
|||
▁GOT 361 |
|||
IAN 362 |
|||
▁GREAT 363 |
|||
▁RI 364 |
|||
▁DOES 365 |
|||
▁THING 366 |
|||
DAY 367 |
|||
OUS 368 |
|||
▁START 369 |
|||
▁MOST 370 |
|||
▁COL 371 |
|||
PH 372 |
|||
▁LOT 373 |
|||
IZE 374 |
|||
BER 375 |
|||
IOUS 376 |
|||
▁LIFE 377 |
|||
▁MANY 378 |
|||
▁FEEL 379 |
|||
ITION 380 |
|||
▁VA 381 |
|||
NESS 382 |
|||
▁BEFORE 383 |
|||
▁THREE 384 |
|||
▁WORLD 385 |
|||
▁GIVE 386 |
|||
▁WHY 387 |
|||
▁PI 388 |
|||
▁LONG 389 |
|||
PORT 390 |
|||
▁SHOW 391 |
|||
▁ACTUALLY 392 |
|||
▁NEVER 393 |
|||
IV 394 |
|||
FORM 395 |
|||
▁THANK 396 |
|||
▁HI 397 |
|||
▁PUT 398 |
|||
▁LOVE 399 |
|||
▁QUESTION 400 |
|||
▁HELP 401 |
|||
▁HAPPEN 402 |
|||
▁MR 403 |
|||
▁OWN 404 |
|||
WARD 405 |
|||
▁MADE 406 |
|||
▁HAND 407 |
|||
▁STATE 408 |
|||
IBLE 409 |
|||
▁TELL 410 |
|||
▁PH 411 |
|||
▁CAME 412 |
|||
▁TEA 413 |
|||
▁STILL 414 |
|||
▁DIFFERENT 415 |
|||
▁PLACE 416 |
|||
▁MIGHT 417 |
|||
▁FIND 418 |
|||
▁DU 419 |
|||
▁IMP 420 |
|||
▁OLD 421 |
|||
▁PERSON 422 |
|||
▁COUNT 423 |
|||
▁JA 424 |
|||
▁POINT 425 |
|||
▁HIGH 426 |
|||
SHIP 427 |
|||
▁LAST 428 |
|||
▁SAME 429 |
|||
▁FOUR 430 |
|||
▁AROUND 431 |
|||
▁OH 432 |
|||
▁CHANGE 433 |
|||
▁UNDER 434 |
|||
▁HOME 435 |
|||
▁ANOTHER 436 |
|||
▁FOUND 437 |
|||
ATIVE 438 |
|||
▁TURN 439 |
|||
▁YES 440 |
|||
LAND 441 |
|||
▁ALWAYS 442 |
|||
▁YEAH 443 |
|||
▁SCHOOL 444 |
|||
▁JE 445 |
|||
▁NEXT 446 |
|||
▁WORD 447 |
|||
▁JU 448 |
|||
LINE 449 |
|||
▁SIX 450 |
|||
▁LEARN 451 |
|||
▁BOOK 452 |
|||
▁PLAY 453 |
|||
▁AWAY 454 |
|||
▁HOUSE 455 |
|||
▁PLAN 456 |
|||
▁WHILE 457 |
|||
▁COMMUNI 458 |
|||
▁FRIEND 459 |
|||
▁AMERICA 460 |
|||
▁INTEREST 461 |
|||
▁KEEP 462 |
|||
▁BETTER 463 |
|||
▁IDEA 464 |
|||
▁HARD 465 |
|||
▁TWENTY 466 |
|||
▁THOUSAND 467 |
|||
▁HUNDRED 468 |
|||
▁WEEK 469 |
|||
▁NUMBER 470 |
|||
▁COURSE 471 |
|||
▁OKAY 472 |
|||
PRESS 473 |
|||
▁SYSTEM 474 |
|||
▁NINE 475 |
|||
▁UNDERSTAND 476 |
|||
▁WITHOUT 477 |
|||
▁BELIEVE 478 |
|||
▁POWER 479 |
|||
▁MAYBE 480 |
|||
▁BUILD 481 |
|||
▁MONEY 482 |
|||
▁BETWEEN 483 |
|||
▁GONNA 484 |
|||
▁IMPORTANT 485 |
|||
▁ANYTHING 486 |
|||
▁LEFT 487 |
|||
▁HAVING 488 |
|||
▁WHITE 489 |
|||
▁PROBLEM 490 |
|||
▁SECOND 491 |
|||
▁SPEAK 492 |
|||
▁TOGETHER 493 |
|||
▁BLACK 494 |
|||
▁PUBLIC 495 |
|||
▁HEALTH 496 |
|||
▁NOTHING 497 |
|||
▁EVERYTHING 498 |
|||
Q 499 |
|||
@ -1,135 +0,0 @@ |
|||
import Foundation |
|||
import SherpaOnnx |
|||
|
|||
public final class WakeWordEngine { |
|||
public static let shared = WakeWordEngine() |
|||
|
|||
private var spotter: OpaquePointer? |
|||
private var stream: OpaquePointer? |
|||
private let lock = NSLock() |
|||
private var isInitialized = false |
|||
|
|||
public var onWakeWordDetected: ((String) -> Void)? |
|||
|
|||
private init() { |
|||
initializeEngine() |
|||
} |
|||
|
|||
private func cStr(_ s: String) -> UnsafePointer<CChar> { |
|||
return UnsafePointer(strdup(s)!) |
|||
} |
|||
|
|||
public func initializeEngine() { |
|||
lock.lock() |
|||
defer { lock.unlock() } |
|||
|
|||
if isInitialized { return } |
|||
|
|||
let fileManager = FileManager.default |
|||
let bundleResourcePath = Bundle.main.resourcePath.map { $0 + "/wakeword_models" } ?? "" |
|||
let fallbackPath = "/Users/alialavi/.wakeword-models/sherpa-onnx-kws-zipformer-gigaspeech-3.3M-2024-01-01" |
|||
|
|||
let modelDir: String |
|||
if fileManager.fileExists(atPath: bundleResourcePath + "/tokens.txt") { |
|||
modelDir = bundleResourcePath |
|||
} else if fileManager.fileExists(atPath: fallbackPath + "/tokens.txt") { |
|||
modelDir = fallbackPath |
|||
} else { |
|||
print("WakeWordEngine: Model files not found.") |
|||
return |
|||
} |
|||
|
|||
let keywordsPath: String |
|||
let customKeywords = Bundle.main.resourcePath.map { $0 + "/wakeword_models/keywords.txt" } ?? "" |
|||
if fileManager.fileExists(atPath: customKeywords) { |
|||
keywordsPath = customKeywords |
|||
} else { |
|||
keywordsPath = modelDir + "/keywords.txt" |
|||
} |
|||
|
|||
var featConfig = SherpaOnnxFeatureConfig(sample_rate: 16000, feature_dim: 80) |
|||
var modelConfig = SherpaOnnxOnlineModelConfig() |
|||
modelConfig.tokens = cStr(modelDir + "/tokens.txt") |
|||
modelConfig.transducer.encoder = cStr(modelDir + "/encoder-epoch-12-avg-2-chunk-16-left-64.int8.onnx") |
|||
modelConfig.transducer.decoder = cStr(modelDir + "/decoder-epoch-12-avg-2-chunk-16-left-64.int8.onnx") |
|||
modelConfig.transducer.joiner = cStr(modelDir + "/joiner-epoch-12-avg-2-chunk-16-left-64.int8.onnx") |
|||
modelConfig.num_threads = 2 |
|||
modelConfig.provider = cStr("cpu") |
|||
|
|||
var config = SherpaOnnxKeywordSpotterConfig( |
|||
feat_config: featConfig, |
|||
model_config: modelConfig, |
|||
max_active_paths: 4, |
|||
num_trailing_blanks: 1, |
|||
keywords_score: 1.0, |
|||
keywords_threshold: 0.25, |
|||
keywords_file: cStr(keywordsPath), |
|||
keywords_buf: nil, |
|||
keywords_buf_size: 0 |
|||
) |
|||
|
|||
guard let spotter = SherpaOnnxCreateKeywordSpotter(&config) else { |
|||
print("WakeWordEngine: Failed to create SherpaOnnxKeywordSpotter") |
|||
return |
|||
} |
|||
guard let stream = SherpaOnnxCreateKeywordStream(spotter) else { |
|||
print("WakeWordEngine: Failed to create KeywordStream") |
|||
SherpaOnnxDestroyKeywordSpotter(spotter) |
|||
return |
|||
} |
|||
|
|||
self.spotter = spotter |
|||
self.stream = stream |
|||
self.isInitialized = true |
|||
print("WakeWordEngine: Initialized successfully with keywords at \(keywordsPath)") |
|||
} |
|||
|
|||
public func acceptAudioChunk(_ pcmData: Data) { |
|||
lock.lock() |
|||
defer { lock.unlock() } |
|||
|
|||
guard isInitialized, let spotter = self.spotter, let stream = self.stream else { return } |
|||
|
|||
let sampleCount = pcmData.count / 2 |
|||
guard sampleCount > 0 else { return } |
|||
|
|||
var floatSamples = [Float](repeating: 0, count: sampleCount) |
|||
pcmData.withUnsafeBytes { raw in |
|||
let ptr = raw.bindMemory(to: Int16.self) |
|||
for i in 0..<sampleCount { |
|||
floatSamples[i] = Float(ptr[i]) / 32768.0 |
|||
} |
|||
} |
|||
|
|||
floatSamples.withUnsafeBufferPointer { buf in |
|||
guard let ptr = buf.baseAddress else { return } |
|||
SherpaOnnxOnlineStreamAcceptWaveform(stream, 16000, ptr, Int32(sampleCount)) |
|||
} |
|||
|
|||
while SherpaOnnxIsKeywordStreamReady(spotter, stream) == 1 { |
|||
SherpaOnnxDecodeKeywordStream(spotter, stream) |
|||
if let resultPtr = SherpaOnnxGetKeywordResult(spotter, stream) { |
|||
let kw = String(cString: resultPtr.pointee.keyword).trimmingCharacters(in: .whitespacesAndNewlines) |
|||
if !kw.isEmpty { |
|||
print("WakeWordEngine: 🎯 WAKE WORD DETECTED: '\(kw)'!") |
|||
SherpaOnnxResetKeywordStream(spotter, stream) |
|||
SherpaOnnxDestroyKeywordResult(resultPtr) |
|||
|
|||
DispatchQueue.main.async { [weak self] in |
|||
self?.onWakeWordDetected?(kw) |
|||
} |
|||
break |
|||
} |
|||
SherpaOnnxDestroyKeywordResult(resultPtr) |
|||
} |
|||
} |
|||
} |
|||
|
|||
public func reset() { |
|||
lock.lock() |
|||
defer { lock.unlock() } |
|||
if let spotter = self.spotter, let stream = self.stream { |
|||
SherpaOnnxResetKeywordStream(spotter, stream) |
|||
} |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue