|
- package ingest
-
- import (
- "fmt"
- "math"
-
- "github.com/jan/fm-rds-tx/internal/audio"
- )
-
- const int32AbsMax = 2147483648.0
-
- func ChunkToFrames(chunk PCMChunk) ([]audio.Frame, error) {
- if chunk.Channels != 1 && chunk.Channels != 2 {
- return nil, fmt.Errorf("unsupported channel count: %d", chunk.Channels)
- }
- if chunk.Channels <= 0 {
- return nil, fmt.Errorf("invalid channel count: %d", chunk.Channels)
- }
- if len(chunk.Samples)%chunk.Channels != 0 {
- return nil, fmt.Errorf("invalid interleaved sample count: %d for channels=%d", len(chunk.Samples), chunk.Channels)
- }
-
- frames := make([]audio.Frame, len(chunk.Samples)/chunk.Channels)
- switch chunk.Channels {
- case 1:
- for i := range frames {
- s := normalizePCM(chunk.Samples[i])
- frames[i] = audio.NewFrame(s, s)
- }
- case 2:
- for i := range frames {
- off := i * 2
- l := normalizePCM(chunk.Samples[off])
- r := normalizePCM(chunk.Samples[off+1])
- frames[i] = audio.NewFrame(l, r)
- }
- }
- return frames, nil
- }
-
- func normalizePCM(v int32) audio.Sample {
- norm := float64(v) / int32AbsMax
- norm = math.Max(float64(audio.SampleMin), math.Min(float64(audio.SampleMax), norm))
- return audio.Sample(norm)
- }
|