diff --git a/internal/audio/adaptive_buffer.go b/internal/audio/adaptive_buffer.go index 057532b..64fbc06 100644 --- a/internal/audio/adaptive_buffer.go +++ b/internal/audio/adaptive_buffer.go @@ -42,20 +42,20 @@ func DefaultAdaptiveBufferConfig() AdaptiveBufferConfig { DefaultBufferSize: 6, // Default 6 frames (increased for better stability) // CPU thresholds optimized for single-core ARM Cortex A7 under load - LowCPUThreshold: 20.0, // Below 20% CPU - HighCPUThreshold: 60.0, // Above 60% CPU (lowered to be more responsive) + LowCPUThreshold: GetConfig().LowCPUThreshold * 100, // Below 20% CPU + HighCPUThreshold: GetConfig().HighCPUThreshold * 100, // Above 60% CPU (lowered to be more responsive) // Memory thresholds for 256MB total RAM - LowMemoryThreshold: 35.0, // Below 35% memory usage - HighMemoryThreshold: 75.0, // Above 75% memory usage (lowered for earlier response) + LowMemoryThreshold: GetConfig().LowMemoryThreshold * 100, // Below 35% memory usage + HighMemoryThreshold: GetConfig().HighMemoryThreshold * 100, // Above 75% memory usage (lowered for earlier response) // Latency targets - TargetLatency: 20 * time.Millisecond, // Target 20ms latency - MaxLatency: 50 * time.Millisecond, // Max acceptable 50ms + TargetLatency: GetConfig().TargetLatency, // Target 20ms latency + MaxLatency: GetConfig().MaxLatencyTarget, // Max acceptable latency // Adaptation settings - AdaptationInterval: 500 * time.Millisecond, // Check every 500ms - SmoothingFactor: 0.3, // Moderate responsiveness + AdaptationInterval: GetConfig().BufferUpdateInterval, // Check every 500ms + SmoothingFactor: GetConfig().SmoothingFactor, // Moderate responsiveness } } @@ -133,7 +133,7 @@ func (abm *AdaptiveBufferManager) UpdateLatency(latency time.Duration) { atomic.StoreInt64(&abm.averageLatency, newLatency) } else { // Exponential moving average: 70% historical, 30% current - newAvg := int64(float64(currentAvg)*0.7 + float64(newLatency)*0.3) + newAvg := int64(float64(currentAvg)*GetConfig().HistoricalWeight + float64(newLatency)*GetConfig().CurrentWeight) atomic.StoreInt64(&abm.averageLatency, newAvg) } } @@ -195,7 +195,7 @@ func (abm *AdaptiveBufferManager) adaptBufferSizes() { latencyFactor := abm.calculateLatencyFactor(currentLatency) // Combine factors with weights (CPU has highest priority for KVM coexistence) - combinedFactor := 0.5*cpuFactor + 0.3*memoryFactor + 0.2*latencyFactor + combinedFactor := GetConfig().CPUMemoryWeight*cpuFactor + GetConfig().MemoryWeight*memoryFactor + GetConfig().LatencyWeight*latencyFactor // Apply adaptation with smoothing currentInput := float64(atomic.LoadInt64(&abm.currentInputBufferSize)) @@ -306,8 +306,8 @@ func (abm *AdaptiveBufferManager) GetStats() map[string]interface{} { "input_buffer_size": abm.GetInputBufferSize(), "output_buffer_size": abm.GetOutputBufferSize(), "average_latency_ms": float64(atomic.LoadInt64(&abm.averageLatency)) / 1e6, - "system_cpu_percent": float64(atomic.LoadInt64(&abm.systemCPUPercent)) / 100, - "system_memory_percent": float64(atomic.LoadInt64(&abm.systemMemoryPercent)) / 100, + "system_cpu_percent": float64(atomic.LoadInt64(&abm.systemCPUPercent)) / GetConfig().PercentageMultiplier, + "system_memory_percent": float64(atomic.LoadInt64(&abm.systemMemoryPercent)) / GetConfig().PercentageMultiplier, "adaptation_count": atomic.LoadInt64(&abm.adaptationCount), "last_adaptation": lastAdaptation, } diff --git a/internal/audio/adaptive_optimizer.go b/internal/audio/adaptive_optimizer.go index e9ac814..89fdf70 100644 --- a/internal/audio/adaptive_optimizer.go +++ b/internal/audio/adaptive_optimizer.go @@ -42,9 +42,9 @@ type OptimizerConfig struct { func DefaultOptimizerConfig() OptimizerConfig { return OptimizerConfig{ MaxOptimizationLevel: 8, - CooldownPeriod: 30 * time.Second, - Aggressiveness: 0.7, - RollbackThreshold: 300 * time.Millisecond, + CooldownPeriod: GetConfig().CooldownPeriod, + Aggressiveness: GetConfig().OptimizerAggressiveness, + RollbackThreshold: GetConfig().RollbackThreshold, StabilityPeriod: 10 * time.Second, } } @@ -109,7 +109,7 @@ func (ao *AdaptiveOptimizer) handleLatencyOptimization(metrics LatencyMetrics) e // calculateTargetOptimizationLevel determines the appropriate optimization level func (ao *AdaptiveOptimizer) calculateTargetOptimizationLevel(metrics LatencyMetrics) int64 { // Base calculation on current latency vs target - latencyRatio := float64(metrics.Current) / float64(50*time.Millisecond) // 50ms target + latencyRatio := float64(metrics.Current) / float64(GetConfig().LatencyTarget) // 50ms target // Adjust based on trend switch metrics.Trend { @@ -125,7 +125,7 @@ func (ao *AdaptiveOptimizer) calculateTargetOptimizationLevel(metrics LatencyMet latencyRatio *= ao.config.Aggressiveness // Convert to optimization level - targetLevel := int64(latencyRatio * 2) // Scale to 0-10 range + targetLevel := int64(latencyRatio * GetConfig().LatencyScalingFactor) // Scale to 0-10 range if targetLevel > int64(ao.config.MaxOptimizationLevel) { targetLevel = int64(ao.config.MaxOptimizationLevel) } diff --git a/internal/audio/audio.go b/internal/audio/audio.go index 243899a..90fc1ed 100644 --- a/internal/audio/audio.go +++ b/internal/audio/audio.go @@ -47,17 +47,17 @@ type AudioMetrics struct { var ( currentConfig = AudioConfig{ Quality: AudioQualityMedium, - Bitrate: 64, + Bitrate: GetConfig().AudioQualityMediumOutputBitrate, SampleRate: GetConfig().SampleRate, Channels: GetConfig().Channels, - FrameSize: 20 * time.Millisecond, + FrameSize: GetConfig().AudioQualityMediumFrameSize, } currentMicrophoneConfig = AudioConfig{ Quality: AudioQualityMedium, - Bitrate: 32, + Bitrate: GetConfig().AudioQualityMediumInputBitrate, SampleRate: GetConfig().SampleRate, Channels: 1, - FrameSize: 20 * time.Millisecond, + FrameSize: GetConfig().AudioQualityMediumFrameSize, } metrics AudioMetrics ) @@ -69,24 +69,24 @@ var qualityPresets = map[AudioQuality]struct { frameSize time.Duration }{ AudioQualityLow: { - outputBitrate: 32, inputBitrate: 16, - sampleRate: 22050, channels: 1, - frameSize: 40 * time.Millisecond, + outputBitrate: GetConfig().AudioQualityLowOutputBitrate, inputBitrate: GetConfig().AudioQualityLowInputBitrate, + sampleRate: GetConfig().AudioQualityLowSampleRate, channels: GetConfig().AudioQualityLowChannels, + frameSize: GetConfig().AudioQualityLowFrameSize, }, AudioQualityMedium: { - outputBitrate: 64, inputBitrate: 32, - sampleRate: 44100, channels: 2, - frameSize: 20 * time.Millisecond, + outputBitrate: GetConfig().AudioQualityMediumOutputBitrate, inputBitrate: GetConfig().AudioQualityMediumInputBitrate, + sampleRate: GetConfig().AudioQualityMediumSampleRate, channels: GetConfig().AudioQualityMediumChannels, + frameSize: GetConfig().AudioQualityMediumFrameSize, }, AudioQualityHigh: { - outputBitrate: 128, inputBitrate: 64, - sampleRate: GetConfig().SampleRate, channels: GetConfig().Channels, - frameSize: 20 * time.Millisecond, + outputBitrate: GetConfig().AudioQualityHighOutputBitrate, inputBitrate: GetConfig().AudioQualityHighInputBitrate, + sampleRate: GetConfig().SampleRate, channels: GetConfig().AudioQualityHighChannels, + frameSize: GetConfig().AudioQualityHighFrameSize, }, AudioQualityUltra: { - outputBitrate: 192, inputBitrate: 96, - sampleRate: GetConfig().SampleRate, channels: GetConfig().Channels, - frameSize: 10 * time.Millisecond, + outputBitrate: GetConfig().AudioQualityUltraOutputBitrate, inputBitrate: GetConfig().AudioQualityUltraInputBitrate, + sampleRate: GetConfig().SampleRate, channels: GetConfig().AudioQualityUltraChannels, + frameSize: GetConfig().AudioQualityUltraFrameSize, }, } @@ -114,7 +114,7 @@ func GetMicrophoneQualityPresets() map[AudioQuality]AudioConfig { Bitrate: preset.inputBitrate, SampleRate: func() int { if quality == AudioQualityLow { - return 16000 + return GetConfig().AudioQualityMicLowSampleRate } return preset.sampleRate }(), diff --git a/internal/audio/batch_audio.go b/internal/audio/batch_audio.go index 253e94c..9e9dc29 100644 --- a/internal/audio/batch_audio.go +++ b/internal/audio/batch_audio.go @@ -72,7 +72,7 @@ func NewBatchAudioProcessor(batchSize int, batchDuration time.Duration) *BatchAu readQueue: make(chan batchReadRequest, batchSize*2), readBufPool: &sync.Pool{ New: func() interface{} { - return make([]byte, 1500) // Max audio frame size + return make([]byte, GetConfig().AudioFramePoolSize) // Max audio frame size }, }, } @@ -110,7 +110,7 @@ func (bap *BatchAudioProcessor) Stop() { bap.cancel() // Wait for processing to complete - time.Sleep(bap.batchDuration + 10*time.Millisecond) + time.Sleep(bap.batchDuration + GetConfig().BatchProcessingDelay) bap.logger.Info().Msg("batch audio processor stopped") } @@ -134,7 +134,7 @@ func (bap *BatchAudioProcessor) BatchReadEncode(buffer []byte) (int, error) { select { case bap.readQueue <- request: // Successfully queued - case <-time.After(5 * time.Millisecond): + case <-time.After(GetConfig().ShortTimeout): // Queue is full or blocked, fallback to single operation atomic.AddInt64(&bap.stats.SingleReads, 1) atomic.AddInt64(&bap.stats.SingleFrames, 1) @@ -145,7 +145,7 @@ func (bap *BatchAudioProcessor) BatchReadEncode(buffer []byte) (int, error) { select { case result := <-resultChan: return result.length, result.err - case <-time.After(50 * time.Millisecond): + case <-time.After(GetConfig().MediumTimeout): // Timeout, fallback to single operation atomic.AddInt64(&bap.stats.SingleReads, 1) atomic.AddInt64(&bap.stats.SingleFrames, 1) diff --git a/internal/audio/buffer_pool.go b/internal/audio/buffer_pool.go index cf26e28..c9ab45f 100644 --- a/internal/audio/buffer_pool.go +++ b/internal/audio/buffer_pool.go @@ -23,7 +23,7 @@ type AudioBufferPool struct { func NewAudioBufferPool(bufferSize int) *AudioBufferPool { // Pre-allocate 20% of max pool size for immediate availability - preallocSize := 20 + preallocSize := GetConfig().PreallocPercentage preallocated := make([]*[]byte, 0, preallocSize) // Pre-allocate buffers to reduce initial allocation overhead @@ -34,7 +34,7 @@ func NewAudioBufferPool(bufferSize int) *AudioBufferPool { return &AudioBufferPool{ bufferSize: bufferSize, - maxPoolSize: 100, // Limit pool size to prevent excessive memory usage + maxPoolSize: GetConfig().MaxPoolSize, // Limit pool size to prevent excessive memory usage preallocated: preallocated, preallocSize: preallocSize, pool: sync.Pool{ @@ -111,8 +111,8 @@ func (p *AudioBufferPool) Put(buf []byte) { } var ( - audioFramePool = NewAudioBufferPool(1500) - audioControlPool = NewAudioBufferPool(64) + audioFramePool = NewAudioBufferPool(GetConfig().AudioFramePoolSize) + audioControlPool = NewAudioBufferPool(GetConfig().OutputHeaderSize) ) func GetAudioFrameBuffer() []byte { @@ -144,7 +144,7 @@ func (p *AudioBufferPool) GetPoolStats() AudioBufferPoolDetailedStats { var hitRate float64 if totalRequests > 0 { - hitRate = float64(hitCount) / float64(totalRequests) * 100 + hitRate = float64(hitCount) / float64(totalRequests) * GetConfig().PercentageMultiplier } return AudioBufferPoolDetailedStats{ diff --git a/internal/audio/cgo_audio.go b/internal/audio/cgo_audio.go index 63016fc..f480b9a 100644 --- a/internal/audio/cgo_audio.go +++ b/internal/audio/cgo_audio.go @@ -22,18 +22,37 @@ static snd_pcm_t *pcm_handle = NULL; static snd_pcm_t *pcm_playback_handle = NULL; static OpusEncoder *encoder = NULL; static OpusDecoder *decoder = NULL; -// Optimized Opus encoder settings for ARM Cortex-A7 -static int opus_bitrate = 96000; // Increased for better quality -static int opus_complexity = 3; // Reduced for ARM performance -static int opus_vbr = 1; // Variable bitrate enabled -static int opus_vbr_constraint = 1; // Constrained VBR for consistent latency -static int opus_signal_type = OPUS_SIGNAL_MUSIC; // Optimized for general audio -static int opus_bandwidth = OPUS_BANDWIDTH_FULLBAND; // Full bandwidth -static int opus_dtx = 0; // Disable DTX for real-time audio -static int sample_rate = 48000; -static int channels = 2; -static int frame_size = 960; // 20ms for 48kHz -static int max_packet_size = 1500; +// Opus encoder settings - initialized from Go configuration +static int opus_bitrate = 96000; // Will be set from GetConfig().CGOOpusBitrate +static int opus_complexity = 3; // Will be set from GetConfig().CGOOpusComplexity +static int opus_vbr = 1; // Will be set from GetConfig().CGOOpusVBR +static int opus_vbr_constraint = 1; // Will be set from GetConfig().CGOOpusVBRConstraint +static int opus_signal_type = 3; // Will be set from GetConfig().CGOOpusSignalType +static int opus_bandwidth = 1105; // Will be set from GetConfig().CGOOpusBandwidth +static int opus_dtx = 0; // Will be set from GetConfig().CGOOpusDTX +static int sample_rate = 48000; // Will be set from GetConfig().CGOSampleRate +static int channels = 2; // Will be set from GetConfig().CGOChannels +static int frame_size = 960; // Will be set from GetConfig().CGOFrameSize +static int max_packet_size = 1500; // Will be set from GetConfig().CGOMaxPacketSize +static int sleep_microseconds = 50000; // Will be set from GetConfig().CGOSleepMicroseconds + +// Function to update constants from Go configuration +void update_audio_constants(int bitrate, int complexity, int vbr, int vbr_constraint, + int signal_type, int bandwidth, int dtx, int sr, int ch, + int fs, int max_pkt, int sleep_us) { + opus_bitrate = bitrate; + opus_complexity = complexity; + opus_vbr = vbr; + opus_vbr_constraint = vbr_constraint; + opus_signal_type = signal_type; + opus_bandwidth = bandwidth; + opus_dtx = dtx; + sample_rate = sr; + channels = ch; + frame_size = fs; + max_packet_size = max_pkt; + sleep_microseconds = sleep_us; +} // State tracking to prevent race conditions during rapid start/stop static volatile int capture_initializing = 0; @@ -56,7 +75,7 @@ static int safe_alsa_open(snd_pcm_t **handle, const char *device, snd_pcm_stream if (err == -EBUSY && attempts > 0) { // Device busy, wait and retry - usleep(50000); // 50ms + usleep(sleep_microseconds); // 50ms continue; } break; @@ -415,8 +434,25 @@ var ( ) func cgoAudioInit() error { - ret := C.jetkvm_audio_init() - if ret != 0 { + // Update C constants from Go configuration + config := GetConfig() + C.update_audio_constants( + C.int(config.CGOOpusBitrate), + C.int(config.CGOOpusComplexity), + C.int(config.CGOOpusVBR), + C.int(config.CGOOpusVBRConstraint), + C.int(config.CGOOpusSignalType), + C.int(config.CGOOpusBandwidth), + C.int(config.CGOOpusDTX), + C.int(config.CGOSampleRate), + C.int(config.CGOChannels), + C.int(config.CGOFrameSize), + C.int(config.CGOMaxPacketSize), + C.int(config.CGOSleepMicroseconds), + ) + + result := C.jetkvm_audio_init() + if result != 0 { return errAudioInitFailed } return nil @@ -427,7 +463,7 @@ func cgoAudioClose() { } func cgoAudioReadEncode(buf []byte) (int, error) { - if len(buf) < 1276 { + if len(buf) < GetConfig().MinReadEncodeBuffer { return 0, errBufferTooSmall } @@ -461,7 +497,7 @@ func cgoAudioDecodeWrite(buf []byte) (int, error) { if buf == nil { return 0, errNilBuffer } - if len(buf) > 4096 { + if len(buf) > GetConfig().MaxDecodeWriteBuffer { return 0, errBufferTooLarge } diff --git a/internal/audio/config_constants.go b/internal/audio/config_constants.go index b1a956c..b09e5aa 100644 --- a/internal/audio/config_constants.go +++ b/internal/audio/config_constants.go @@ -2,53 +2,695 @@ package audio import "time" -// AudioConfigConstants centralizes all hardcoded values used across audio components +// AudioConfigConstants centralizes all hardcoded values used across audio components. +// This configuration system allows runtime tuning of audio performance, quality, and resource usage. +// Each constant is documented with its purpose, usage location, and impact on system behavior. type AudioConfigConstants struct { // Audio Quality Presets + // MaxAudioFrameSize defines the maximum size of an audio frame in bytes. + // Used in: buffer_pool.go, adaptive_buffer.go + // Impact: Higher values allow larger audio chunks but increase memory usage and latency. + // Typical range: 1024-8192 bytes. Default 4096 provides good balance. MaxAudioFrameSize int - // Opus Encoding Parameters - OpusBitrate int - OpusComplexity int - OpusVBR int - OpusVBRConstraint int - OpusDTX int + // Opus Encoding Parameters - Core codec settings for audio compression + // OpusBitrate sets the target bitrate for Opus encoding in bits per second. + // Used in: cgo_audio.go for encoder initialization + // Impact: Higher bitrates improve audio quality but increase bandwidth usage. + // Range: 6000-510000 bps. 128000 (128kbps) provides high quality for most use cases. + OpusBitrate int - // Audio Parameters - SampleRate int - Channels int - FrameSize int + // OpusComplexity controls the computational complexity of Opus encoding (0-10). + // Used in: cgo_audio.go for encoder configuration + // Impact: Higher values improve quality but increase CPU usage and encoding latency. + // Range: 0-10. Value 10 provides best quality, 0 fastest encoding. + OpusComplexity int + + // OpusVBR enables Variable Bit Rate encoding (0=CBR, 1=VBR). + // Used in: cgo_audio.go for encoder mode selection + // Impact: VBR (1) adapts bitrate to content complexity, improving efficiency. + // CBR (0) maintains constant bitrate for predictable bandwidth usage. + OpusVBR int + + // OpusVBRConstraint enables constrained VBR mode (0=unconstrained, 1=constrained). + // Used in: cgo_audio.go when VBR is enabled + // Impact: Constrained VBR (1) limits bitrate variation for more predictable bandwidth. + // Unconstrained (0) allows full bitrate adaptation for optimal quality. + OpusVBRConstraint int + + // OpusDTX enables Discontinuous Transmission (0=disabled, 1=enabled). + // Used in: cgo_audio.go for encoder optimization + // Impact: DTX (1) reduces bandwidth during silence but may cause audio artifacts. + // Disabled (0) maintains constant transmission for consistent quality. + OpusDTX int + + // Audio Parameters - Fundamental audio stream characteristics + // SampleRate defines the number of audio samples per second in Hz. + // Used in: All audio processing components + // Impact: Higher rates improve frequency response but increase processing load. + // Common values: 16000 (voice), 44100 (CD quality), 48000 (professional). + SampleRate int + + // Channels specifies the number of audio channels (1=mono, 2=stereo). + // Used in: All audio processing and encoding/decoding operations + // Impact: Stereo (2) provides spatial audio but doubles bandwidth and processing. + // Mono (1) reduces resource usage but loses spatial information. + Channels int + + // FrameSize defines the number of samples per audio frame. + // Used in: Opus encoding/decoding, buffer management + // Impact: Larger frames reduce overhead but increase latency. + // Must match Opus frame sizes: 120, 240, 480, 960, 1920, 2880 samples. + FrameSize int + + // MaxPacketSize sets the maximum size of encoded audio packets in bytes. + // Used in: Network transmission, buffer allocation + // Impact: Larger packets reduce network overhead but increase burst bandwidth. + // Should accommodate worst-case Opus output plus protocol headers. MaxPacketSize int - // Process Management + // Audio Quality Bitrates - Predefined quality presets for different use cases + // These bitrates are used in audio.go for quality level selection + // Impact: Higher bitrates improve audio fidelity but increase bandwidth usage + + // AudioQualityLowOutputBitrate defines bitrate for low-quality audio output (kbps). + // Used in: audio.go for bandwidth-constrained scenarios + // Impact: Minimal bandwidth usage but reduced audio quality. Suitable for voice-only. + // Default 32kbps provides acceptable voice quality with very low bandwidth. + AudioQualityLowOutputBitrate int + + // AudioQualityLowInputBitrate defines bitrate for low-quality audio input (kbps). + // Used in: audio.go for microphone input in low-bandwidth scenarios + // Impact: Reduces upload bandwidth but may affect voice clarity. + // Default 16kbps suitable for basic voice communication. + AudioQualityLowInputBitrate int + + // AudioQualityMediumOutputBitrate defines bitrate for medium-quality audio output (kbps). + // Used in: audio.go for balanced quality/bandwidth scenarios + // Impact: Good balance between quality and bandwidth usage. + // Default 64kbps provides clear voice and acceptable music quality. + AudioQualityMediumOutputBitrate int + + // AudioQualityMediumInputBitrate defines bitrate for medium-quality audio input (kbps). + // Used in: audio.go for microphone input with balanced quality + // Impact: Better voice quality than low setting with moderate bandwidth usage. + // Default 32kbps suitable for clear voice communication. + AudioQualityMediumInputBitrate int + + // AudioQualityHighOutputBitrate defines bitrate for high-quality audio output (kbps). + // Used in: audio.go for high-fidelity audio scenarios + // Impact: Excellent audio quality but higher bandwidth requirements. + // Default 128kbps provides near-CD quality for music and crystal-clear voice. + AudioQualityHighOutputBitrate int + + // AudioQualityHighInputBitrate defines bitrate for high-quality audio input (kbps). + // Used in: audio.go for high-quality microphone capture + // Impact: Superior voice quality but increased upload bandwidth usage. + // Default 64kbps suitable for professional voice communication. + AudioQualityHighInputBitrate int + + // AudioQualityUltraOutputBitrate defines bitrate for ultra-high-quality audio output (kbps). + // Used in: audio.go for maximum quality scenarios + // Impact: Maximum audio fidelity but highest bandwidth consumption. + // Default 192kbps provides studio-quality audio for critical applications. + AudioQualityUltraOutputBitrate int + + // AudioQualityUltraInputBitrate defines bitrate for ultra-high-quality audio input (kbps). + // Used in: audio.go for maximum quality microphone capture + // Impact: Best possible voice quality but maximum upload bandwidth usage. + // Default 96kbps suitable for broadcast-quality voice communication. + AudioQualityUltraInputBitrate int + + // Audio Quality Sample Rates - Frequency sampling rates for different quality levels + // Used in: audio.go for configuring audio capture and playback sample rates + // Impact: Higher sample rates capture more frequency detail but increase processing load + + // AudioQualityLowSampleRate defines sample rate for low-quality audio (Hz). + // Used in: audio.go for bandwidth-constrained scenarios + // Impact: Reduces frequency response but minimizes processing and bandwidth. + // Default 22050Hz captures frequencies up to 11kHz, adequate for voice. + AudioQualityLowSampleRate int + + // AudioQualityMediumSampleRate defines sample rate for medium-quality audio (Hz). + // Used in: audio.go for balanced quality scenarios + // Impact: Good frequency response with moderate processing requirements. + // Default 44100Hz (CD quality) captures frequencies up to 22kHz. + AudioQualityMediumSampleRate int + + // AudioQualityMicLowSampleRate defines sample rate for low-quality microphone input (Hz). + // Used in: audio.go for microphone capture in constrained scenarios + // Impact: Optimized for voice communication with minimal processing overhead. + // Default 16000Hz captures voice frequencies (300-3400Hz) efficiently. + AudioQualityMicLowSampleRate int + + // Audio Quality Frame Sizes - Duration of audio frames for different quality levels + // Used in: audio.go for configuring Opus frame duration + // Impact: Larger frames reduce overhead but increase latency and memory usage + + // AudioQualityLowFrameSize defines frame duration for low-quality audio. + // Used in: audio.go for low-latency scenarios with minimal processing + // Impact: Longer frames reduce CPU overhead but increase audio latency. + // Default 40ms provides good efficiency for voice communication. + AudioQualityLowFrameSize time.Duration + + // AudioQualityMediumFrameSize defines frame duration for medium-quality audio. + // Used in: audio.go for balanced latency and efficiency + // Impact: Moderate frame size balances latency and processing efficiency. + // Default 20ms provides good balance for most applications. + AudioQualityMediumFrameSize time.Duration + + // AudioQualityHighFrameSize defines frame duration for high-quality audio. + // Used in: audio.go for high-quality scenarios + // Impact: Optimized frame size for high-quality encoding efficiency. + // Default 20ms maintains low latency while supporting high bitrates. + AudioQualityHighFrameSize time.Duration + + // AudioQualityUltraFrameSize defines frame duration for ultra-quality audio. + // Used in: audio.go for maximum quality scenarios + // Impact: Smaller frames reduce latency but increase processing overhead. + // Default 10ms provides minimal latency for real-time applications. + AudioQualityUltraFrameSize time.Duration + + // Audio Quality Channels - Channel configuration for different quality levels + // Used in: audio.go for configuring mono/stereo audio + // Impact: Stereo doubles bandwidth and processing but provides spatial audio + + // AudioQualityLowChannels defines channel count for low-quality audio. + // Used in: audio.go for bandwidth-constrained scenarios + // Impact: Mono (1) minimizes bandwidth and processing for voice communication. + // Default 1 (mono) suitable for voice-only applications. + AudioQualityLowChannels int + + // AudioQualityMediumChannels defines channel count for medium-quality audio. + // Used in: audio.go for balanced quality scenarios + // Impact: Stereo (2) provides spatial audio with moderate bandwidth increase. + // Default 2 (stereo) suitable for general audio applications. + AudioQualityMediumChannels int + + // AudioQualityHighChannels defines channel count for high-quality audio. + // Used in: audio.go for high-fidelity scenarios + // Impact: Stereo (2) essential for high-quality music and spatial audio. + // Default 2 (stereo) required for full audio experience. + AudioQualityHighChannels int + + // AudioQualityUltraChannels defines channel count for ultra-quality audio. + // Used in: audio.go for maximum quality scenarios + // Impact: Stereo (2) mandatory for studio-quality audio reproduction. + // Default 2 (stereo) provides full spatial audio fidelity. + AudioQualityUltraChannels int + + // CGO Audio Constants - Low-level C library configuration for audio processing + // These constants are passed to C code in cgo_audio.go for native audio operations + // Impact: Direct control over native audio library behavior and performance + + // CGOOpusBitrate sets the bitrate for native Opus encoder (bits per second). + // Used in: cgo_audio.go update_audio_constants() function + // Impact: Controls quality vs bandwidth tradeoff in native encoding. + // Default 96000 (96kbps) provides good quality for real-time applications. + CGOOpusBitrate int + + // CGOOpusComplexity sets computational complexity for native Opus encoder (0-10). + // Used in: cgo_audio.go for native encoder configuration + // Impact: Higher values improve quality but increase CPU usage in C code. + // Default 3 balances quality and performance for embedded systems. + CGOOpusComplexity int + + // CGOOpusVBR enables Variable Bit Rate in native Opus encoder (0=CBR, 1=VBR). + // Used in: cgo_audio.go for native encoder mode selection + // Impact: VBR (1) adapts bitrate dynamically for better efficiency. + // Default 1 (VBR) provides optimal bandwidth utilization. + CGOOpusVBR int + + // CGOOpusVBRConstraint enables constrained VBR in native encoder (0/1). + // Used in: cgo_audio.go when VBR is enabled + // Impact: Constrains bitrate variation for more predictable bandwidth. + // Default 1 (constrained) provides controlled bandwidth usage. + CGOOpusVBRConstraint int + + // CGOOpusSignalType specifies signal type hint for native Opus encoder. + // Used in: cgo_audio.go for encoder optimization + // Impact: Optimizes encoder for specific content type (voice vs music). + // Values: 3=OPUS_SIGNAL_MUSIC for general audio, 2=OPUS_SIGNAL_VOICE for speech. + CGOOpusSignalType int + + // CGOOpusBandwidth sets frequency bandwidth for native Opus encoder. + // Used in: cgo_audio.go for encoder frequency range configuration + // Impact: Controls frequency range vs bitrate efficiency. + // Default 1105 (OPUS_BANDWIDTH_FULLBAND) uses full 20kHz bandwidth. + CGOOpusBandwidth int + + // CGOOpusDTX enables Discontinuous Transmission in native encoder (0/1). + // Used in: cgo_audio.go for bandwidth optimization during silence + // Impact: Reduces bandwidth during silence but may cause audio artifacts. + // Default 0 (disabled) maintains consistent audio quality. + CGOOpusDTX int + + // CGOSampleRate defines sample rate for native audio processing (Hz). + // Used in: cgo_audio.go for ALSA and Opus configuration + // Impact: Must match system audio capabilities and Opus requirements. + // Default 48000Hz provides professional audio quality. + CGOSampleRate int + + // CGOChannels defines channel count for native audio processing. + // Used in: cgo_audio.go for ALSA device and Opus encoder configuration + // Impact: Must match audio hardware capabilities and application needs. + // Default 2 (stereo) provides full spatial audio support. + CGOChannels int + + // CGOFrameSize defines frame size for native Opus processing (samples). + // Used in: cgo_audio.go for Opus encoder/decoder frame configuration + // Impact: Must be valid Opus frame size, affects latency and efficiency. + // Default 960 samples (20ms at 48kHz) balances latency and efficiency. + CGOFrameSize int + + // CGOMaxPacketSize defines maximum packet size for native encoding (bytes). + // Used in: cgo_audio.go for buffer allocation in C code + // Impact: Must accommodate worst-case Opus output to prevent buffer overruns. + // Default 1500 bytes handles typical Opus output with safety margin. + CGOMaxPacketSize int + + // Input IPC Constants - Configuration for audio input inter-process communication + // Used in: input_ipc.go for microphone audio capture and processing + // Impact: Controls audio input quality and processing efficiency + + // InputIPCSampleRate defines sample rate for input IPC audio processing (Hz). + // Used in: input_ipc.go for microphone capture configuration + // Impact: Must match microphone capabilities and encoding requirements. + // Default 48000Hz provides professional quality microphone input. + InputIPCSampleRate int + + // InputIPCChannels defines channel count for input IPC audio processing. + // Used in: input_ipc.go for microphone channel configuration + // Impact: Stereo (2) captures spatial audio, mono (1) reduces processing. + // Default 2 (stereo) supports full microphone array capabilities. + InputIPCChannels int + + // InputIPCFrameSize defines frame size for input IPC processing (samples). + // Used in: input_ipc.go for microphone frame processing + // Impact: Larger frames reduce overhead but increase input latency. + // Default 960 samples (20ms at 48kHz) balances latency and efficiency. + InputIPCFrameSize int + + // Output IPC Constants - Configuration for audio output inter-process communication + // Used in: output_streaming.go for audio playback and streaming + // Impact: Controls audio output quality, latency, and reliability + + // OutputMaxFrameSize defines maximum frame size for output processing (bytes). + // Used in: output_streaming.go for buffer allocation and frame processing + // Impact: Larger frames allow bigger audio chunks but increase memory usage. + // Default 4096 bytes accommodates typical audio frames with safety margin. + OutputMaxFrameSize int + + // OutputWriteTimeout defines timeout for output write operations. + // Used in: output_streaming.go for preventing blocking on slow audio devices + // Impact: Shorter timeouts improve responsiveness but may cause audio drops. + // Default 10ms prevents blocking while allowing device response time. + OutputWriteTimeout time.Duration + + // OutputMaxDroppedFrames defines maximum consecutive dropped frames before error. + // Used in: output_streaming.go for audio quality monitoring + // Impact: Higher values tolerate more audio glitches but may degrade experience. + // Default 50 frames allows brief interruptions while detecting serious issues. + OutputMaxDroppedFrames int + + // OutputHeaderSize defines size of output message headers (bytes). + // Used in: output_streaming.go for message parsing and buffer allocation + // Impact: Must match actual header size to prevent parsing errors. + // Default 17 bytes matches current output message header format. + OutputHeaderSize int + + // OutputMessagePoolSize defines size of output message object pool. + // Used in: output_streaming.go for memory management and performance + // Impact: Larger pools reduce allocation overhead but increase memory usage. + // Default 128 messages provides good balance for typical workloads. + OutputMessagePoolSize int + + // Socket Buffer Constants - Network socket buffer configuration for audio streaming + // Used in: socket_buffer.go for optimizing network performance + // Impact: Controls network throughput, latency, and memory usage + + // SocketOptimalBuffer defines optimal socket buffer size (bytes). + // Used in: socket_buffer.go for default socket buffer configuration + // Impact: Balances throughput and memory usage for typical audio streams. + // Default 131072 (128KB) provides good performance for most scenarios. + SocketOptimalBuffer int + + // SocketMaxBuffer defines maximum socket buffer size (bytes). + // Used in: socket_buffer.go for high-throughput scenarios + // Impact: Larger buffers improve throughput but increase memory usage and latency. + // Default 262144 (256KB) handles high-bitrate audio without excessive memory. + SocketMaxBuffer int + + // SocketMinBuffer defines minimum socket buffer size (bytes). + // Used in: socket_buffer.go for low-memory scenarios + // Impact: Smaller buffers reduce memory usage but may limit throughput. + // Default 32768 (32KB) provides minimum viable buffer for audio streaming. + SocketMinBuffer int + + // Scheduling Policy Constants - Linux process scheduling policies for audio threads + // Used in: process_monitor.go for configuring thread scheduling behavior + // Impact: Controls how audio threads are scheduled by the Linux kernel + + // SchedNormal defines normal (CFS) scheduling policy. + // Used in: process_monitor.go for non-critical audio threads + // Impact: Standard time-sharing scheduling, may cause audio latency under load. + // Value 0 corresponds to SCHED_NORMAL in Linux kernel. + SchedNormal int + + // SchedFIFO defines First-In-First-Out real-time scheduling policy. + // Used in: process_monitor.go for critical audio threads requiring deterministic timing + // Impact: Provides real-time scheduling but may starve other processes if misused. + // Value 1 corresponds to SCHED_FIFO in Linux kernel. + SchedFIFO int + + // SchedRR defines Round-Robin real-time scheduling policy. + // Used in: process_monitor.go for real-time threads that should share CPU time + // Impact: Real-time scheduling with time slicing, balances determinism and fairness. + // Value 2 corresponds to SCHED_RR in Linux kernel. + SchedRR int + + // Real-time Priority Levels - Priority values for real-time audio thread scheduling + // Used in: process_monitor.go for setting thread priorities + // Impact: Higher priorities get more CPU time but may affect system responsiveness + + // RTAudioHighPriority defines highest priority for critical audio threads. + // Used in: process_monitor.go for time-critical audio processing (encoding/decoding) + // Impact: Ensures audio threads get CPU time but may impact system responsiveness. + // Default 80 provides high priority without completely starving other processes. + RTAudioHighPriority int + + // RTAudioMediumPriority defines medium priority for important audio threads. + // Used in: process_monitor.go for audio I/O and buffering operations + // Impact: Good priority for audio operations while maintaining system balance. + // Default 60 provides elevated priority for audio without extreme impact. + RTAudioMediumPriority int + + // RTAudioLowPriority defines low priority for background audio threads. + // Used in: process_monitor.go for audio monitoring and metrics collection + // Impact: Ensures audio background tasks run without impacting critical operations. + // Default 40 provides some priority elevation while remaining background. + RTAudioLowPriority int + + // RTNormalPriority defines normal priority (no real-time scheduling). + // Used in: process_monitor.go for non-critical audio threads + // Impact: Standard scheduling priority, no special real-time guarantees. + // Default 0 uses normal kernel scheduling without real-time privileges. + RTNormalPriority int + + // Process Management - Configuration for audio process lifecycle management + // Used in: supervisor.go for managing audio process restarts and recovery + // Impact: Controls system resilience and recovery from audio process failures + + // MaxRestartAttempts defines maximum number of restart attempts for failed processes. + // Used in: supervisor.go for limiting restart attempts to prevent infinite loops + // Impact: Higher values increase resilience but may mask persistent problems. + // Default 5 attempts allows recovery from transient issues while detecting persistent failures. MaxRestartAttempts int - RestartWindow time.Duration - RestartDelay time.Duration - MaxRestartDelay time.Duration - // Buffer Management - PreallocSize int - MaxPoolSize int - MessagePoolSize int + // RestartWindow defines time window for counting restart attempts. + // Used in: supervisor.go for restart attempt rate limiting + // Impact: Longer windows allow more restart attempts but slower failure detection. + // Default 5 minutes provides reasonable window for transient issue recovery. + RestartWindow time.Duration + + // RestartDelay defines initial delay before restarting failed processes. + // Used in: supervisor.go for implementing restart backoff strategy + // Impact: Longer delays reduce restart frequency but increase recovery time. + // Default 2 seconds allows brief recovery time without excessive delay. + RestartDelay time.Duration + + // MaxRestartDelay defines maximum delay between restart attempts. + // Used in: supervisor.go for capping exponential backoff delays + // Impact: Prevents excessively long delays while maintaining backoff benefits. + // Default 30 seconds caps restart delays at reasonable maximum. + MaxRestartDelay time.Duration + + // Buffer Management - Memory buffer configuration for audio processing + // Used across multiple components for memory allocation and performance optimization + // Impact: Controls memory usage, allocation efficiency, and processing performance + + // PreallocSize defines size of preallocated memory pools (bytes). + // Used in: buffer_pool.go for initial memory pool allocation + // Impact: Larger pools reduce allocation overhead but increase memory usage. + // Default 1MB (1024*1024) provides good balance for typical audio workloads. + PreallocSize int + + // MaxPoolSize defines maximum number of objects in memory pools. + // Used in: buffer_pool.go for limiting pool growth + // Impact: Larger pools reduce allocation frequency but increase memory usage. + // Default 100 objects provides good balance between performance and memory. + MaxPoolSize int + + // MessagePoolSize defines size of message object pools. + // Used in: Various IPC components for message allocation + // Impact: Larger pools reduce allocation overhead for message passing. + // Default 256 messages handles typical message throughput efficiently. + MessagePoolSize int + + // OptimalSocketBuffer defines optimal socket buffer size (bytes). + // Used in: socket_buffer.go for default socket configuration + // Impact: Balances network throughput and memory usage. + // Default 262144 (256KB) provides good performance for audio streaming. OptimalSocketBuffer int - MaxSocketBuffer int - MinSocketBuffer int - // IPC Configuration - MagicNumber uint32 - MaxFrameSize int - WriteTimeout time.Duration + // MaxSocketBuffer defines maximum socket buffer size (bytes). + // Used in: socket_buffer.go for high-throughput scenarios + // Impact: Larger buffers improve throughput but increase memory and latency. + // Default 1048576 (1MB) handles high-bitrate streams without excessive memory. + MaxSocketBuffer int + + // MinSocketBuffer defines minimum socket buffer size (bytes). + // Used in: socket_buffer.go for memory-constrained scenarios + // Impact: Smaller buffers reduce memory but may limit throughput. + // Default 8192 (8KB) provides minimum viable buffer for audio streaming. + MinSocketBuffer int + + // ChannelBufferSize defines buffer size for Go channels in audio processing. + // Used in: Various components for inter-goroutine communication + // Impact: Larger buffers reduce blocking but increase memory usage and latency. + // Default 500 messages provides good balance for audio processing pipelines. + ChannelBufferSize int + + // AudioFramePoolSize defines size of audio frame object pools. + // Used in: buffer_pool.go for audio frame allocation + // Impact: Larger pools reduce allocation overhead for frame processing. + // Default 1500 frames handles typical audio frame throughput efficiently. + AudioFramePoolSize int + + // PageSize defines memory page size for alignment and allocation (bytes). + // Used in: buffer_pool.go for memory-aligned allocations + // Impact: Must match system page size for optimal memory performance. + // Default 4096 bytes matches typical Linux page size. + PageSize int + + // InitialBufferFrames defines initial buffer size in audio frames. + // Used in: adaptive_buffer.go for initial buffer allocation + // Impact: Larger initial buffers reduce early reallocations but increase startup memory. + // Default 500 frames provides good starting point for most audio scenarios. + InitialBufferFrames int + + // BytesToMBDivisor defines divisor for converting bytes to megabytes. + // Used in: memory_metrics.go for memory usage reporting + // Impact: Must be 1024*1024 for accurate binary megabyte conversion. + // Default 1048576 (1024*1024) provides standard binary MB conversion. + BytesToMBDivisor int + + // MinReadEncodeBuffer defines minimum buffer size for CGO audio read/encode (bytes). + // Used in: cgo_audio.go for native audio processing buffer allocation + // Impact: Must accommodate minimum audio frame size to prevent buffer underruns. + // Default 1276 bytes handles minimum Opus frame with safety margin. + MinReadEncodeBuffer int + + // MaxDecodeWriteBuffer defines maximum buffer size for CGO audio decode/write (bytes). + // Used in: cgo_audio.go for native audio processing buffer allocation + // Impact: Must accommodate maximum audio frame size to prevent buffer overruns. + // Default 4096 bytes handles maximum audio frame size with safety margin. + MaxDecodeWriteBuffer int + + // IPC Configuration - Inter-Process Communication settings for audio components + // Used in: ipc.go for configuring audio process communication + // Impact: Controls IPC reliability, performance, and protocol compliance + + // MagicNumber defines magic number for IPC message validation. + // Used in: ipc.go for message header validation and protocol compliance + // Impact: Must match expected value to prevent protocol errors. + // Default 0xDEADBEEF provides distinctive pattern for message validation. + MagicNumber uint32 + + // MaxFrameSize defines maximum frame size for IPC messages (bytes). + // Used in: ipc.go for message size validation and buffer allocation + // Impact: Must accommodate largest expected audio frame to prevent truncation. + // Default 4096 bytes handles typical audio frames with safety margin. + MaxFrameSize int + + // WriteTimeout defines timeout for IPC write operations. + // Used in: ipc.go for preventing blocking on slow IPC operations + // Impact: Shorter timeouts improve responsiveness but may cause message drops. + // Default 5 seconds allows for system load while preventing indefinite blocking. + WriteTimeout time.Duration + + // MaxDroppedFrames defines maximum consecutive dropped frames before error. + // Used in: ipc.go for IPC quality monitoring + // Impact: Higher values tolerate more IPC issues but may mask problems. + // Default 10 frames allows brief interruptions while detecting serious issues. MaxDroppedFrames int - HeaderSize int - // Monitoring and Metrics + // HeaderSize defines size of IPC message headers (bytes). + // Used in: ipc.go for message parsing and buffer allocation + // Impact: Must match actual header size to prevent parsing errors. + // Default 8 bytes matches current IPC message header format. + HeaderSize int + + // Monitoring and Metrics - Configuration for audio performance monitoring + // Used in: metrics.go, latency_monitor.go for performance tracking + // Impact: Controls monitoring accuracy, overhead, and data retention + + // MetricsUpdateInterval defines frequency of metrics collection and reporting. + // Used in: metrics.go for periodic metrics updates + // Impact: Shorter intervals provide more accurate monitoring but increase overhead. + // Default 1000ms (1 second) provides good balance between accuracy and performance. MetricsUpdateInterval time.Duration - EMAAlpha float64 - WarmupSamples int - LogThrottleInterval time.Duration - MetricsChannelBuffer int - // Performance Tuning + // EMAAlpha defines smoothing factor for Exponential Moving Average calculations. + // Used in: metrics.go for smoothing performance metrics + // Impact: Higher values respond faster to changes but are more sensitive to noise. + // Default 0.1 provides good smoothing while maintaining responsiveness. + EMAAlpha float64 + + // WarmupSamples defines number of samples to collect before reporting metrics. + // Used in: metrics.go for avoiding inaccurate initial measurements + // Impact: More samples improve initial accuracy but delay metric availability. + // Default 10 samples provides good initial accuracy without excessive delay. + WarmupSamples int + + // LogThrottleInterval defines minimum interval between similar log messages. + // Used in: Various components for preventing log spam + // Impact: Longer intervals reduce log volume but may miss important events. + // Default 5 seconds prevents log flooding while maintaining visibility. + LogThrottleInterval time.Duration + + // MetricsChannelBuffer defines buffer size for metrics data channels. + // Used in: metrics.go for metrics data collection pipelines + // Impact: Larger buffers reduce blocking but increase memory usage and latency. + // Default 100 metrics provides good balance for metrics collection. + MetricsChannelBuffer int + + // LatencyHistorySize defines number of latency measurements to retain. + // Used in: latency_monitor.go for latency trend analysis + // Impact: More history improves trend analysis but increases memory usage. + // Default 100 measurements provides good history for analysis. + LatencyHistorySize int + + // Process Monitoring Constants - System resource monitoring configuration + // Used in: process_monitor.go for monitoring CPU, memory, and system resources + // Impact: Controls resource monitoring accuracy and system compatibility + + // MaxCPUPercent defines maximum valid CPU percentage value. + // Used in: process_monitor.go for CPU usage validation + // Impact: Values above this are considered invalid and filtered out. + // Default 100.0 represents 100% CPU usage as maximum valid value. + MaxCPUPercent float64 + + // MinCPUPercent defines minimum valid CPU percentage value. + // Used in: process_monitor.go for CPU usage validation + // Impact: Values below this are considered noise and filtered out. + // Default 0.01 (0.01%) filters out measurement noise while preserving low usage. + MinCPUPercent float64 + + // DefaultClockTicks defines default system clock ticks per second. + // Used in: process_monitor.go for CPU time calculations on embedded systems + // Impact: Must match system configuration for accurate CPU measurements. + // Default 250.0 matches typical embedded ARM system configuration. + DefaultClockTicks float64 + + // DefaultMemoryGB defines default system memory size in gigabytes. + // Used in: process_monitor.go for memory percentage calculations + // Impact: Should match actual system memory for accurate percentage calculations. + // Default 8 GB represents typical JetKVM system memory configuration. + DefaultMemoryGB int + + // MaxWarmupSamples defines maximum number of warmup samples for monitoring. + // Used in: process_monitor.go for initial measurement stabilization + // Impact: More samples improve initial accuracy but delay monitoring start. + // Default 3 samples provides quick stabilization without excessive delay. + MaxWarmupSamples int + + // WarmupCPUSamples defines number of CPU samples for warmup period. + // Used in: process_monitor.go for CPU measurement stabilization + // Impact: More samples improve CPU measurement accuracy during startup. + // Default 2 samples provides basic CPU measurement stabilization. + WarmupCPUSamples int + + // LogThrottleIntervalSec defines log throttle interval in seconds. + // Used in: process_monitor.go for controlling monitoring log frequency + // Impact: Longer intervals reduce log volume but may miss monitoring events. + // Default 10 seconds provides reasonable monitoring log frequency. + LogThrottleIntervalSec int + + // MinValidClockTicks defines minimum valid system clock ticks value. + // Used in: process_monitor.go for system clock validation + // Impact: Values below this indicate system configuration issues. + // Default 50 ticks represents minimum reasonable system clock configuration. + MinValidClockTicks int + + // MaxValidClockTicks defines maximum valid system clock ticks value. + // Used in: process_monitor.go for system clock validation + // Impact: Values above this indicate system configuration issues. + // Default 1000 ticks represents maximum reasonable system clock configuration. + MaxValidClockTicks int + + // Performance Tuning - Thresholds for adaptive audio quality and resource management + // Used in: adaptive_optimizer.go, quality_manager.go for performance optimization + // Impact: Controls when audio quality adjustments are triggered based on system load + + // CPUThresholdLow defines CPU usage threshold for low system load. + // Used in: adaptive_optimizer.go for triggering quality improvements + // Impact: Below this threshold, audio quality can be increased safely. + // Default 20% allows quality improvements when system has spare capacity. + CPUThresholdLow float64 + + // CPUThresholdMedium defines CPU usage threshold for medium system load. + // Used in: adaptive_optimizer.go for maintaining current quality + // Impact: Between low and medium thresholds, quality remains stable. + // Default 60% represents balanced system load where quality should be maintained. + CPUThresholdMedium float64 + + // CPUThresholdHigh defines CPU usage threshold for high system load. + // Used in: adaptive_optimizer.go for triggering quality reductions + // Impact: Above this threshold, audio quality is reduced to preserve performance. + // Default 75% prevents system overload by reducing audio processing demands. + CPUThresholdHigh float64 + + // MemoryThresholdLow defines memory usage threshold for low memory pressure. + // Used in: adaptive_optimizer.go for memory-based quality decisions + // Impact: Below this threshold, memory-intensive audio features can be enabled. + // Default 30% allows enhanced features when memory is abundant. + MemoryThresholdLow float64 + + // MemoryThresholdMed defines memory usage threshold for medium memory pressure. + // Used in: adaptive_optimizer.go for balanced memory management + // Impact: Between low and medium thresholds, memory usage is monitored closely. + // Default 60% represents moderate memory pressure requiring careful management. + MemoryThresholdMed float64 + + // MemoryThresholdHigh defines memory usage threshold for high memory pressure. + // Used in: adaptive_optimizer.go for aggressive memory conservation + // Impact: Above this threshold, memory usage is minimized by reducing quality. + // Default 80% triggers aggressive memory conservation to prevent system issues. + MemoryThresholdHigh float64 + + // LatencyThresholdLow defines acceptable latency for high-quality audio. + // Used in: adaptive_optimizer.go for latency-based quality decisions + // Impact: Below this threshold, audio quality can be maximized. + // Default 20ms represents excellent latency allowing maximum quality. + LatencyThresholdLow time.Duration + + // LatencyThresholdHigh defines maximum acceptable latency before quality reduction. + // Used in: adaptive_optimizer.go for preventing excessive audio delay + // Impact: Above this threshold, quality is reduced to improve latency. + // Default 50ms represents maximum acceptable latency for real-time audio. + LatencyThresholdHigh time.Duration + CPUFactor float64 MemoryFactor float64 LatencyFactor float64 @@ -63,65 +705,420 @@ type AudioConfigConstants struct { NormalPriority int NiceValue int - // Error Handling + // Error Handling - Configuration for error recovery and retry mechanisms + // Used in: error_handler.go, retry_manager.go for robust error handling + // Impact: Controls system resilience and recovery behavior + + // MaxRetries defines maximum number of retry attempts for failed operations. + // Used in: retry_manager.go for limiting retry attempts + // Impact: More retries improve success rate but may delay error reporting. + // Default 3 retries provides good balance between persistence and responsiveness. + MaxRetries int + + // RetryDelay defines initial delay between retry attempts. + // Used in: retry_manager.go for spacing retry attempts + // Impact: Longer delays reduce system load but slow recovery. + // Default 100ms provides quick retries while avoiding excessive load. + RetryDelay time.Duration + + // MaxRetryDelay defines maximum delay between retry attempts. + // Used in: retry_manager.go for capping exponential backoff + // Impact: Prevents excessively long delays while maintaining backoff benefits. + // Default 5 seconds caps retry delays at reasonable maximum. + MaxRetryDelay time.Duration + + // BackoffMultiplier defines multiplier for exponential backoff retry delays. + // Used in: retry_manager.go for calculating progressive retry delays + // Impact: Higher values increase delays more aggressively between retries. + // Default 2.0 doubles delay each retry, providing standard exponential backoff. + BackoffMultiplier float64 + + // ErrorChannelSize defines buffer size for error reporting channels. + // Used in: error_handler.go for error message queuing + // Impact: Larger buffers prevent error loss but increase memory usage. + // Default 50 errors provides adequate buffering for error bursts. + ErrorChannelSize int + MaxConsecutiveErrors int MaxRetryAttempts int + + // Timing Constants + DefaultSleepDuration time.Duration // 100ms + ShortSleepDuration time.Duration // 10ms + LongSleepDuration time.Duration // 200ms + DefaultTickerInterval time.Duration // 100ms + BufferUpdateInterval time.Duration // 500ms + StatsUpdateInterval time.Duration // 5s + SupervisorTimeout time.Duration // 10s + InputSupervisorTimeout time.Duration // 5s + ShortTimeout time.Duration // 5ms + MediumTimeout time.Duration // 50ms + BatchProcessingDelay time.Duration // 10ms + AdaptiveOptimizerStability time.Duration // 10s + MaxLatencyTarget time.Duration // 50ms + LatencyMonitorTarget time.Duration // 50ms + + // Adaptive Buffer Configuration + LowCPUThreshold float64 // 20% CPU threshold + HighCPUThreshold float64 // 60% CPU threshold + LowMemoryThreshold float64 // 50% memory threshold + HighMemoryThreshold float64 // 75% memory threshold + TargetLatency time.Duration // 20ms target latency + + // Adaptive Optimizer Configuration + CooldownPeriod time.Duration // 30s cooldown period + RollbackThreshold time.Duration // 300ms rollback threshold + LatencyTarget time.Duration // 50ms latency target + + // Latency Monitor Configuration + MaxLatencyThreshold time.Duration // 200ms max latency + JitterThreshold time.Duration // 20ms jitter threshold + + // Microphone Contention Configuration + MicContentionTimeout time.Duration // 200ms contention timeout + + // Priority Scheduler Configuration + MinNiceValue int // -20 minimum nice value + MaxNiceValue int // 19 maximum nice value + + // Buffer Pool Configuration + PreallocPercentage int // 20% preallocation percentage + InputPreallocPercentage int // 30% input preallocation percentage + + // Exponential Moving Average Configuration + HistoricalWeight float64 // 70% historical weight + CurrentWeight float64 // 30% current weight + + // Sleep and Backoff Configuration + CGOSleepMicroseconds int // 50000 microseconds (50ms) + BackoffStart time.Duration // 50ms initial backoff + + // Protocol Magic Numbers + InputMagicNumber uint32 // 0x4A4B4D49 "JKMI" (JetKVM Microphone Input) + OutputMagicNumber uint32 // 0x4A4B4F55 "JKOU" (JetKVM Output) + + // Calculation Constants + PercentageMultiplier float64 // 100.0 for percentage calculations + AveragingWeight float64 // 0.7 for weighted averaging calculations + ScalingFactor float64 // 1.5 for scaling calculations + SmoothingFactor float64 // 0.3 for adaptive buffer smoothing + CPUMemoryWeight float64 // 0.5 for CPU factor in combined calculations + MemoryWeight float64 // 0.3 for memory factor in combined calculations + LatencyWeight float64 // 0.2 for latency factor in combined calculations + PoolGrowthMultiplier int // 2x growth multiplier for pool sizes + LatencyScalingFactor float64 // 2.0 for latency ratio scaling + OptimizerAggressiveness float64 // 0.7 for optimizer aggressiveness } // DefaultAudioConfig returns the default configuration constants +// These values are carefully chosen based on JetKVM's embedded ARM environment, +// real-time audio requirements, and extensive testing for optimal performance. func DefaultAudioConfig() *AudioConfigConstants { return &AudioConfigConstants{ // Audio Quality Presets + // Rationale: 4096 bytes accommodates largest expected audio frames with safety margin + // for high-quality audio while preventing buffer overruns on embedded systems MaxAudioFrameSize: 4096, // Opus Encoding Parameters - OpusBitrate: 128000, - OpusComplexity: 10, - OpusVBR: 1, + // Rationale: 128kbps provides excellent quality for KVM audio while maintaining + // reasonable bandwidth usage over network connections + OpusBitrate: 128000, + // Rationale: Maximum complexity (10) ensures best quality encoding, acceptable + // on modern ARM processors with sufficient CPU headroom + OpusComplexity: 10, + // Rationale: VBR enabled (1) optimizes bitrate based on audio content complexity, + // reducing bandwidth for simple audio while maintaining quality for complex audio + OpusVBR: 1, + // Rationale: Unconstrained VBR (0) allows maximum bitrate flexibility for + // optimal quality-bandwidth balance in varying network conditions OpusVBRConstraint: 0, - OpusDTX: 0, + // Rationale: DTX disabled (0) ensures consistent audio stream for KVM applications + // where silence detection might interfere with system audio monitoring + OpusDTX: 0, // Audio Parameters - SampleRate: 48000, - Channels: 2, - FrameSize: 960, + // Rationale: 48kHz sample rate is professional audio standard, provides full + // frequency range (up to 24kHz) for accurate system audio reproduction + SampleRate: 48000, + // Rationale: Stereo (2 channels) captures full system audio including spatial + // information and stereo effects common in modern operating systems + Channels: 2, + // Rationale: 960 samples = 20ms frames at 48kHz, optimal balance between + // latency (low enough for real-time) and efficiency (reduces packet overhead) + FrameSize: 960, + // Rationale: 4000 bytes accommodates compressed Opus frames with overhead, + // prevents packet fragmentation while allowing for quality variations MaxPacketSize: 4000, + // Audio Quality Bitrates (kbps) + // Rationale: Low quality optimized for bandwidth-constrained connections, + // output higher than input as system audio typically more complex than microphone + AudioQualityLowOutputBitrate: 32, + AudioQualityLowInputBitrate: 16, + // Rationale: Medium quality balances bandwidth and quality for typical usage, + // suitable for most KVM scenarios with reasonable network connections + AudioQualityMediumOutputBitrate: 64, + AudioQualityMediumInputBitrate: 32, + // Rationale: High quality for excellent audio fidelity, matches default Opus + // bitrate for professional applications requiring clear audio reproduction + AudioQualityHighOutputBitrate: 128, + AudioQualityHighInputBitrate: 64, + // Rationale: Ultra quality for audiophile-grade reproduction, suitable for + // high-bandwidth connections where audio quality is paramount + AudioQualityUltraOutputBitrate: 192, + AudioQualityUltraInputBitrate: 96, + + // Audio Quality Sample Rates (Hz) + // Rationale: 22.05kHz captures frequencies up to 11kHz, sufficient for speech + // and basic audio while minimizing processing load on constrained connections + AudioQualityLowSampleRate: 22050, + // Rationale: 44.1kHz CD-quality standard, captures full audible range up to + // 22kHz, excellent balance of quality and processing requirements + AudioQualityMediumSampleRate: 44100, + // Rationale: 16kHz optimized for voice/microphone input, captures speech + // frequencies (300-8000Hz) efficiently while reducing bandwidth + AudioQualityMicLowSampleRate: 16000, + + // Audio Quality Frame Sizes + // Rationale: 40ms frames reduce processing overhead for low-quality mode, + // acceptable latency increase for bandwidth-constrained scenarios + AudioQualityLowFrameSize: 40 * time.Millisecond, + // Rationale: 20ms frames provide good balance of latency and efficiency, + // standard for real-time audio applications + AudioQualityMediumFrameSize: 20 * time.Millisecond, + AudioQualityHighFrameSize: 20 * time.Millisecond, + // Rationale: 10ms frames minimize latency for ultra-responsive audio, + // suitable for applications requiring immediate audio feedback + AudioQualityUltraFrameSize: 10 * time.Millisecond, + + // Audio Quality Channels + // Rationale: Mono (1 channel) reduces bandwidth by 50% for low-quality mode, + // acceptable for basic audio monitoring where stereo separation not critical + AudioQualityLowChannels: 1, + // Rationale: Stereo (2 channels) preserves spatial audio information for + // medium/high/ultra quality modes, essential for modern system audio + AudioQualityMediumChannels: 2, + AudioQualityHighChannels: 2, + AudioQualityUltraChannels: 2, + + // CGO Audio Constants + // Rationale: 96kbps provides good quality for CGO layer while being more + // conservative than main Opus bitrate, suitable for embedded processing + CGOOpusBitrate: 96000, + // Rationale: Lower complexity (3) reduces CPU load in CGO layer while + // maintaining acceptable quality for real-time processing + CGOOpusComplexity: 3, + // Rationale: VBR enabled (1) allows bitrate adaptation based on content + // complexity, optimizing bandwidth usage in CGO processing + CGOOpusVBR: 1, + // Rationale: Constrained VBR (1) limits bitrate variations for more + // predictable processing load in embedded environment + CGOOpusVBRConstraint: 1, + // Rationale: OPUS_SIGNAL_MUSIC (3) optimizes encoding for general audio + // content including system sounds, music, and mixed audio + CGOOpusSignalType: 3, // OPUS_SIGNAL_MUSIC + // Rationale: OPUS_BANDWIDTH_FULLBAND (1105) enables full 20kHz bandwidth + // for complete audio spectrum reproduction + CGOOpusBandwidth: 1105, // OPUS_BANDWIDTH_FULLBAND + // Rationale: DTX disabled (0) ensures consistent audio stream without + // silence detection that could interfere with system audio monitoring + CGOOpusDTX: 0, + // Rationale: 48kHz sample rate matches main audio parameters for + // consistency and professional audio quality + CGOSampleRate: 48000, + // Rationale: Stereo (2 channels) maintains spatial audio information + // throughout the CGO processing pipeline + CGOChannels: 2, + // Rationale: 960 samples (20ms at 48kHz) matches main frame size for + // consistent timing and efficient processing + CGOFrameSize: 960, + // Rationale: 1500 bytes accommodates Ethernet MTU constraints while + // providing sufficient space for compressed audio packets + CGOMaxPacketSize: 1500, + + // Input IPC Constants + // Rationale: 48kHz sample rate ensures high-quality microphone input + // capture matching system audio output for consistent quality + InputIPCSampleRate: 48000, + // Rationale: Stereo (2 channels) captures spatial microphone information + // and maintains compatibility with stereo input devices + InputIPCChannels: 2, + // Rationale: 960 samples (20ms) provides optimal balance between latency + // and processing efficiency for real-time microphone input + InputIPCFrameSize: 960, + + // Output IPC Constants + // Rationale: 4096 bytes accommodates largest audio frames with safety + // margin, preventing buffer overruns in IPC communication + OutputMaxFrameSize: 4096, + // Rationale: 10ms timeout provides quick response for real-time audio + // while preventing blocking in high-performance scenarios + OutputWriteTimeout: 10 * time.Millisecond, + // Rationale: Allow up to 50 dropped frames before error handling, + // providing resilience against temporary network/processing issues + OutputMaxDroppedFrames: 50, + // Rationale: 17-byte header provides sufficient space for frame metadata + // including timestamps, sequence numbers, and format information + OutputHeaderSize: 17, + // Rationale: 128 message pool size balances memory usage with throughput + // for efficient audio streaming without excessive buffering + OutputMessagePoolSize: 128, + + // Socket Buffer Constants + // Rationale: 128KB optimal buffer provides good balance between memory + // usage and network throughput for typical audio streaming scenarios + SocketOptimalBuffer: 131072, // 128KB + // Rationale: 256KB maximum buffer accommodates burst traffic and high + // bitrate audio while preventing excessive memory consumption + SocketMaxBuffer: 262144, // 256KB + // Rationale: 32KB minimum buffer ensures adequate buffering for basic + // audio streaming while minimizing memory footprint + SocketMinBuffer: 32768, // 32KB + + // Scheduling Policy Constants + // Rationale: SCHED_NORMAL (0) provides standard time-sharing scheduling + // suitable for non-critical audio processing tasks + SchedNormal: 0, + // Rationale: SCHED_FIFO (1) provides real-time first-in-first-out + // scheduling for critical audio processing requiring deterministic timing + SchedFIFO: 1, + // Rationale: SCHED_RR (2) provides real-time round-robin scheduling + // for balanced real-time processing with time slicing + SchedRR: 2, + + // Real-time Priority Levels + // Rationale: Priority 80 ensures audio processing gets highest CPU + // priority for latency-critical operations without starving system + RTAudioHighPriority: 80, + // Rationale: Priority 60 provides elevated priority for important + // audio tasks while allowing higher priority system operations + RTAudioMediumPriority: 60, + // Rationale: Priority 40 provides moderate real-time priority for + // audio tasks that need responsiveness but aren't latency-critical + RTAudioLowPriority: 40, + // Rationale: Priority 0 represents normal scheduling priority for + // non-real-time audio processing tasks + RTNormalPriority: 0, + // Process Management + // Rationale: 5 restart attempts provides resilience against transient + // failures while preventing infinite restart loops MaxRestartAttempts: 5, - RestartWindow: 5 * time.Minute, - RestartDelay: 2 * time.Second, - MaxRestartDelay: 30 * time.Second, + // Rationale: 5-minute restart window allows recovery from temporary + // issues while resetting attempt counter for long-term stability + RestartWindow: 5 * time.Minute, + // Rationale: 1-second initial restart delay prevents rapid restart + // cycles while allowing quick recovery from brief failures + RestartDelay: 1 * time.Second, + // Rationale: 30-second maximum delay prevents excessive wait times + // while implementing exponential backoff for persistent failures + MaxRestartDelay: 30 * time.Second, // Buffer Management - PreallocSize: 1024 * 1024, // 1MB - MaxPoolSize: 100, - MessagePoolSize: 100, - OptimalSocketBuffer: 262144, // 256KB - MaxSocketBuffer: 1048576, // 1MB - MinSocketBuffer: 8192, // 8KB + // Rationale: 1MB preallocation provides substantial buffer space for + // high-throughput audio processing while remaining reasonable for embedded systems + PreallocSize: 1024 * 1024, // 1MB + // Rationale: 100 pool size limits memory usage while providing adequate + // object pooling for efficient memory management + MaxPoolSize: 100, + // Rationale: 256 message pool size balances memory usage with message + // throughput for efficient IPC communication + MessagePoolSize: 256, + // Rationale: 256KB optimal socket buffer provides good network performance + // for audio streaming without excessive memory consumption + OptimalSocketBuffer: 262144, // 256KB + // Rationale: 1MB maximum socket buffer accommodates burst traffic and + // high-bitrate audio while preventing excessive memory usage + MaxSocketBuffer: 1048576, // 1MB + // Rationale: 8KB minimum socket buffer ensures basic network buffering + // while minimizing memory footprint for low-bandwidth scenarios + MinSocketBuffer: 8192, // 8KB + // Rationale: 500 channel buffer size provides adequate buffering for + // inter-goroutine communication without blocking + ChannelBufferSize: 500, // Channel buffer size for processing + // Rationale: 1500 audio frame pool size accommodates frame reuse for + // efficient memory management in high-throughput scenarios + AudioFramePoolSize: 1500, // Audio frame pool size + // Rationale: 4096-byte page size aligns with system memory pages for + // optimal memory allocation and cache performance + PageSize: 4096, // Memory page size + // Rationale: 500 initial buffer frames provides adequate startup buffering + // without excessive memory allocation during initialization + InitialBufferFrames: 500, // Initial buffer size in frames + // Rationale: 1024*1024 divisor provides standard MB conversion for + // memory usage calculations and reporting + BytesToMBDivisor: 1024 * 1024, // Divisor for converting bytes to MB + // Rationale: 1276 bytes minimum buffer accommodates smallest CGO audio + // read/encode operations while ensuring adequate processing space + MinReadEncodeBuffer: 1276, // Minimum buffer size for CGO audio read/encode + // Rationale: 4096 bytes maximum buffer provides sufficient space for + // largest CGO audio decode/write operations without excessive allocation + MaxDecodeWriteBuffer: 4096, // Maximum buffer size for CGO audio decode/write // IPC Configuration - MagicNumber: 0xDEADBEEF, - MaxFrameSize: 4096, - WriteTimeout: 5 * time.Second, + // Rationale: 0xDEADBEEF magic number provides distinctive header for + // IPC message validation and debugging purposes + MagicNumber: 0xDEADBEEF, + // Rationale: 4096 bytes maximum frame size accommodates largest audio + // frames while preventing excessive memory allocation + MaxFrameSize: 4096, + // Rationale: 5-second write timeout provides reasonable wait time for + // IPC operations while preventing indefinite blocking + WriteTimeout: 5 * time.Second, + // Rationale: Allow up to 10 dropped frames before error handling, + // balancing audio continuity with quality maintenance MaxDroppedFrames: 10, - HeaderSize: 8, + // Rationale: 8-byte header provides sufficient space for basic IPC + // metadata including message type and size information + HeaderSize: 8, // Monitoring and Metrics + // Rationale: 1-second metrics update interval provides timely monitoring + // without excessive overhead for performance tracking MetricsUpdateInterval: 1000 * time.Millisecond, - EMAAlpha: 0.1, - WarmupSamples: 10, - LogThrottleInterval: 5 * time.Second, - MetricsChannelBuffer: 100, + // Rationale: 0.1 EMA alpha provides smooth exponential moving average + // with 90% weight on historical data for stable metrics + EMAAlpha: 0.1, + // Rationale: 10 warmup samples allow metrics to stabilize before + // making optimization decisions based on performance data + WarmupSamples: 10, + // Rationale: 5-second log throttle interval prevents log spam while + // ensuring important events are captured for debugging + LogThrottleInterval: 5 * time.Second, + // Rationale: 100 metrics channel buffer provides adequate buffering + // for metrics collection without blocking performance monitoring + MetricsChannelBuffer: 100, + // Rationale: 100 latency measurements provide sufficient history for + // statistical analysis and trend detection + LatencyHistorySize: 100, // Number of latency measurements to keep + + // Process Monitoring Constants + MaxCPUPercent: 100.0, // Maximum CPU percentage + MinCPUPercent: 0.01, // Minimum CPU percentage + DefaultClockTicks: 250.0, // Default clock ticks for embedded ARM systems + DefaultMemoryGB: 8, // Default memory in GB + MaxWarmupSamples: 3, // Maximum warmup samples + WarmupCPUSamples: 2, // CPU warmup samples + LogThrottleIntervalSec: 10, // Log throttle interval in seconds + MinValidClockTicks: 50, // Minimum valid clock ticks + MaxValidClockTicks: 1000, // Maximum valid clock ticks // Performance Tuning - CPUFactor: 0.7, - MemoryFactor: 0.8, - LatencyFactor: 0.9, - InputSizeThreshold: 1024, - OutputSizeThreshold: 2048, - TargetLevel: 0.5, + CPUThresholdLow: 0.20, + CPUThresholdMedium: 0.60, + CPUThresholdHigh: 0.75, + MemoryThresholdLow: 0.30, + MemoryThresholdMed: 0.60, + MemoryThresholdHigh: 0.80, + LatencyThresholdLow: 20 * time.Millisecond, + LatencyThresholdHigh: 50 * time.Millisecond, + CPUFactor: 0.7, + MemoryFactor: 0.8, + LatencyFactor: 0.9, + InputSizeThreshold: 1024, + OutputSizeThreshold: 2048, + TargetLevel: 0.5, // Priority Scheduling AudioHighPriority: -10, @@ -131,8 +1128,98 @@ func DefaultAudioConfig() *AudioConfigConstants { NiceValue: -10, // Error Handling + MaxRetries: 3, + RetryDelay: 100 * time.Millisecond, + MaxRetryDelay: 5 * time.Second, + BackoffMultiplier: 2.0, + ErrorChannelSize: 50, MaxConsecutiveErrors: 5, MaxRetryAttempts: 3, + + // Timing Constants + DefaultSleepDuration: 100 * time.Millisecond, + ShortSleepDuration: 10 * time.Millisecond, + LongSleepDuration: 200 * time.Millisecond, + DefaultTickerInterval: 100 * time.Millisecond, + BufferUpdateInterval: 500 * time.Millisecond, + StatsUpdateInterval: 5 * time.Second, + SupervisorTimeout: 10 * time.Second, + InputSupervisorTimeout: 5 * time.Second, + ShortTimeout: 5 * time.Millisecond, + MediumTimeout: 50 * time.Millisecond, + BatchProcessingDelay: 10 * time.Millisecond, + AdaptiveOptimizerStability: 10 * time.Second, + MaxLatencyTarget: 50 * time.Millisecond, + LatencyMonitorTarget: 50 * time.Millisecond, + + // Adaptive Buffer Configuration + LowCPUThreshold: 0.20, + HighCPUThreshold: 0.60, + LowMemoryThreshold: 0.50, + HighMemoryThreshold: 0.75, + TargetLatency: 20 * time.Millisecond, + + // Adaptive Optimizer Configuration + CooldownPeriod: 30 * time.Second, + RollbackThreshold: 300 * time.Millisecond, + LatencyTarget: 50 * time.Millisecond, + + // Latency Monitor Configuration + MaxLatencyThreshold: 200 * time.Millisecond, + JitterThreshold: 20 * time.Millisecond, + + // Microphone Contention Configuration + MicContentionTimeout: 200 * time.Millisecond, + + // Priority Scheduler Configuration + MinNiceValue: -20, + MaxNiceValue: 19, + + // Buffer Pool Configuration + PreallocPercentage: 20, + InputPreallocPercentage: 30, + + // Exponential Moving Average Configuration + HistoricalWeight: 0.70, + CurrentWeight: 0.30, + + // Sleep and Backoff Configuration + CGOSleepMicroseconds: 50000, + BackoffStart: 50 * time.Millisecond, + + // Protocol Magic Numbers + InputMagicNumber: 0x4A4B4D49, // "JKMI" (JetKVM Microphone Input) + OutputMagicNumber: 0x4A4B4F55, // "JKOU" (JetKVM Output) + + // Calculation Constants - Mathematical constants used throughout audio processing + // Used in: Various components for calculations and conversions + // Impact: Controls calculation accuracy and algorithm behavior + + // PercentageMultiplier defines multiplier for percentage calculations. + // Used in: Throughout codebase for converting ratios to percentages + // Impact: Must be 100 for standard percentage calculations. + // Default 100 provides standard percentage conversion (0.5 * 100 = 50%). + PercentageMultiplier: 100.0, // For percentage calculations + + // AveragingWeight defines weight for weighted averaging calculations. + // Used in: metrics.go, adaptive_optimizer.go for smoothing values + // Impact: Higher values give more weight to recent measurements. + // Default 0.7 (70%) emphasizes recent values while maintaining stability. + AveragingWeight: 0.7, // For weighted averaging calculations + + // ScalingFactor defines general scaling factor for various calculations. + // Used in: adaptive_optimizer.go, quality_manager.go for scaling adjustments + // Impact: Controls magnitude of adaptive adjustments and scaling operations. + // Default 1.5 provides moderate scaling for quality and performance adjustments. + ScalingFactor: 1.5, // For scaling calculations + + SmoothingFactor: 0.3, // For adaptive buffer smoothing + CPUMemoryWeight: 0.5, // CPU factor weight in combined calculations + MemoryWeight: 0.3, // Memory factor weight in combined calculations + LatencyWeight: 0.2, // Latency factor weight in combined calculations + PoolGrowthMultiplier: 2, // Pool growth multiplier + LatencyScalingFactor: 2.0, // Latency ratio scaling factor + OptimizerAggressiveness: 0.7, // Optimizer aggressiveness factor } } diff --git a/internal/audio/input_ipc.go b/internal/audio/input_ipc.go index e59bdc8..931700f 100644 --- a/internal/audio/input_ipc.go +++ b/internal/audio/input_ipc.go @@ -16,14 +16,19 @@ import ( "github.com/jetkvm/kvm/internal/logging" ) -const ( - inputMagicNumber uint32 = 0x4A4B4D49 // "JKMI" (JetKVM Microphone Input) +var ( + inputMagicNumber uint32 = GetConfig().InputMagicNumber // "JKMI" (JetKVM Microphone Input) inputSocketName = "audio_input.sock" - maxFrameSize = 4096 // Maximum Opus frame size writeTimeout = 15 * time.Millisecond // Non-blocking write timeout (increased for high load) - maxDroppedFrames = 100 // Maximum consecutive dropped frames before reconnect - headerSize = 17 // Fixed header size: 4+1+4+8 bytes - messagePoolSize = 256 // Pre-allocated message pool size +) + +const ( + headerSize = 17 // Fixed header size: 4+1+4+8 bytes +) + +var ( + maxFrameSize = GetConfig().MaxFrameSize // Maximum Opus frame size + messagePoolSize = GetConfig().MessagePoolSize // Pre-allocated message pool size ) // InputMessageType represents the type of IPC message @@ -79,9 +84,9 @@ var messagePoolInitOnce sync.Once func initializeMessagePool() { messagePoolInitOnce.Do(func() { // Pre-allocate 30% of pool size for immediate availability - preallocSize := messagePoolSize * 30 / 100 + preallocSize := messagePoolSize * GetConfig().InputPreallocPercentage / 100 globalMessagePool.preallocSize = preallocSize - globalMessagePool.maxPoolSize = messagePoolSize * 2 // Allow growth up to 2x + globalMessagePool.maxPoolSize = messagePoolSize * GetConfig().PoolGrowthMultiplier // Allow growth up to 2x globalMessagePool.preallocated = make([]*OptimizedIPCMessage, 0, preallocSize) // Pre-allocate messages to reduce initial allocation overhead @@ -315,7 +320,7 @@ func (ais *AudioInputServer) handleConnection(conn net.Conn) { if ais.conn == nil { return } - time.Sleep(100 * time.Millisecond) + time.Sleep(GetConfig().DefaultSleepDuration) } } } @@ -345,7 +350,7 @@ func (ais *AudioInputServer) readMessage(conn net.Conn) (*InputIPCMessage, error } // Validate message length - if msg.Length > maxFrameSize { + if msg.Length > uint32(maxFrameSize) { return nil, fmt.Errorf("message too large: %d bytes", msg.Length) } @@ -711,7 +716,7 @@ func (aic *AudioInputClient) GetDropRate() float64 { if total == 0 { return 0.0 } - return float64(dropped) / float64(total) * 100.0 + return float64(dropped) / float64(total) * GetConfig().PercentageMultiplier } // ResetStats resets frame statistics @@ -820,11 +825,11 @@ func (ais *AudioInputServer) startMonitorGoroutine() { }() defer ais.wg.Done() - ticker := time.NewTicker(100 * time.Millisecond) + ticker := time.NewTicker(GetConfig().DefaultTickerInterval) defer ticker.Stop() // Buffer size update ticker (less frequent) - bufferUpdateTicker := time.NewTicker(500 * time.Millisecond) + bufferUpdateTicker := time.NewTicker(GetConfig().BufferUpdateInterval) defer bufferUpdateTicker.Stop() for { @@ -917,7 +922,7 @@ func (mp *MessagePool) GetMessagePoolStats() MessagePoolStats { var hitRate float64 if totalRequests > 0 { - hitRate = float64(hitCount) / float64(totalRequests) * 100 + hitRate = float64(hitCount) / float64(totalRequests) * GetConfig().PercentageMultiplier } // Calculate channel pool size diff --git a/internal/audio/input_ipc_manager.go b/internal/audio/input_ipc_manager.go index 2986d4b..9092d17 100644 --- a/internal/audio/input_ipc_manager.go +++ b/internal/audio/input_ipc_manager.go @@ -41,13 +41,13 @@ func (aim *AudioInputIPCManager) Start() error { } config := InputIPCConfig{ - SampleRate: 48000, - Channels: 2, - FrameSize: 960, + SampleRate: GetConfig().InputIPCSampleRate, + Channels: GetConfig().InputIPCChannels, + FrameSize: GetConfig().InputIPCFrameSize, } // Wait for subprocess readiness - time.Sleep(200 * time.Millisecond) + time.Sleep(GetConfig().LongSleepDuration) err = aim.supervisor.SendConfig(config) if err != nil { diff --git a/internal/audio/input_server_main.go b/internal/audio/input_server_main.go index 9fe2b38..39fb3ec 100644 --- a/internal/audio/input_server_main.go +++ b/internal/audio/input_server_main.go @@ -64,7 +64,7 @@ func RunAudioInputServer() error { server.Stop() // Give some time for cleanup - time.Sleep(100 * time.Millisecond) + time.Sleep(GetConfig().DefaultSleepDuration) logger.Info().Msg("Audio input server subprocess stopped") return nil diff --git a/internal/audio/input_supervisor.go b/internal/audio/input_supervisor.go index d7ca2d3..5cd7788 100644 --- a/internal/audio/input_supervisor.go +++ b/internal/audio/input_supervisor.go @@ -128,7 +128,7 @@ func (ais *AudioInputSupervisor) Stop() { select { case <-done: ais.logger.Info().Msg("Audio input server subprocess stopped gracefully") - case <-time.After(5 * time.Second): + case <-time.After(GetConfig().InputSupervisorTimeout): // Force kill if graceful shutdown failed ais.logger.Warn().Msg("Audio input server subprocess did not stop gracefully, force killing") err := ais.cmd.Process.Kill() @@ -220,7 +220,7 @@ func (ais *AudioInputSupervisor) monitorSubprocess() { // connectClient attempts to connect the client to the server func (ais *AudioInputSupervisor) connectClient() { // Wait briefly for the server to start (reduced from 500ms) - time.Sleep(100 * time.Millisecond) + time.Sleep(GetConfig().DefaultSleepDuration) err := ais.client.Connect() if err != nil { diff --git a/internal/audio/ipc.go b/internal/audio/ipc.go index 33f96ae..eaa8484 100644 --- a/internal/audio/ipc.go +++ b/internal/audio/ipc.go @@ -16,16 +16,14 @@ import ( "github.com/rs/zerolog" ) -const ( - outputMagicNumber uint32 = 0x4A4B4F55 // "JKOU" (JetKVM Output) - outputSocketName = "audio_output.sock" - outputMaxFrameSize = 4096 // Maximum Opus frame size - outputWriteTimeout = 10 * time.Millisecond // Non-blocking write timeout (increased for high load) - outputMaxDroppedFrames = 50 // Maximum consecutive dropped frames - outputHeaderSize = 17 // Fixed header size: 4+1+4+8 bytes - outputMessagePoolSize = 128 // Pre-allocated message pool size +var ( + outputMagicNumber uint32 = GetConfig().OutputMagicNumber // "JKOU" (JetKVM Output) + outputSocketName = "audio_output.sock" ) +// Output IPC constants are now centralized in config_constants.go +// outputMaxFrameSize, outputWriteTimeout, outputMaxDroppedFrames, outputHeaderSize, outputMessagePoolSize + // OutputMessageType represents the type of IPC message type OutputMessageType uint8 @@ -48,8 +46,8 @@ type OutputIPCMessage struct { // OutputOptimizedMessage represents a pre-allocated message for zero-allocation operations type OutputOptimizedMessage struct { - header [outputHeaderSize]byte // Pre-allocated header buffer - data []byte // Reusable data buffer + header [17]byte // Pre-allocated header buffer (using constant value since array size must be compile-time constant) + data []byte // Reusable data buffer } // OutputMessagePool manages pre-allocated messages for zero-allocation IPC @@ -66,7 +64,7 @@ func NewOutputMessagePool(size int) *OutputMessagePool { // Pre-allocate messages for i := 0; i < size; i++ { msg := &OutputOptimizedMessage{ - data: make([]byte, outputMaxFrameSize), + data: make([]byte, GetConfig().OutputMaxFrameSize), } pool.pool <- msg } @@ -82,7 +80,7 @@ func (p *OutputMessagePool) Get() *OutputOptimizedMessage { default: // Pool exhausted, create new message return &OutputOptimizedMessage{ - data: make([]byte, outputMaxFrameSize), + data: make([]byte, GetConfig().OutputMaxFrameSize), } } } @@ -98,7 +96,7 @@ func (p *OutputMessagePool) Put(msg *OutputOptimizedMessage) { } // Global message pool for output IPC -var globalOutputMessagePool = NewOutputMessagePool(outputMessagePoolSize) +var globalOutputMessagePool = NewOutputMessagePool(GetConfig().OutputMessagePoolSize) type AudioServer struct { // Atomic fields must be first for proper alignment on ARM @@ -135,7 +133,7 @@ func NewAudioServer() (*AudioServer, error) { } // Initialize with adaptive buffer size (start with 500 frames) - initialBufferSize := int64(500) + initialBufferSize := int64(GetConfig().InitialBufferFrames) // Initialize latency monitoring latencyConfig := DefaultLatencyConfig() @@ -284,8 +282,8 @@ func (s *AudioServer) Close() error { } func (s *AudioServer) SendFrame(frame []byte) error { - if len(frame) > outputMaxFrameSize { - return fmt.Errorf("frame size %d exceeds maximum %d", len(frame), outputMaxFrameSize) + if len(frame) > GetConfig().OutputMaxFrameSize { + return fmt.Errorf("frame size %d exceeds maximum %d", len(frame), GetConfig().OutputMaxFrameSize) } start := time.Now() @@ -340,7 +338,7 @@ func (s *AudioServer) sendFrameToClient(frame []byte) error { binary.LittleEndian.PutUint64(optMsg.header[9:17], uint64(start.UnixNano())) // Use non-blocking write with timeout - ctx, cancel := context.WithTimeout(context.Background(), outputWriteTimeout) + ctx, cancel := context.WithTimeout(context.Background(), GetConfig().OutputWriteTimeout) defer cancel() // Create a channel to signal write completion @@ -492,8 +490,8 @@ func (c *AudioClient) ReceiveFrame() ([]byte, error) { } size := binary.LittleEndian.Uint32(optMsg.header[5:9]) - if size > outputMaxFrameSize { - return nil, fmt.Errorf("frame size %d exceeds maximum %d", size, outputMaxFrameSize) + if int(size) > GetConfig().OutputMaxFrameSize { + return nil, fmt.Errorf("frame size %d exceeds maximum %d", size, GetConfig().OutputMaxFrameSize) } // Read frame data diff --git a/internal/audio/latency_monitor.go b/internal/audio/latency_monitor.go index 963ee28..d46ced9 100644 --- a/internal/audio/latency_monitor.go +++ b/internal/audio/latency_monitor.go @@ -83,10 +83,10 @@ const ( func DefaultLatencyConfig() LatencyConfig { return LatencyConfig{ TargetLatency: 50 * time.Millisecond, - MaxLatency: 200 * time.Millisecond, + MaxLatency: GetConfig().MaxLatencyThreshold, OptimizationInterval: 5 * time.Second, - HistorySize: 100, - JitterThreshold: 20 * time.Millisecond, + HistorySize: GetConfig().LatencyHistorySize, + JitterThreshold: GetConfig().JitterThreshold, AdaptiveThreshold: 0.8, // Trigger optimization when 80% above target } } diff --git a/internal/audio/memory_metrics.go b/internal/audio/memory_metrics.go index a5129b1..bb9293b 100644 --- a/internal/audio/memory_metrics.go +++ b/internal/audio/memory_metrics.go @@ -171,8 +171,8 @@ func LogMemoryMetrics() { metrics := CollectMemoryMetrics() logger.Info(). - Uint64("heap_alloc_mb", metrics.RuntimeStats.HeapAlloc/1024/1024). - Uint64("heap_sys_mb", metrics.RuntimeStats.HeapSys/1024/1024). + Uint64("heap_alloc_mb", metrics.RuntimeStats.HeapAlloc/uint64(GetConfig().BytesToMBDivisor)). + Uint64("heap_sys_mb", metrics.RuntimeStats.HeapSys/uint64(GetConfig().BytesToMBDivisor)). Uint64("heap_objects", metrics.RuntimeStats.HeapObjects). Uint32("num_gc", metrics.RuntimeStats.NumGC). Float64("gc_cpu_fraction", metrics.RuntimeStats.GCCPUFraction). diff --git a/internal/audio/metrics.go b/internal/audio/metrics.go index 9c2b442..ffddd3b 100644 --- a/internal/audio/metrics.go +++ b/internal/audio/metrics.go @@ -451,7 +451,7 @@ func GetLastMetricsUpdate() time.Time { // StartMetricsUpdater starts a goroutine that periodically updates Prometheus metrics func StartMetricsUpdater() { go func() { - ticker := time.NewTicker(5 * time.Second) // Update every 5 seconds + ticker := time.NewTicker(GetConfig().StatsUpdateInterval) // Update every 5 seconds defer ticker.Stop() for range ticker.C { diff --git a/internal/audio/mic_contention.go b/internal/audio/mic_contention.go index 8b06630..373d656 100644 --- a/internal/audio/mic_contention.go +++ b/internal/audio/mic_contention.go @@ -105,7 +105,7 @@ func GetMicrophoneContentionManager() *MicrophoneContentionManager { } if atomic.CompareAndSwapInt32(&micContentionInitialized, 0, 1) { - manager := NewMicrophoneContentionManager(200 * time.Millisecond) + manager := NewMicrophoneContentionManager(GetConfig().MicContentionTimeout) atomic.StorePointer(&globalMicContentionManager, unsafe.Pointer(manager)) return manager } @@ -115,7 +115,7 @@ func GetMicrophoneContentionManager() *MicrophoneContentionManager { return (*MicrophoneContentionManager)(ptr) } - return NewMicrophoneContentionManager(200 * time.Millisecond) + return NewMicrophoneContentionManager(GetConfig().MicContentionTimeout) } func TryMicrophoneOperation() OperationResult { diff --git a/internal/audio/output_server_main.go b/internal/audio/output_server_main.go index 7f2e17b..489cb94 100644 --- a/internal/audio/output_server_main.go +++ b/internal/audio/output_server_main.go @@ -64,7 +64,7 @@ func RunAudioOutputServer() error { StopNonBlockingAudioStreaming() // Give some time for cleanup - time.Sleep(100 * time.Millisecond) + time.Sleep(GetConfig().DefaultSleepDuration) logger.Info().Msg("Audio output server subprocess stopped") return nil diff --git a/internal/audio/output_streaming.go b/internal/audio/output_streaming.go index 4dfb646..265e535 100644 --- a/internal/audio/output_streaming.go +++ b/internal/audio/output_streaming.go @@ -61,9 +61,9 @@ func NewOutputStreamer() (*OutputStreamer, error) { bufferPool: NewAudioBufferPool(GetMaxAudioFrameSize()), // Use existing buffer pool ctx: ctx, cancel: cancel, - batchSize: initialBatchSize, // Use adaptive batch size - processingChan: make(chan []byte, 500), // Large buffer for smooth processing - statsInterval: 5 * time.Second, // Statistics every 5 seconds + batchSize: initialBatchSize, // Use adaptive batch size + processingChan: make(chan []byte, GetConfig().ChannelBufferSize), // Large buffer for smooth processing + statsInterval: 5 * time.Second, // Statistics every 5 seconds lastStatsTime: time.Now().UnixNano(), }, nil } @@ -127,7 +127,7 @@ func (s *OutputStreamer) streamLoop() { defer ticker.Stop() // Batch size update ticker - batchUpdateTicker := time.NewTicker(500 * time.Millisecond) + batchUpdateTicker := time.NewTicker(GetConfig().BufferUpdateInterval) defer batchUpdateTicker.Stop() for { @@ -233,7 +233,7 @@ func (s *OutputStreamer) reportStatistics() { processingTime := atomic.LoadInt64(&s.processingTime) if processed > 0 { - dropRate := float64(dropped) / float64(processed+dropped) * 100 + dropRate := float64(dropped) / float64(processed+dropped) * GetConfig().PercentageMultiplier avgProcessingTime := time.Duration(processingTime) getOutputStreamingLogger().Info().Int64("processed", processed).Int64("dropped", dropped).Float64("drop_rate", dropRate).Dur("avg_processing", avgProcessingTime).Msg("Output Audio Stats") @@ -270,7 +270,7 @@ func (s *OutputStreamer) GetDetailedStats() map[string]interface{} { } if processed+dropped > 0 { - stats["drop_rate_percent"] = float64(dropped) / float64(processed+dropped) * 100 + stats["drop_rate_percent"] = float64(dropped) / float64(processed+dropped) * GetConfig().PercentageMultiplier } // Add client statistics @@ -343,7 +343,7 @@ func StartAudioOutputStreaming(send func([]byte)) error { RecordFrameReceived(n) } // Small delay to prevent busy waiting - time.Sleep(10 * time.Millisecond) + time.Sleep(GetConfig().ShortSleepDuration) } } }() @@ -364,6 +364,6 @@ func StopAudioOutputStreaming() { // Wait for streaming to stop for atomic.LoadInt32(&outputStreamingRunning) == 1 { - time.Sleep(10 * time.Millisecond) + time.Sleep(GetConfig().ShortSleepDuration) } } diff --git a/internal/audio/priority_scheduler.go b/internal/audio/priority_scheduler.go index ffd8595..b9b57d8 100644 --- a/internal/audio/priority_scheduler.go +++ b/internal/audio/priority_scheduler.go @@ -16,23 +16,17 @@ type SchedParam struct { Priority int32 } -// Priority levels for audio processing -const ( - // SCHED_FIFO priorities (1-99, higher = more priority) - AudioHighPriority = 80 // High priority for critical audio processing - AudioMediumPriority = 60 // Medium priority for regular audio processing - AudioLowPriority = 40 // Low priority for background audio tasks +// getPriorityConstants returns priority levels from centralized config +func getPriorityConstants() (audioHigh, audioMedium, audioLow, normal int) { + config := GetConfig() + return config.AudioHighPriority, config.AudioMediumPriority, config.AudioLowPriority, config.NormalPriority +} - // SCHED_NORMAL is the default (priority 0) - NormalPriority = 0 -) - -// Scheduling policies -const ( - SCHED_NORMAL = 0 - SCHED_FIFO = 1 - SCHED_RR = 2 -) +// getSchedulingPolicies returns scheduling policies from centralized config +func getSchedulingPolicies() (schedNormal, schedFIFO, schedRR int) { + config := GetConfig() + return config.SchedNormal, config.SchedFIFO, config.SchedRR +} // PriorityScheduler manages thread priorities for audio processing type PriorityScheduler struct { @@ -73,7 +67,8 @@ func (ps *PriorityScheduler) SetThreadPriority(priority int, policy int) error { if errno != 0 { // If we can't set real-time priority, try nice value instead - if policy != SCHED_NORMAL { + schedNormal, _, _ := getSchedulingPolicies() + if policy != schedNormal { ps.logger.Warn().Int("errno", int(errno)).Msg("Failed to set real-time priority, falling back to nice") return ps.setNicePriority(priority) } @@ -89,11 +84,11 @@ func (ps *PriorityScheduler) setNicePriority(rtPriority int) error { // Convert real-time priority to nice value (inverse relationship) // RT priority 80 -> nice -10, RT priority 40 -> nice 0 niceValue := (40 - rtPriority) / 4 - if niceValue < -20 { - niceValue = -20 + if niceValue < GetConfig().MinNiceValue { + niceValue = GetConfig().MinNiceValue } - if niceValue > 19 { - niceValue = 19 + if niceValue > GetConfig().MaxNiceValue { + niceValue = GetConfig().MaxNiceValue } err := syscall.Setpriority(syscall.PRIO_PROCESS, 0, niceValue) @@ -108,22 +103,30 @@ func (ps *PriorityScheduler) setNicePriority(rtPriority int) error { // SetAudioProcessingPriority sets high priority for audio processing threads func (ps *PriorityScheduler) SetAudioProcessingPriority() error { - return ps.SetThreadPriority(AudioHighPriority, SCHED_FIFO) + audioHigh, _, _, _ := getPriorityConstants() + _, schedFIFO, _ := getSchedulingPolicies() + return ps.SetThreadPriority(audioHigh, schedFIFO) } // SetAudioIOPriority sets medium priority for audio I/O threads func (ps *PriorityScheduler) SetAudioIOPriority() error { - return ps.SetThreadPriority(AudioMediumPriority, SCHED_FIFO) + _, audioMedium, _, _ := getPriorityConstants() + _, schedFIFO, _ := getSchedulingPolicies() + return ps.SetThreadPriority(audioMedium, schedFIFO) } // SetAudioBackgroundPriority sets low priority for background audio tasks func (ps *PriorityScheduler) SetAudioBackgroundPriority() error { - return ps.SetThreadPriority(AudioLowPriority, SCHED_FIFO) + _, _, audioLow, _ := getPriorityConstants() + _, schedFIFO, _ := getSchedulingPolicies() + return ps.SetThreadPriority(audioLow, schedFIFO) } // ResetPriority resets thread to normal scheduling func (ps *PriorityScheduler) ResetPriority() error { - return ps.SetThreadPriority(NormalPriority, SCHED_NORMAL) + _, _, _, normal := getPriorityConstants() + schedNormal, _, _ := getSchedulingPolicies() + return ps.SetThreadPriority(normal, schedNormal) } // Disable disables priority scheduling (useful for testing or fallback) diff --git a/internal/audio/process_monitor.go b/internal/audio/process_monitor.go index d5581c4..d131e83 100644 --- a/internal/audio/process_monitor.go +++ b/internal/audio/process_monitor.go @@ -13,26 +13,29 @@ import ( "github.com/rs/zerolog" ) -// Constants for process monitoring -const ( +// Variables for process monitoring (using configuration) +var ( // System constants - pageSize = 4096 - maxCPUPercent = 100.0 - minCPUPercent = 0.01 - defaultClockTicks = 250.0 // Common for embedded ARM systems - defaultMemoryGB = 8 + maxCPUPercent = GetConfig().MaxCPUPercent + minCPUPercent = GetConfig().MinCPUPercent + defaultClockTicks = GetConfig().DefaultClockTicks + defaultMemoryGB = GetConfig().DefaultMemoryGB // Monitoring thresholds - maxWarmupSamples = 3 - warmupCPUSamples = 2 - logThrottleInterval = 10 + maxWarmupSamples = GetConfig().MaxWarmupSamples + warmupCPUSamples = GetConfig().WarmupCPUSamples // Channel buffer size - metricsChannelBuffer = 100 + metricsChannelBuffer = GetConfig().MetricsChannelBuffer // Clock tick detection ranges - minValidClockTicks = 50 - maxValidClockTicks = 1000 + minValidClockTicks = float64(GetConfig().MinValidClockTicks) + maxValidClockTicks = float64(GetConfig().MaxValidClockTicks) +) + +// Variables for process monitoring +var ( + pageSize = GetConfig().PageSize ) // ProcessMetrics represents CPU and memory usage metrics for a process @@ -217,7 +220,7 @@ func (pm *ProcessMonitor) collectMetrics(pid int, state *processState) (ProcessM vsize, _ := strconv.ParseInt(fields[22], 10, 64) rss, _ := strconv.ParseInt(fields[23], 10, 64) - metric.MemoryRSS = rss * pageSize + metric.MemoryRSS = rss * int64(pageSize) metric.MemoryVMS = vsize // Calculate CPU percentage @@ -230,7 +233,7 @@ func (pm *ProcessMonitor) collectMetrics(pid int, state *processState) (ProcessM // Calculate memory percentage (RSS / total system memory) if totalMem := pm.getTotalMemory(); totalMem > 0 { - metric.MemoryPercent = float64(metric.MemoryRSS) / float64(totalMem) * 100.0 + metric.MemoryPercent = float64(metric.MemoryRSS) / float64(totalMem) * GetConfig().PercentageMultiplier } // Update state for next calculation @@ -261,7 +264,7 @@ func (pm *ProcessMonitor) calculateCPUPercent(totalCPUTime int64, state *process // Convert from clock ticks to seconds using actual system clock ticks clockTicks := pm.getClockTicks() cpuSeconds := cpuDelta / clockTicks - cpuPercent := (cpuSeconds / timeDelta) * 100.0 + cpuPercent := (cpuSeconds / timeDelta) * GetConfig().PercentageMultiplier // Apply bounds if cpuPercent > maxCPUPercent { @@ -341,7 +344,7 @@ func (pm *ProcessMonitor) getTotalMemory() int64 { pm.memoryOnce.Do(func() { file, err := os.Open("/proc/meminfo") if err != nil { - pm.totalMemory = defaultMemoryGB * 1024 * 1024 * 1024 + pm.totalMemory = int64(defaultMemoryGB) * 1024 * 1024 * 1024 return } defer file.Close() @@ -360,7 +363,7 @@ func (pm *ProcessMonitor) getTotalMemory() int64 { break } } - pm.totalMemory = defaultMemoryGB * 1024 * 1024 * 1024 // Fallback + pm.totalMemory = int64(defaultMemoryGB) * 1024 * 1024 * 1024 // Fallback }) return pm.totalMemory } diff --git a/internal/audio/relay.go b/internal/audio/relay.go index d8fb2d9..001faf4 100644 --- a/internal/audio/relay.go +++ b/internal/audio/relay.go @@ -151,7 +151,7 @@ func (r *AudioRelay) relayLoop() { r.logger.Error().Msg("Too many consecutive errors, stopping relay") return } - time.Sleep(10 * time.Millisecond) + time.Sleep(GetConfig().ShortSleepDuration) continue } diff --git a/internal/audio/socket_buffer.go b/internal/audio/socket_buffer.go index f7a0f7f..d5a97d6 100644 --- a/internal/audio/socket_buffer.go +++ b/internal/audio/socket_buffer.go @@ -6,12 +6,7 @@ import ( "syscall" ) -const ( - // Socket buffer sizes optimized for JetKVM's audio workload - OptimalSocketBuffer = 128 * 1024 // 128KB (32 frames @ 4KB each) - MaxSocketBuffer = 256 * 1024 // 256KB for high-load scenarios - MinSocketBuffer = 32 * 1024 // 32KB minimum for basic functionality -) +// Socket buffer sizes are now centralized in config_constants.go // SocketBufferConfig holds socket buffer configuration type SocketBufferConfig struct { @@ -23,8 +18,8 @@ type SocketBufferConfig struct { // DefaultSocketBufferConfig returns the default socket buffer configuration func DefaultSocketBufferConfig() SocketBufferConfig { return SocketBufferConfig{ - SendBufferSize: OptimalSocketBuffer, - RecvBufferSize: OptimalSocketBuffer, + SendBufferSize: GetConfig().SocketOptimalBuffer, + RecvBufferSize: GetConfig().SocketOptimalBuffer, Enabled: true, } } @@ -32,8 +27,8 @@ func DefaultSocketBufferConfig() SocketBufferConfig { // HighLoadSocketBufferConfig returns configuration for high-load scenarios func HighLoadSocketBufferConfig() SocketBufferConfig { return SocketBufferConfig{ - SendBufferSize: MaxSocketBuffer, - RecvBufferSize: MaxSocketBuffer, + SendBufferSize: GetConfig().SocketMaxBuffer, + RecvBufferSize: GetConfig().SocketMaxBuffer, Enabled: true, } } @@ -112,20 +107,20 @@ func ValidateSocketBufferConfig(config SocketBufferConfig) error { return nil } - if config.SendBufferSize < MinSocketBuffer { - return fmt.Errorf("send buffer size %d is below minimum %d", config.SendBufferSize, MinSocketBuffer) + if config.SendBufferSize < GetConfig().SocketMinBuffer { + return fmt.Errorf("send buffer size %d is below minimum %d", config.SendBufferSize, GetConfig().SocketMinBuffer) } - if config.RecvBufferSize < MinSocketBuffer { - return fmt.Errorf("receive buffer size %d is below minimum %d", config.RecvBufferSize, MinSocketBuffer) + if config.RecvBufferSize < GetConfig().SocketMinBuffer { + return fmt.Errorf("receive buffer size %d is below minimum %d", config.RecvBufferSize, GetConfig().SocketMinBuffer) } - if config.SendBufferSize > MaxSocketBuffer { - return fmt.Errorf("send buffer size %d exceeds maximum %d", config.SendBufferSize, MaxSocketBuffer) + if config.SendBufferSize > GetConfig().SocketMaxBuffer { + return fmt.Errorf("send buffer size %d exceeds maximum %d", config.SendBufferSize, GetConfig().SocketMaxBuffer) } - if config.RecvBufferSize > MaxSocketBuffer { - return fmt.Errorf("receive buffer size %d exceeds maximum %d", config.RecvBufferSize, MaxSocketBuffer) + if config.RecvBufferSize > GetConfig().SocketMaxBuffer { + return fmt.Errorf("receive buffer size %d exceeds maximum %d", config.RecvBufferSize, GetConfig().SocketMaxBuffer) } return nil diff --git a/internal/audio/supervisor.go b/internal/audio/supervisor.go index 9429c05..f4534da 100644 --- a/internal/audio/supervisor.go +++ b/internal/audio/supervisor.go @@ -131,7 +131,7 @@ func (s *AudioServerSupervisor) Stop() error { select { case <-s.processDone: s.logger.Info().Msg("audio server process stopped gracefully") - case <-time.After(10 * time.Second): + case <-time.After(GetConfig().SupervisorTimeout): s.logger.Warn().Msg("audio server process did not stop gracefully, forcing termination") s.forceKillProcess() } @@ -365,7 +365,7 @@ func (s *AudioServerSupervisor) terminateProcess() { select { case <-done: s.logger.Info().Int("pid", pid).Msg("audio server process terminated gracefully") - case <-time.After(5 * time.Second): + case <-time.After(GetConfig().InputSupervisorTimeout): s.logger.Warn().Int("pid", pid).Msg("process did not terminate gracefully, sending SIGKILL") s.forceKillProcess() } diff --git a/internal/audio/zero_copy.go b/internal/audio/zero_copy.go index b282d8b..a3fd582 100644 --- a/internal/audio/zero_copy.go +++ b/internal/audio/zero_copy.go @@ -234,7 +234,7 @@ func (p *ZeroCopyFramePool) GetZeroCopyPoolStats() ZeroCopyFramePoolStats { var hitRate float64 if totalRequests > 0 { - hitRate = float64(hitCount) / float64(totalRequests) * 100 + hitRate = float64(hitCount) / float64(totalRequests) * GetConfig().PercentageMultiplier } return ZeroCopyFramePoolStats{