diff --git a/internal/audio/adaptive_buffer.go b/internal/audio/adaptive_buffer.go index 13b8571d..4dc30d40 100644 --- a/internal/audio/adaptive_buffer.go +++ b/internal/audio/adaptive_buffer.go @@ -234,7 +234,7 @@ func (abm *AdaptiveBufferManager) adaptationLoop() { // The algorithm runs periodically and only applies changes when the adaptation interval // has elapsed, preventing excessive adjustments that could destabilize the audio pipeline. func (abm *AdaptiveBufferManager) adaptBufferSizes() { - // Use fixed system metrics since monitoring is simplified + // Use fixed system metrics for stability systemCPU := 50.0 // Assume moderate CPU usage systemMemory := 60.0 // Assume moderate memory usage diff --git a/internal/audio/cgo_audio.go b/internal/audio/cgo_audio.go index 756b8e6e..2e6fd45d 100644 --- a/internal/audio/cgo_audio.go +++ b/internal/audio/cgo_audio.go @@ -1046,7 +1046,7 @@ func updateOpusEncoderParams(bitrate, complexity, vbr, vbrConstraint, signalType // Buffer pool for reusing buffers in CGO functions var ( // Using SizedBufferPool for better memory management - // Track buffer pool usage for monitoring + // Track buffer pool usage cgoBufferPoolGets atomic.Int64 cgoBufferPoolPuts atomic.Int64 // Batch processing statistics - only enabled in debug builds diff --git a/internal/audio/core_config_constants.go b/internal/audio/core_config_constants.go index 6a2a20e9..74a7d0ba 100644 --- a/internal/audio/core_config_constants.go +++ b/internal/audio/core_config_constants.go @@ -505,11 +505,9 @@ func DefaultAudioConfig() *AudioConfigConstants { AdaptiveMaxBufferSize: 1024, // Much higher maximum for quality changes AdaptiveDefaultBufferSize: 512, // Higher default for stability during bursts - // Adaptive Optimizer Configuration - Faster response CooldownPeriod: 15 * time.Second, // Reduced cooldown period RollbackThreshold: 200 * time.Millisecond, // Lower rollback threshold - // Latency Monitor Configuration - More aggressive monitoring MaxLatencyThreshold: 150 * time.Millisecond, // Lower max latency threshold JitterThreshold: 15 * time.Millisecond, // Reduced jitter threshold LatencyOptimizationInterval: 3 * time.Second, // More frequent optimization @@ -638,8 +636,6 @@ func DefaultAudioConfig() *AudioConfigConstants { MinFrameSize: 1, // 1 byte minimum frame size (allow small frames) FrameSizeTolerance: 512, // 512 bytes frame size tolerance - // Removed device health monitoring configuration - functionality not used - // Latency Histogram Bucket Configuration LatencyBucket10ms: 10 * time.Millisecond, // 10ms latency bucket LatencyBucket25ms: 25 * time.Millisecond, // 25ms latency bucket diff --git a/internal/audio/core_metrics.go b/internal/audio/core_metrics.go index a0dc9886..923bd1da 100644 --- a/internal/audio/core_metrics.go +++ b/internal/audio/core_metrics.go @@ -406,8 +406,7 @@ func UpdateSocketBufferMetrics(component, bufferType string, size, utilization f atomic.StoreInt64(&lastMetricsUpdate, time.Now().Unix()) } -// UpdateDeviceHealthMetrics - Device health monitoring functionality has been removed -// This function is no longer used as device health monitoring is not implemented +// UpdateDeviceHealthMetrics - Placeholder for future device health metrics // UpdateMemoryMetrics updates memory metrics func UpdateMemoryMetrics() { diff --git a/internal/audio/ipc_common.go b/internal/audio/ipc_common.go index 4b2263d7..6e35a1d8 100644 --- a/internal/audio/ipc_common.go +++ b/internal/audio/ipc_common.go @@ -132,6 +132,42 @@ func (mp *GenericMessagePool) GetStats() (hitCount, missCount int64, hitRate flo return hits, misses, hitRate } +// Helper functions + +// EncodeMessageHeader encodes a message header into a byte slice +func EncodeMessageHeader(magic uint32, msgType uint8, length uint32, timestamp int64) []byte { + header := make([]byte, 17) + binary.LittleEndian.PutUint32(header[0:4], magic) + header[4] = msgType + binary.LittleEndian.PutUint32(header[5:9], length) + binary.LittleEndian.PutUint64(header[9:17], uint64(timestamp)) + return header +} + +// EncodeAudioConfig encodes basic audio configuration to binary format +func EncodeAudioConfig(sampleRate, channels, frameSize int) []byte { + data := make([]byte, 12) // 3 * int32 + binary.LittleEndian.PutUint32(data[0:4], uint32(sampleRate)) + binary.LittleEndian.PutUint32(data[4:8], uint32(channels)) + binary.LittleEndian.PutUint32(data[8:12], uint32(frameSize)) + return data +} + +// EncodeOpusConfig encodes complete Opus configuration to binary format +func EncodeOpusConfig(sampleRate, channels, frameSize, bitrate, complexity, vbr, signalType, bandwidth, dtx int) []byte { + data := make([]byte, 36) // 9 * int32 + binary.LittleEndian.PutUint32(data[0:4], uint32(sampleRate)) + binary.LittleEndian.PutUint32(data[4:8], uint32(channels)) + binary.LittleEndian.PutUint32(data[8:12], uint32(frameSize)) + binary.LittleEndian.PutUint32(data[12:16], uint32(bitrate)) + binary.LittleEndian.PutUint32(data[16:20], uint32(complexity)) + binary.LittleEndian.PutUint32(data[20:24], uint32(vbr)) + binary.LittleEndian.PutUint32(data[24:28], uint32(signalType)) + binary.LittleEndian.PutUint32(data[28:32], uint32(bandwidth)) + binary.LittleEndian.PutUint32(data[32:36], uint32(dtx)) + return data +} + // Common write message function func WriteIPCMessage(conn net.Conn, msg IPCMessage, pool *GenericMessagePool, droppedFramesCounter *int64) error { if conn == nil { @@ -143,10 +179,8 @@ func WriteIPCMessage(conn net.Conn, msg IPCMessage, pool *GenericMessagePool, dr defer pool.Put(optMsg) // Prepare header in pre-allocated buffer - binary.LittleEndian.PutUint32(optMsg.header[0:4], msg.GetMagic()) - optMsg.header[4] = msg.GetType() - binary.LittleEndian.PutUint32(optMsg.header[5:9], msg.GetLength()) - binary.LittleEndian.PutUint64(optMsg.header[9:17], uint64(msg.GetTimestamp())) + header := EncodeMessageHeader(msg.GetMagic(), msg.GetType(), msg.GetLength(), msg.GetTimestamp()) + copy(optMsg.header[:], header) // Set write deadline for timeout handling (more efficient than goroutines) if deadline := time.Now().Add(Config.WriteTimeout); deadline.After(time.Now()) { diff --git a/internal/audio/ipc_input.go b/internal/audio/ipc_input.go index 07147af5..b8a43086 100644 --- a/internal/audio/ipc_input.go +++ b/internal/audio/ipc_input.go @@ -767,11 +767,8 @@ func (aic *AudioInputClient) SendConfig(config InputIPCConfig) error { return fmt.Errorf("input configuration validation failed: %w", err) } - // Serialize config (simple binary format) - data := make([]byte, 12) // 3 * int32 - binary.LittleEndian.PutUint32(data[0:4], uint32(config.SampleRate)) - binary.LittleEndian.PutUint32(data[4:8], uint32(config.Channels)) - binary.LittleEndian.PutUint32(data[8:12], uint32(config.FrameSize)) + // Serialize config using common function + data := EncodeAudioConfig(config.SampleRate, config.Channels, config.FrameSize) msg := &InputIPCMessage{ Magic: inputMagicNumber, @@ -799,17 +796,8 @@ func (aic *AudioInputClient) SendOpusConfig(config InputIPCOpusConfig) error { config.SampleRate, config.Channels, config.FrameSize, config.Bitrate) } - // Serialize Opus configuration (9 * int32 = 36 bytes) - data := make([]byte, 36) - binary.LittleEndian.PutUint32(data[0:4], uint32(config.SampleRate)) - binary.LittleEndian.PutUint32(data[4:8], uint32(config.Channels)) - binary.LittleEndian.PutUint32(data[8:12], uint32(config.FrameSize)) - binary.LittleEndian.PutUint32(data[12:16], uint32(config.Bitrate)) - binary.LittleEndian.PutUint32(data[16:20], uint32(config.Complexity)) - binary.LittleEndian.PutUint32(data[20:24], uint32(config.VBR)) - binary.LittleEndian.PutUint32(data[24:28], uint32(config.SignalType)) - binary.LittleEndian.PutUint32(data[28:32], uint32(config.Bandwidth)) - binary.LittleEndian.PutUint32(data[32:36], uint32(config.DTX)) + // Serialize Opus configuration using common function + data := EncodeOpusConfig(config.SampleRate, config.Channels, config.FrameSize, config.Bitrate, config.Complexity, config.VBR, config.SignalType, config.Bandwidth, config.DTX) msg := &InputIPCMessage{ Magic: inputMagicNumber, diff --git a/internal/audio/ipc_output.go b/internal/audio/ipc_output.go index d97f2dad..02ed33e3 100644 --- a/internal/audio/ipc_output.go +++ b/internal/audio/ipc_output.go @@ -173,11 +173,7 @@ func (s *AudioOutputServer) SendFrame(frame []byte) error { // writeMessage writes a message to the connection func (s *AudioOutputServer) writeMessage(conn net.Conn, msg *OutputIPCMessage) error { - header := make([]byte, 17) - binary.LittleEndian.PutUint32(header[0:4], msg.Magic) - header[4] = uint8(msg.Type) - binary.LittleEndian.PutUint32(header[5:9], msg.Length) - binary.LittleEndian.PutUint64(header[9:17], uint64(msg.Timestamp)) + header := EncodeMessageHeader(msg.Magic, uint8(msg.Type), msg.Length, msg.Timestamp) if _, err := conn.Write(header); err != nil { return fmt.Errorf("failed to write header: %w", err) diff --git a/internal/audio/ipc_unified.go b/internal/audio/ipc_unified.go index 14ad0b19..4a5a2b88 100644 --- a/internal/audio/ipc_unified.go +++ b/internal/audio/ipc_unified.go @@ -365,15 +365,7 @@ func (s *UnifiedAudioServer) SendFrame(frame []byte) error { // writeMessage writes a message to the connection func (s *UnifiedAudioServer) writeMessage(conn net.Conn, msg *UnifiedIPCMessage) error { - // Get header buffer from pool - headerPtr := headerBufferPool.Get().(*[]byte) - header := *headerPtr - defer headerBufferPool.Put(headerPtr) - - binary.LittleEndian.PutUint32(header[0:4], msg.Magic) - header[4] = uint8(msg.Type) - binary.LittleEndian.PutUint32(header[5:9], msg.Length) - binary.LittleEndian.PutUint64(header[9:17], uint64(msg.Timestamp)) + header := EncodeMessageHeader(msg.Magic, uint8(msg.Type), msg.Length, msg.Timestamp) if _, err := conn.Write(header); err != nil { return fmt.Errorf("failed to write header: %w", err) diff --git a/internal/audio/output_streaming.go b/internal/audio/output_streaming.go index 1cf404c8..5f9f60d9 100644 --- a/internal/audio/output_streaming.go +++ b/internal/audio/output_streaming.go @@ -48,8 +48,6 @@ func getOutputStreamingLogger() *zerolog.Logger { // StartAudioOutputStreaming starts audio output streaming (capturing system audio) func StartAudioOutputStreaming(send func([]byte)) error { - // Initialize audio monitoring (latency tracking and cache cleanup) - if !atomic.CompareAndSwapInt32(&outputStreamingRunning, 0, 1) { return ErrAudioAlreadyRunning }