Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

60 Zeilen
1.4KB

  1. package dsp
  2. import (
  3. "github.com/jan/fm-rds-tx/internal/output"
  4. )
  5. // ResampleIQ resamples a CompositeFrame from its native sample rate to
  6. // the target device rate using linear interpolation. Returns a new frame.
  7. // If rates are equal (within 0.5 Hz), returns the original frame unchanged.
  8. func ResampleIQ(frame *output.CompositeFrame, targetRateHz float64) *output.CompositeFrame {
  9. if frame == nil || len(frame.Samples) == 0 {
  10. return frame
  11. }
  12. srcRate := frame.SampleRateHz
  13. if srcRate <= 0 || targetRateHz <= 0 {
  14. return frame
  15. }
  16. // No resampling needed if rates match
  17. ratio := targetRateHz / srcRate
  18. if ratio > 0.999 && ratio < 1.001 {
  19. return frame
  20. }
  21. srcLen := len(frame.Samples)
  22. dstLen := int(float64(srcLen) * ratio)
  23. if dstLen <= 0 {
  24. return frame
  25. }
  26. dst := make([]output.IQSample, dstLen)
  27. step := 1.0 / ratio // position step in source samples per output sample
  28. pos := 0.0
  29. for i := 0; i < dstLen; i++ {
  30. idx := int(pos)
  31. frac := float32(pos - float64(idx))
  32. if idx+1 < srcLen {
  33. s0 := frame.Samples[idx]
  34. s1 := frame.Samples[idx+1]
  35. dst[i] = output.IQSample{
  36. I: s0.I*(1-frac) + s1.I*frac,
  37. Q: s0.Q*(1-frac) + s1.Q*frac,
  38. }
  39. } else if idx < srcLen {
  40. dst[i] = frame.Samples[idx]
  41. }
  42. pos += step
  43. }
  44. return &output.CompositeFrame{
  45. Samples: dst,
  46. SampleRateHz: targetRateHz,
  47. Timestamp: frame.Timestamp,
  48. Sequence: frame.Sequence,
  49. }
  50. }