mirror of https://github.com/jetkvm/kvm.git
style(audio): fix formatting and add missing newlines
- Fix indentation in test files and supervisor code - Add missing newlines at end of files - Clean up documentation formatting - Fix buffer pool pointer return type
This commit is contained in:
parent
6a68e23d12
commit
e8d12bae4b
|
@ -18,17 +18,17 @@ import (
|
|||
// uses multiple factors to make decisions:
|
||||
//
|
||||
// 1. System Load Monitoring:
|
||||
// - CPU usage: High CPU load increases buffer sizes to prevent underruns
|
||||
// - Memory usage: High memory pressure reduces buffer sizes to conserve RAM
|
||||
// - CPU usage: High CPU load increases buffer sizes to prevent underruns
|
||||
// - Memory usage: High memory pressure reduces buffer sizes to conserve RAM
|
||||
//
|
||||
// 2. Latency Tracking:
|
||||
// - Target latency: Optimal latency for the current quality setting
|
||||
// - Max latency: Hard limit beyond which buffers are aggressively reduced
|
||||
// - Target latency: Optimal latency for the current quality setting
|
||||
// - Max latency: Hard limit beyond which buffers are aggressively reduced
|
||||
//
|
||||
// 3. Adaptation Strategy:
|
||||
// - Exponential smoothing: Prevents oscillation and provides stable adjustments
|
||||
// - Discrete steps: Buffer sizes change in fixed increments to avoid instability
|
||||
// - Hysteresis: Different thresholds for increasing vs decreasing buffer sizes
|
||||
// - Exponential smoothing: Prevents oscillation and provides stable adjustments
|
||||
// - Discrete steps: Buffer sizes change in fixed increments to avoid instability
|
||||
// - Hysteresis: Different thresholds for increasing vs decreasing buffer sizes
|
||||
//
|
||||
// The algorithm is specifically tuned for embedded ARM systems with limited resources,
|
||||
// prioritizing stability over absolute minimum latency.
|
||||
|
@ -182,20 +182,23 @@ func (abm *AdaptiveBufferManager) adaptationLoop() {
|
|||
//
|
||||
// Mathematical Model:
|
||||
// 1. Factor Calculation:
|
||||
// - CPU Factor: Sigmoid function that increases buffer size under high CPU load
|
||||
// - Memory Factor: Inverse relationship that decreases buffer size under memory pressure
|
||||
// - Latency Factor: Exponential decay that aggressively reduces buffers when latency exceeds targets
|
||||
//
|
||||
// 2. Combined Factor:
|
||||
// Combined = (CPU_factor * Memory_factor * Latency_factor)
|
||||
// This multiplicative approach ensures any single critical factor can override others
|
||||
// - CPU Factor: Sigmoid function that increases buffer size under high CPU load
|
||||
//
|
||||
// 3. Exponential Smoothing:
|
||||
// New_size = Current_size + smoothing_factor * (Target_size - Current_size)
|
||||
// This prevents rapid oscillations and provides stable convergence
|
||||
// - Memory Factor: Inverse relationship that decreases buffer size under memory pressure
|
||||
//
|
||||
// 4. Discrete Quantization:
|
||||
// Final sizes are rounded to frame boundaries and clamped to configured limits
|
||||
// - Latency Factor: Exponential decay that aggressively reduces buffers when latency exceeds targets
|
||||
//
|
||||
// 2. Combined Factor:
|
||||
// Combined = (CPU_factor * Memory_factor * Latency_factor)
|
||||
// This multiplicative approach ensures any single critical factor can override others
|
||||
//
|
||||
// 3. Exponential Smoothing:
|
||||
// New_size = Current_size + smoothing_factor * (Target_size - Current_size)
|
||||
// This prevents rapid oscillations and provides stable convergence
|
||||
//
|
||||
// 4. Discrete Quantization:
|
||||
// Final sizes are rounded to frame boundaries and clamped to configured limits
|
||||
//
|
||||
// The algorithm runs periodically and only applies changes when the adaptation interval
|
||||
// has elapsed, preventing excessive adjustments that could destabilize the audio pipeline.
|
||||
|
|
|
@ -40,7 +40,8 @@ func NewAudioBufferPool(bufferSize int) *AudioBufferPool {
|
|||
preallocSize: preallocSize,
|
||||
pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 0, bufferSize)
|
||||
buf := make([]byte, 0, bufferSize)
|
||||
return &buf
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -78,8 +78,8 @@ const (
|
|||
AudioOutputIPCComponent = "audio-output-ipc"
|
||||
|
||||
// Common component names
|
||||
AudioRelayComponent = "audio-relay"
|
||||
AudioEventsComponent = "audio-events"
|
||||
AudioRelayComponent = "audio-relay"
|
||||
AudioEventsComponent = "audio-events"
|
||||
AudioMetricsComponent = "audio-metrics"
|
||||
)
|
||||
|
||||
|
|
|
@ -52,9 +52,9 @@ type AudioOutputSupervisor struct {
|
|||
lastExitTime time.Time
|
||||
|
||||
// Channels for coordination
|
||||
processDone chan struct{}
|
||||
stopChan chan struct{}
|
||||
stopChanClosed bool // Track if stopChan is closed
|
||||
processDone chan struct{}
|
||||
stopChan chan struct{}
|
||||
stopChanClosed bool // Track if stopChan is closed
|
||||
processDoneClosed bool // Track if processDone is closed
|
||||
|
||||
// Process monitoring
|
||||
|
@ -107,7 +107,7 @@ func (s *AudioOutputSupervisor) Start() error {
|
|||
s.mutex.Lock()
|
||||
s.processDone = make(chan struct{})
|
||||
s.stopChan = make(chan struct{})
|
||||
s.stopChanClosed = false // Reset channel closed flag
|
||||
s.stopChanClosed = false // Reset channel closed flag
|
||||
s.processDoneClosed = false // Reset channel closed flag
|
||||
// Recreate context as well since it might have been cancelled
|
||||
s.ctx, s.cancel = context.WithCancel(context.Background())
|
||||
|
|
|
@ -109,9 +109,9 @@ func TestAudioOutputSupervisorConcurrentOperations(t *testing.T) {
|
|||
for i := 0; i < 5; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_ = supervisor.GetProcessMetrics()
|
||||
}()
|
||||
defer wg.Done()
|
||||
_ = supervisor.GetProcessMetrics()
|
||||
}()
|
||||
}
|
||||
|
||||
// Test concurrent status checks
|
||||
|
|
|
@ -11,25 +11,25 @@ import (
|
|||
|
||||
// Enhanced validation errors with more specific context
|
||||
var (
|
||||
ErrInvalidFrameLength = errors.New("invalid frame length")
|
||||
ErrFrameDataCorrupted = errors.New("frame data appears corrupted")
|
||||
ErrBufferAlignment = errors.New("buffer alignment invalid")
|
||||
ErrInvalidSampleFormat = errors.New("invalid sample format")
|
||||
ErrInvalidTimestamp = errors.New("invalid timestamp")
|
||||
ErrConfigurationMismatch = errors.New("configuration mismatch")
|
||||
ErrResourceExhaustion = errors.New("resource exhaustion detected")
|
||||
ErrInvalidPointer = errors.New("invalid pointer")
|
||||
ErrBufferOverflow = errors.New("buffer overflow detected")
|
||||
ErrInvalidState = errors.New("invalid state")
|
||||
ErrInvalidFrameLength = errors.New("invalid frame length")
|
||||
ErrFrameDataCorrupted = errors.New("frame data appears corrupted")
|
||||
ErrBufferAlignment = errors.New("buffer alignment invalid")
|
||||
ErrInvalidSampleFormat = errors.New("invalid sample format")
|
||||
ErrInvalidTimestamp = errors.New("invalid timestamp")
|
||||
ErrConfigurationMismatch = errors.New("configuration mismatch")
|
||||
ErrResourceExhaustion = errors.New("resource exhaustion detected")
|
||||
ErrInvalidPointer = errors.New("invalid pointer")
|
||||
ErrBufferOverflow = errors.New("buffer overflow detected")
|
||||
ErrInvalidState = errors.New("invalid state")
|
||||
)
|
||||
|
||||
// ValidationLevel defines the level of validation to perform
|
||||
type ValidationLevel int
|
||||
|
||||
const (
|
||||
ValidationMinimal ValidationLevel = iota // Only critical safety checks
|
||||
ValidationStandard // Standard validation for production
|
||||
ValidationStrict // Comprehensive validation for debugging
|
||||
ValidationMinimal ValidationLevel = iota // Only critical safety checks
|
||||
ValidationStandard // Standard validation for production
|
||||
ValidationStrict // Comprehensive validation for debugging
|
||||
)
|
||||
|
||||
// ValidationConfig controls validation behavior
|
||||
|
@ -47,7 +47,7 @@ func GetValidationConfig() ValidationConfig {
|
|||
Level: ValidationStandard,
|
||||
EnableRangeChecks: true,
|
||||
EnableAlignmentCheck: true,
|
||||
EnableDataIntegrity: false, // Disabled by default for performance
|
||||
EnableDataIntegrity: false, // Disabled by default for performance
|
||||
MaxValidationTime: 5 * time.Second, // Default validation timeout
|
||||
}
|
||||
}
|
||||
|
@ -254,9 +254,10 @@ func validateAudioDataIntegrity(data []byte, channels int) error {
|
|||
|
||||
for i := 0; i < len(data); i += 2 {
|
||||
sample := int16(data[i]) | int16(data[i+1])<<8
|
||||
if sample == 0 {
|
||||
switch sample {
|
||||
case 0:
|
||||
zeroCount++
|
||||
} else if sample == 32767 || sample == -32768 {
|
||||
case 32767, -32768:
|
||||
maxCount++
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,25 +13,27 @@ import (
|
|||
// allocations and memory copying in the audio pipeline:
|
||||
//
|
||||
// Key Features:
|
||||
// 1. Reference Counting: Multiple components can safely share the same frame data
|
||||
// without copying. The frame is automatically returned to the pool when the last
|
||||
// reference is released.
|
||||
//
|
||||
// 2. Thread Safety: All operations are protected by RWMutex, allowing concurrent
|
||||
// reads while ensuring exclusive access for modifications.
|
||||
// 1. Reference Counting: Multiple components can safely share the same frame data
|
||||
// without copying. The frame is automatically returned to the pool when the last
|
||||
// reference is released.
|
||||
//
|
||||
// 3. Pool Integration: Frames are automatically managed by ZeroCopyFramePool,
|
||||
// enabling efficient reuse and preventing memory fragmentation.
|
||||
// 2. Thread Safety: All operations are protected by RWMutex, allowing concurrent
|
||||
// reads while ensuring exclusive access for modifications.
|
||||
//
|
||||
// 4. Unsafe Pointer Access: For performance-critical CGO operations, direct
|
||||
// memory access is provided while maintaining safety through reference counting.
|
||||
// 3. Pool Integration: Frames are automatically managed by ZeroCopyFramePool,
|
||||
// enabling efficient reuse and preventing memory fragmentation.
|
||||
//
|
||||
// 4. Unsafe Pointer Access: For performance-critical CGO operations, direct
|
||||
// memory access is provided while maintaining safety through reference counting.
|
||||
//
|
||||
// Usage Pattern:
|
||||
// frame := pool.Get() // Acquire frame (refCount = 1)
|
||||
// frame.AddRef() // Share with another component (refCount = 2)
|
||||
// data := frame.Data() // Access data safely
|
||||
// frame.Release() // Release reference (refCount = 1)
|
||||
// frame.Release() // Final release, returns to pool (refCount = 0)
|
||||
//
|
||||
// frame := pool.Get() // Acquire frame (refCount = 1)
|
||||
// frame.AddRef() // Share with another component (refCount = 2)
|
||||
// data := frame.Data() // Access data safely
|
||||
// frame.Release() // Release reference (refCount = 1)
|
||||
// frame.Release() // Final release, returns to pool (refCount = 0)
|
||||
//
|
||||
// Memory Safety:
|
||||
// - Frames cannot be modified while shared (refCount > 1)
|
||||
|
@ -52,19 +54,22 @@ type ZeroCopyAudioFrame struct {
|
|||
// real-time audio processing with minimal allocation overhead:
|
||||
//
|
||||
// Tier 1 - Pre-allocated Frames:
|
||||
// A small number of frames are pre-allocated at startup and kept ready
|
||||
// for immediate use. This provides the fastest possible allocation for
|
||||
// the most common case and eliminates allocation latency spikes.
|
||||
//
|
||||
// A small number of frames are pre-allocated at startup and kept ready
|
||||
// for immediate use. This provides the fastest possible allocation for
|
||||
// the most common case and eliminates allocation latency spikes.
|
||||
//
|
||||
// Tier 2 - sync.Pool Cache:
|
||||
// The standard Go sync.Pool provides efficient reuse of frames with
|
||||
// automatic garbage collection integration. Frames are automatically
|
||||
// returned here when memory pressure is low.
|
||||
//
|
||||
// The standard Go sync.Pool provides efficient reuse of frames with
|
||||
// automatic garbage collection integration. Frames are automatically
|
||||
// returned here when memory pressure is low.
|
||||
//
|
||||
// Tier 3 - Memory Guard:
|
||||
// A configurable limit prevents excessive memory usage by limiting
|
||||
// the total number of allocated frames. When the limit is reached,
|
||||
// allocation requests are denied to prevent OOM conditions.
|
||||
//
|
||||
// A configurable limit prevents excessive memory usage by limiting
|
||||
// the total number of allocated frames. When the limit is reached,
|
||||
// allocation requests are denied to prevent OOM conditions.
|
||||
//
|
||||
// Performance Characteristics:
|
||||
// - Pre-allocated tier: ~10ns allocation time
|
||||
|
|
Loading…
Reference in New Issue