From 2d1d4ad406228ef62ab078724cb7d1556e003d01 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 13 Jul 2026 16:03:19 +0800
Subject: [PATCH] chore: point independent project metadata to unified root
---
C1.source/privatevoice.src/internal/engine/engine_windows.go | 88 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/C1.source/privatevoice.src/internal/engine/engine_windows.go b/C1.source/privatevoice.src/internal/engine/engine_windows.go
index 8ace9c7..6dd2ea2 100755
--- a/C1.source/privatevoice.src/internal/engine/engine_windows.go
+++ b/C1.source/privatevoice.src/internal/engine/engine_windows.go
@@ -4,7 +4,10 @@
import (
"fmt"
+ "syscall"
"time"
+ "unsafe"
+
"voicesnap/internal/logger"
"voicesnap/internal/model"
@@ -14,10 +17,22 @@
type sherpaEngine struct {
recognizer *sherpa.OfflineRecognizer
+ provider string
hwInfo string
}
+var (
+ kernel32 = syscall.NewLazyDLL("kernel32.dll")
+ procGetShortPathNameW = kernel32.NewProc("GetShortPathNameW")
+)
+
func newPlatformEngine(resolved model.ResolvedModel) (Engine, error) {
+ modelPath := windowsRuntimePath(resolved.Files["model"])
+ tokensPath := windowsRuntimePath(resolved.Files["tokens"])
+ if modelPath != resolved.Files["model"] || tokensPath != resolved.Files["tokens"] {
+ logger.Info("Using Windows short paths for sherpa runtime model files")
+ }
+
// Try DirectML first, then CPU fallback
providers := []struct {
name string
@@ -31,10 +46,10 @@
config := sherpa.OfflineRecognizerConfig{}
config.FeatConfig.SampleRate = 16000
config.FeatConfig.FeatureDim = 80
- config.ModelConfig.SenseVoice.Model = resolved.Files["model"]
+ config.ModelConfig.SenseVoice.Model = modelPath
config.ModelConfig.SenseVoice.Language = resolved.Profile.LanguageParam
config.ModelConfig.SenseVoice.UseInverseTextNormalization = 1
- config.ModelConfig.Tokens = resolved.Files["tokens"]
+ config.ModelConfig.Tokens = tokensPath
config.ModelConfig.NumThreads = resolved.Profile.NumThreads
config.ModelConfig.Provider = p.provider
config.DecodingMethod = "greedy_search"
@@ -45,6 +60,7 @@
logger.Info("Engine initialized: %s", info)
return &sherpaEngine{
recognizer: recognizer,
+ provider: p.provider,
hwInfo: info,
}, nil
}
@@ -54,14 +70,78 @@
return nil, fmt.Errorf("failed to initialize sherpa-onnx with any provider")
}
+func windowsRuntimePath(path string) string {
+ if path == "" {
+ return path
+ }
+ if isASCII(path) {
+ return path
+ }
+ short, ok := shortPathName(path)
+ if !ok || short == "" {
+ return path
+ }
+ return short
+}
+
+func isASCII(path string) bool {
+ for _, r := range path {
+ if r > 127 {
+ return false
+ }
+ }
+ return true
+}
+
+func shortPathName(path string) (string, bool) {
+ pathPtr, err := syscall.UTF16PtrFromString(path)
+ if err != nil {
+ return "", false
+ }
+
+ buf := make([]uint16, 32768)
+ ret, _, _ := procGetShortPathNameW.Call(
+ uintptr(unsafe.Pointer(pathPtr)),
+ uintptr(unsafe.Pointer(&buf[0])),
+ uintptr(len(buf)),
+ )
+ if ret == 0 || ret >= uintptr(len(buf)) {
+ return "", false
+ }
+
+ return syscall.UTF16ToString(buf[:int(ret)]), true
+}
+
func (e *sherpaEngine) Recognize(samples []float32) (string, error) {
+ totalStart := time.Now()
+ streamStart := time.Now()
stream := sherpa.NewOfflineStream(e.recognizer)
+ streamMS := durationMS(time.Since(streamStart))
defer sherpa.DeleteOfflineStream(stream)
+ acceptStart := time.Now()
stream.AcceptWaveform(16000, samples)
+ acceptMS := durationMS(time.Since(acceptStart))
+ decodeStart := time.Now()
e.recognizer.Decode(stream)
+ decodeMS := durationMS(time.Since(decodeStart))
+ resultStart := time.Now()
result := stream.GetResult()
+ resultMS := durationMS(time.Since(resultStart))
+ logger.Info(
+ "PERF engine_recognize_detail backend=%q provider=%q engine=%q samples=%d audio_ms=%d create_stream_ms=%d accept_ms=%d decode_ms=%d result_ms=%d total_ms=%d",
+ model.BackendSenseVoice,
+ e.provider,
+ e.hwInfo,
+ len(samples),
+ audioDurationMS(samples),
+ streamMS,
+ acceptMS,
+ decodeMS,
+ resultMS,
+ durationMS(time.Since(totalStart)),
+ )
return result.Text, nil
}
@@ -70,6 +150,10 @@
return e.hwInfo
}
+func (e *sherpaEngine) Provider() string {
+ return e.provider
+}
+
func (e *sherpaEngine) ReleaseTailCaptureDelay() time.Duration {
return senseVoiceReleaseTailDelay
}
--
Gitblit v1.9.3