Ariver
2026-05-18 aa6d716dff8ea05a57500aab74775292df7954b2
VoiceSnapGo/internal/audio/recorder.go
@@ -9,9 +9,9 @@
)
const (
   sampleRate     = 16000
   channels       = 1
   bitsPerSample  = 16
   sampleRate       = 16000
   channels         = 1
   bitsPerSample    = 16
   silenceThreshold = 0.05
)
@@ -25,8 +25,8 @@
type Recorder struct {
   mu sync.Mutex
   ctx     *malgo.AllocatedContext
   device  *malgo.Device
   ctx    *malgo.AllocatedContext
   device *malgo.Device
   // PCM buffer (16-bit signed, little-endian)
   pcmBuf []byte
@@ -35,11 +35,11 @@
   preferredDevice string
   // State
   isRecording      bool
   maxVolume        float64
   currentVolume    float64
   volumeCallback   func(float64)
   deviceChangeCb   func(string)
   isRecording    bool
   maxVolume      float64
   currentVolume  float64
   volumeCallback func(float64)
   deviceChangeCb func(string)
}
// NewRecorder creates a new audio recorder backed by malgo.
@@ -151,19 +151,21 @@
// Stop stops recording and discards audio data.
func (r *Recorder) Stop() {
   device := r.detachDevice()
   stopAndUninitDevice(device)
   r.mu.Lock()
   defer r.mu.Unlock()
   r.stopDevice()
   r.pcmBuf = nil
}
// StopAndGetSamples stops recording and returns the captured audio as float32 samples.
func (r *Recorder) StopAndGetSamples() []float32 {
   device := r.detachDevice()
   stopAndUninitDevice(device)
   r.mu.Lock()
   defer r.mu.Unlock()
   r.stopDevice()
   if len(r.pcmBuf) < 2 {
      return nil
@@ -203,23 +205,36 @@
// Close releases all audio resources.
func (r *Recorder) Close() {
   device := r.detachDevice()
   stopAndUninitDevice(device)
   r.mu.Lock()
   defer r.mu.Unlock()
   r.stopDevice()
   if r.ctx != nil {
      r.ctx.Free()
      r.ctx = nil
   }
}
func (r *Recorder) stopDevice() {
   if r.device != nil {
      r.device.Stop()
      r.device.Uninit()
      r.device = nil
   }
func (r *Recorder) detachDevice() *malgo.Device {
   r.mu.Lock()
   defer r.mu.Unlock()
   device := r.device
   r.device = nil
   r.isRecording = false
   return device
}
func stopAndUninitDevice(device *malgo.Device) {
   if device == nil {
      return
   }
   logger.Info("Stopping audio device")
   device.Stop()
   logger.Info("Audio device stopped")
   device.Uninit()
   logger.Info("Audio device uninitialized")
}
func (r *Recorder) onData(input []byte) {