Ariver
2026-06-07 90dfe73f1a1b6815cfba08ec165394719005e4cf
privatevoice.src/internal/engine/engine_darwin.go
@@ -16,9 +16,17 @@
   hwInfo     string
}
type xasrStreamingEngine struct {
   recognizer *sherpa.OnlineRecognizer
   hwInfo     string
}
func newPlatformEngine(resolved model.ResolvedModel) (Engine, error) {
   if !isSupportedBackend(resolved.BackendKind) {
      return nil, fmt.Errorf("unsupported backend kind: %s", resolved.BackendKind)
   }
   if resolved.BackendKind == model.BackendXASRStreaming {
      return newXASRStreamingEngine(resolved)
   }
   providers := darwinProviders(resolved.ProviderOrder)
@@ -42,6 +50,30 @@
   }
   return nil, fmt.Errorf("failed to initialize sherpa-onnx with any provider")
}
func newXASRStreamingEngine(resolved model.ResolvedModel) (Engine, error) {
   providers := darwinProviders(resolved.ProviderOrder)
   for _, p := range providers {
      config, err := onlineConfigForResolvedModel(resolved, p.provider)
      if err != nil {
         return nil, err
      }
      recognizer := sherpa.NewOnlineRecognizer(&config)
      if recognizer != nil {
         info := fmt.Sprintf("%s ยท %s", resolved.Profile.DisplayName, p.name)
         logger.Info("Engine initialized: %s", info)
         return &xasrStreamingEngine{
            recognizer: recognizer,
            hwInfo:     info,
         }, nil
      }
      logger.Info("Failed to init X-ASR with %s, trying next provider", p.name)
   }
   return nil, fmt.Errorf("failed to initialize X-ASR streaming recognizer with any provider")
}
func offlineConfigForResolvedModel(resolved model.ResolvedModel, provider string) (sherpa.OfflineRecognizerConfig, error) {
@@ -79,6 +111,29 @@
      config.ModelConfig.Qwen3ASR.Seed = 0
   default:
      return sherpa.OfflineRecognizerConfig{}, fmt.Errorf("unsupported backend kind: %s", resolved.BackendKind)
   }
   return config, nil
}
func onlineConfigForResolvedModel(resolved model.ResolvedModel, provider string) (sherpa.OnlineRecognizerConfig, error) {
   config := sherpa.OnlineRecognizerConfig{}
   config.FeatConfig.SampleRate = 16000
   config.FeatConfig.FeatureDim = 80
   config.ModelConfig.Tokens = resolved.Files["tokens"]
   config.ModelConfig.NumThreads = resolved.Profile.NumThreads
   config.ModelConfig.Provider = provider
   config.ModelConfig.ModelType = "zipformer2"
   config.DecodingMethod = "greedy_search"
   config.EnableEndpoint = 0
   switch resolved.BackendKind {
   case model.BackendXASRStreaming:
      config.ModelConfig.Transducer.Encoder = resolved.Files["encoder"]
      config.ModelConfig.Transducer.Decoder = resolved.Files["decoder"]
      config.ModelConfig.Transducer.Joiner = resolved.Files["joiner"]
   default:
      return sherpa.OnlineRecognizerConfig{}, fmt.Errorf("unsupported online backend kind: %s", resolved.BackendKind)
   }
   return config, nil
@@ -127,7 +182,32 @@
   return result.Text, nil
}
func (e *xasrStreamingEngine) Recognize(samples []float32) (string, error) {
   stream := sherpa.NewOnlineStream(e.recognizer)
   defer sherpa.DeleteOnlineStream(stream)
   if len(samples) > 0 {
      stream.AcceptWaveform(16000, samples)
   }
   stream.InputFinished()
   for e.recognizer.IsReady(stream) {
      e.recognizer.Decode(stream)
   }
   result := e.recognizer.GetResult(stream)
   if result == nil {
      return "", nil
   }
   return result.Text, nil
}
func (e *sherpaEngine) HardwareInfo() string {
   return e.hwInfo
}
func (e *xasrStreamingEngine) HardwareInfo() string {
   return e.hwInfo
}
@@ -137,3 +217,10 @@
      e.recognizer = nil
   }
}
func (e *xasrStreamingEngine) Close() {
   if e.recognizer != nil {
      sherpa.DeleteOnlineRecognizer(e.recognizer)
      e.recognizer = nil
   }
}