package wav import ( "fmt" "os" "valhallir-deconvolver/pkg/convolve" "github.com/go-audio/audio" "github.com/go-audio/wav" ) // WAVData represents the PCM data and metadata from a WAV file type WAVData struct { SampleRate int BitDepth int Channels int PCMData []float64 } // toMono averages all channels to mono func toMono(data []float64, channels int) []float64 { if channels == 1 { return data } mono := make([]float64, len(data)/channels) for i := 0; i < len(mono); i++ { sum := 0.0 for c := 0; c < channels; c++ { sum += data[i*channels+c] } mono[i] = sum / float64(channels) } return mono } // ReadWAVFile reads a WAV file and returns its PCM data as float64 (resampled to 96kHz mono) func ReadWAVFile(filePath string) (*WAVData, error) { file, err := os.Open(filePath) if err != nil { return nil, fmt.Errorf("failed to open file %s: %w", filePath, err) } defer file.Close() decoder := wav.NewDecoder(file) if !decoder.IsValidFile() { return nil, fmt.Errorf("file %s is not a valid WAV file", filePath) } // Read all PCM data var pcmData []int32 buf := &audio.IntBuffer{Data: make([]int, 4096), Format: &audio.Format{SampleRate: int(decoder.SampleRate), NumChannels: int(decoder.NumChans)}} for { n, err := decoder.PCMBuffer(buf) if err != nil { break } if n == 0 { break } // Convert int samples to float64 for i := 0; i < n; i++ { pcmData = append(pcmData, int32(buf.Data[i])) } } // Convert int32 to float64 (-1.0 to 1.0 range, scale by bit depth) floatData := make([]float64, len(pcmData)) var norm float64 if decoder.BitDepth == 16 { norm = float64(1 << 15) } else if decoder.BitDepth == 24 { norm = float64(1 << 23) } else if decoder.BitDepth == 32 { norm = float64(1 << 31) } else { norm = float64(1 << 23) // fallback } for i, sample := range pcmData { floatData[i] = float64(sample) / norm } // Convert to mono if needed channels := int(decoder.NumChans) if channels > 1 { floatData = toMono(floatData, channels) channels = 1 } // Resample to 96kHz if needed inSampleRate := int(decoder.SampleRate) if inSampleRate != 96000 { floatData = convolve.Resample(floatData, inSampleRate, 96000) } return &WAVData{ SampleRate: 96000, BitDepth: int(decoder.BitDepth), // original bit depth Channels: 1, PCMData: floatData, }, nil }