Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

46 linhas
1.1KB

  1. package ingest
  2. import (
  3. "fmt"
  4. "math"
  5. "github.com/jan/fm-rds-tx/internal/audio"
  6. )
  7. const int32AbsMax = 2147483648.0
  8. func ChunkToFrames(chunk PCMChunk) ([]audio.Frame, error) {
  9. if chunk.Channels != 1 && chunk.Channels != 2 {
  10. return nil, fmt.Errorf("unsupported channel count: %d", chunk.Channels)
  11. }
  12. if chunk.Channels <= 0 {
  13. return nil, fmt.Errorf("invalid channel count: %d", chunk.Channels)
  14. }
  15. if len(chunk.Samples)%chunk.Channels != 0 {
  16. return nil, fmt.Errorf("invalid interleaved sample count: %d for channels=%d", len(chunk.Samples), chunk.Channels)
  17. }
  18. frames := make([]audio.Frame, len(chunk.Samples)/chunk.Channels)
  19. switch chunk.Channels {
  20. case 1:
  21. for i := range frames {
  22. s := normalizePCM(chunk.Samples[i])
  23. frames[i] = audio.NewFrame(s, s)
  24. }
  25. case 2:
  26. for i := range frames {
  27. off := i * 2
  28. l := normalizePCM(chunk.Samples[off])
  29. r := normalizePCM(chunk.Samples[off+1])
  30. frames[i] = audio.NewFrame(l, r)
  31. }
  32. }
  33. return frames, nil
  34. }
  35. func normalizePCM(v int32) audio.Sample {
  36. norm := float64(v) / int32AbsMax
  37. norm = math.Max(float64(audio.SampleMin), math.Min(float64(audio.SampleMax), norm))
  38. return audio.Sample(norm)
  39. }