sweep: name voice-daemon magic numbers, drop dead keep-alive vars (V-581)
mavsttd/whisper_handler.go: name the no_speech_prob confidence-zeroing floor (0.9) and the whisper thread count (4), both previously bare literals with no reason attached. mavttsd/piper_handler.go: name piper's render rate (22050) and the canonical wire rate (16000) used by the resampler, instead of repeating the two numbers inline four times. mavenclient/main.go: remove the strconv/io/net/time imports and their `var _ = ...` keep-alive lines — dead weight with no caller, not future scaffolding. Behaviour-preserving; no test changed. go test -race ./internal/... ./cmd/... is green.
This commit is contained in:
@@ -31,15 +31,11 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/kami/maven/internal/audio"
|
||||
"github.com/kami/maven/internal/voice"
|
||||
@@ -155,9 +151,3 @@ func writeWAV(path string, a audio.Audio) error {
|
||||
// jsonUnmarshal — kept local rather than pulling encoding/json into main.go
|
||||
// top-level space.
|
||||
func jsonUnmarshal(b []byte, v any) error { return json.Unmarshal(b, v) }
|
||||
|
||||
// keep strconv + io + net + time alive for future duration/size helpers.
|
||||
var _ = strconv.Atoi
|
||||
var _ io.Reader = (io.Reader)(nil)
|
||||
var _ = net.IPv4
|
||||
var _ = time.Second
|
||||
|
||||
@@ -22,6 +22,18 @@ import (
|
||||
// to it before sending, so it's also the rate the silence gate assumes.
|
||||
const whisperSampleRate = 16000
|
||||
|
||||
// whisperThreads — greedy decode is single-pass and this is a laptop CPU
|
||||
// (homesrv), not a server box; 4 was picked to leave headroom for the rest
|
||||
// of the daemons sharing the machine, not measured against a latency target.
|
||||
const whisperThreads = 4
|
||||
|
||||
// noSpeechFloor — whisper's own no_speech_prob past this point means the
|
||||
// segment it transcribed is not speech (the model still emits token
|
||||
// probabilities for silence/noise, so a high avgLogProb-derived confidence
|
||||
// can coexist with a segment that should be zero). Read as "at least 90%
|
||||
// sure this was not speech."
|
||||
const noSpeechFloor = 0.9
|
||||
|
||||
type whisperHandler struct {
|
||||
ctx *C.struct_whisper_context
|
||||
minMs int // clips shorter than this are dropped (hallucination bait)
|
||||
@@ -101,7 +113,7 @@ func (h *whisperHandler) Transcribe(ctx context.Context, req worker.TranscribeRe
|
||||
params.print_realtime = false
|
||||
params.print_timestamps = false
|
||||
params.print_special = false
|
||||
params.n_threads = C.int(4)
|
||||
params.n_threads = C.int(whisperThreads)
|
||||
params.single_segment = true
|
||||
|
||||
lang := C.CString(req.Lang)
|
||||
@@ -162,7 +174,7 @@ func (h *whisperHandler) Transcribe(ctx context.Context, req worker.TranscribeRe
|
||||
}
|
||||
|
||||
noSpeechProb := float64(C.whisper_full_get_segment_no_speech_prob(h.ctx, 0))
|
||||
if noSpeechProb > 0.9 {
|
||||
if noSpeechProb > noSpeechFloor {
|
||||
confidence = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -116,18 +116,27 @@ func (h *piperHandler) Synthesize(ctx context.Context, req worker.SynthesizeReq)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// resample22050To16000 converts raw 16-bit PCM from 22050 Hz to 16000 Hz
|
||||
// using linear interpolation.
|
||||
// piperSampleRate is the rate piper's onnx voices render at (ru_RU-irina and
|
||||
// the other models this daemon has been pointed at). targetSampleRate is the
|
||||
// canonical maven wire rate (audio.PCM16kMono) that every downstream
|
||||
// consumer — playback, the voice wire, whisper on the way back in — expects.
|
||||
const (
|
||||
piperSampleRate = 22050
|
||||
targetSampleRate = 16000
|
||||
)
|
||||
|
||||
// resample22050To16000 converts raw 16-bit PCM from piperSampleRate to
|
||||
// targetSampleRate using linear interpolation.
|
||||
func resample22050To16000(input []byte) []byte {
|
||||
if len(input) < 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
nSamples := len(input) / 2
|
||||
outSamples := int(float64(nSamples) * 16000.0 / 22050.0)
|
||||
outSamples := int(float64(nSamples) * float64(targetSampleRate) / float64(piperSampleRate))
|
||||
output := make([]byte, outSamples*2)
|
||||
|
||||
ratio := 22050.0 / 16000.0
|
||||
ratio := float64(piperSampleRate) / float64(targetSampleRate)
|
||||
|
||||
for i := 0; i < outSamples; i++ {
|
||||
srcPos := float64(i) * ratio
|
||||
|
||||
Reference in New Issue
Block a user