From abdb22f7391d4128a4f89d8b668781061aedf86d Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Tue, 30 Jun 2026 03:15:49 +0800
Subject: [PATCH] Add Windows preview build

---
 privatevoice.src/internal/engine/engine_darwin.go |   46 ++++++++++++++++++++++++++++++++--------------
 1 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/privatevoice.src/internal/engine/engine_darwin.go b/privatevoice.src/internal/engine/engine_darwin.go
index d530c83..b45349d 100755
--- a/privatevoice.src/internal/engine/engine_darwin.go
+++ b/privatevoice.src/internal/engine/engine_darwin.go
@@ -16,11 +16,15 @@
 
 const (
 	asrSampleRate          = 16000
+	xasrHeadPaddingSamples = asrSampleRate / 4
 	xasrTailPaddingSamples = asrSampleRate + asrSampleRate/2
 	xasrReleaseTailDelay   = 300 * time.Millisecond
 )
 
-var xasrTailPadding = make([]float32, xasrTailPaddingSamples)
+var (
+	xasrHeadPadding = make([]float32, xasrHeadPaddingSamples)
+	xasrTailPadding = make([]float32, xasrTailPaddingSamples)
+)
 
 type sherpaEngine struct {
 	recognizer *sherpa.OfflineRecognizer
@@ -34,10 +38,11 @@
 }
 
 type xasrStreamingSession struct {
-	engine   *xasrStreamingEngine
-	stream   *sherpa.OnlineStream
-	lastText string
-	finished bool
+	engine             *xasrStreamingEngine
+	stream             *sherpa.OnlineStream
+	lastText           string
+	hasAcceptedSamples bool
+	finished           bool
 }
 
 func newPlatformEngine(resolved model.ResolvedModel) (Engine, error) {
@@ -113,21 +118,19 @@
 		config.ModelConfig.Moonshine.Encoder = resolved.Files["encoder"]
 		config.ModelConfig.Moonshine.UncachedDecoder = resolved.Files["uncached_decoder"]
 		config.ModelConfig.Moonshine.CachedDecoder = resolved.Files["cached_decoder"]
+	case model.BackendTransducer:
+		config.ModelConfig.Transducer.Encoder = resolved.Files["encoder"]
+		config.ModelConfig.Transducer.Decoder = resolved.Files["decoder"]
+		config.ModelConfig.Transducer.Joiner = resolved.Files["joiner"]
 	case model.BackendNemoTransducer:
 		config.ModelConfig.Transducer.Encoder = resolved.Files["encoder"]
 		config.ModelConfig.Transducer.Decoder = resolved.Files["decoder"]
 		config.ModelConfig.Transducer.Joiner = resolved.Files["joiner"]
 		config.ModelConfig.ModelType = model.BackendNemoTransducer
 	case model.BackendQwen3ASR:
-		config.ModelConfig.Qwen3ASR.ConvFrontend = resolved.Files["conv_frontend"]
-		config.ModelConfig.Qwen3ASR.Encoder = resolved.Files["encoder"]
-		config.ModelConfig.Qwen3ASR.Decoder = resolved.Files["decoder"]
-		config.ModelConfig.Qwen3ASR.Tokenizer = resolved.Files["tokenizer"]
-		config.ModelConfig.Qwen3ASR.MaxTotalLen = 1024
-		config.ModelConfig.Qwen3ASR.MaxNewTokens = 256
-		config.ModelConfig.Qwen3ASR.Temperature = 0.0
-		config.ModelConfig.Qwen3ASR.TopP = 0.9
-		config.ModelConfig.Qwen3ASR.Seed = 0
+		if err := applyQwen3ASRConfig(&config, resolved); err != nil {
+			return sherpa.OfflineRecognizerConfig{}, err
+		}
 	default:
 		return sherpa.OfflineRecognizerConfig{}, fmt.Errorf("unsupported backend kind: %s", resolved.BackendKind)
 	}
@@ -235,6 +238,10 @@
 	if s.stream == nil || s.finished {
 		return s.lastText, nil
 	}
+	if !s.hasAcceptedSamples {
+		samples = xasrSamplesWithHeadPadding(samples)
+		s.hasAcceptedSamples = true
+	}
 
 	s.engine.mu.Lock()
 	defer s.engine.mu.Unlock()
@@ -295,6 +302,13 @@
 	return nextText
 }
 
+func xasrSamplesWithHeadPadding(samples []float32) []float32 {
+	padded := make([]float32, 0, len(xasrHeadPadding)+len(samples))
+	padded = append(padded, xasrHeadPadding...)
+	padded = append(padded, samples...)
+	return padded
+}
+
 func (e *sherpaEngine) HardwareInfo() string {
 	return e.hwInfo
 }
@@ -307,6 +321,10 @@
 	return xasrReleaseTailDelay
 }
 
+func (e *xasrStreamingEngine) HoldPreCaptureEnabled() bool {
+	return true
+}
+
 func (e *sherpaEngine) Close() {
 	if e.recognizer != nil {
 		sherpa.DeleteOfflineRecognizer(e.recognizer)

--
Gitblit v1.9.3