🎉 live server seems to be working now

This commit is contained in:
2026-05-14 14:29:57 +02:00
commit d72e439fd9
181 changed files with 47406 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
# Code Review Fixes - 24-bit Audio Implementation
## Date: 2025-10-25
After implementing the 24-bit audio pipeline, I performed a careful code review with "fresh eyes" and found several issues that have been fixed.
## Issues Found and Fixed
### 1. ✅ CRITICAL: Integer Overflow in Volume Control
**File:** `internal/player/output.go`
**Location:** `applyVolume()` function
**Problem:**
```go
result[i] = int32(float64(sample) * multiplier)
```
When applying volume to samples, there was no clipping protection. Samples at max 24-bit range (±8,388,607) multiplied by volume could overflow int32.
**Fix:**
```go
scaled := int64(float64(sample) * multiplier)
// Clamp to 24-bit range to prevent overflow
if scaled > audio.Max24Bit {
scaled = audio.Max24Bit
} else if scaled < audio.Min24Bit {
scaled = audio.Min24Bit
}
result[i] = int32(scaled)
```
**Impact:** Prevents audio distortion and crashes from integer overflow when volume is applied.
---
### 2. ✅ Improved Code Clarity: Better Comments
**File:** `internal/server/audio_source.go`
**Locations:** MP3Source, HTTPMP3Source, FFmpegSource Read methods
**Problem:**
Comments were confusing, referring to "int16 = 2 bytes" next to code dealing with int32 arrays.
**Before:**
```go
numBytes := len(samples) * 2 // int16 = 2 bytes
```
**After:**
```go
// Read bytes from decoder (MP3 decoder outputs int16 = 2 bytes per sample)
numBytes := len(samples) * 2
```
**Also added detailed comments for the conversion:**
```go
// Left-shift by 8 to convert 16-bit range to 24-bit range
// Example: 32767 (max 16-bit) << 8 = 8388352 (near max 24-bit 8388607)
samples[i] = int32(sample16) << 8
```
**Impact:** Makes code intention clearer for future maintainers.
---
### 3. ✅ Code Organization: Added 24-bit Constants
**File:** `internal/audio/types.go`
**Problem:**
24-bit range limits were hardcoded as magic numbers throughout the codebase.
**Fix:**
```go
const (
// 24-bit audio range constants
Max24Bit = 8388607 // 2^23 - 1
Min24Bit = -8388608 // -2^23
)
```
**Updated usages:**
- `internal/player/output.go` - Volume clipping now uses `audio.Max24Bit` and `audio.Min24Bit`
- `internal/server/test_tone_source.go` - Test tone generation uses `max24bit` constant
**Impact:** Single source of truth for 24-bit range, easier to maintain.
---
### 4. ✅ Improved Test Tone Comments
**File:** `internal/server/test_tone_source.go`
**Before:**
```go
pcmValue := int32(sample * 8388607.0 * 0.5) // 50% volume
```
**After:**
```go
// Convert to 24-bit PCM (using int32)
// Scale to 24-bit range and apply 50% volume to avoid clipping
const max24bit = 8388607 // 2^23 - 1
pcmValue := int32(sample * max24bit * 0.5)
```
**Impact:** Clarifies why 50% volume is used (to prevent clipping on sine wave peaks).
---
## Issues Considered But Not Changed
### 1. ResampledSource Error Handling
**File:** `internal/server/audio_source.go:511`
**Code:**
```go
outputSamples := r.resampler.Resample(r.inputBuffer[:n], samples)
return outputSamples, nil
```
**Analysis:**
The resampler returns the number of samples actually written. While we don't explicitly check if it filled the requested amount, this is actually correct behavior - the caller receives the actual count and can handle partial fills. No change needed.
### 2. FLAC Bit Depth Conversion
**File:** `internal/server/audio_source.go:266-280`
**Code:**
```go
if s.bitDepth == 16 {
samples[samplesRead] = sample << 8
} else if s.bitDepth == 24 {
samples[samplesRead] = sample
} else {
// For other bit depths, scale to 24-bit range
shift := s.bitDepth - 24
if shift > 0 {
samples[samplesRead] = sample >> shift
} else {
samples[samplesRead] = sample << -shift
}
}
```
**Analysis:**
The FLAC library returns samples as int32 in the native bit depth range. For 16-bit FLAC, the value is already correctly ranged ±32,768, so left-shifting by 8 is correct. For 24-bit, the value is already in the right range. The generic case handles other bit depths (8-bit, 20-bit, etc.). This logic is sound.
---
## Testing
After fixes:
- ✅ Server compiles successfully
- ✅ Player compiles successfully
- ✅ No new warnings or errors
## Summary
**Total Issues Fixed:** 4
- 1 Critical (integer overflow protection)
- 3 Code quality improvements (comments, constants)
**Lines Changed:** ~30 lines across 4 files
All fixes maintain backward compatibility and improve code robustness without changing the core 24-bit pipeline functionality.