Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

47 行
1.5KB

  1. package dsp
  2. import "math"
  3. // FMModulator converts a composite baseband signal into FM-modulated IQ samples.
  4. // The modulated output represents the instantaneous frequency deviation around
  5. // a zero-IF carrier (baseband IQ). For a real SDR transmitter the SDR hardware
  6. // then upconverts this to the desired center frequency.
  7. type FMModulator struct {
  8. // MaxDeviation is the peak frequency deviation in Hz (±75 kHz for FM broadcast).
  9. MaxDeviation float64
  10. SampleRate float64
  11. phase float64 // accumulated carrier phase in radians
  12. }
  13. // NewFMModulator creates a modulator with broadcast FM defaults.
  14. func NewFMModulator(sampleRate float64) *FMModulator {
  15. return &FMModulator{
  16. MaxDeviation: 75000, // ±75 kHz
  17. SampleRate: sampleRate,
  18. }
  19. }
  20. // Modulate converts a single composite sample (normalized to [-1,+1] representing
  21. // full deviation) into an IQ pair.
  22. func (m *FMModulator) Modulate(composite float64) (i, q float64) {
  23. // Instantaneous frequency offset = composite * maxDeviation
  24. // Phase increment per sample = 2π * freq_offset / sampleRate
  25. freqOffset := composite * m.MaxDeviation
  26. m.phase += 2 * math.Pi * freqOffset / m.SampleRate
  27. // Keep phase bounded to avoid float64 precision loss over long runs
  28. if m.phase > math.Pi || m.phase < -math.Pi {
  29. m.phase -= 2 * math.Pi * math.Floor((m.phase+math.Pi)/(2*math.Pi))
  30. }
  31. i = math.Cos(m.phase)
  32. q = math.Sin(m.phase)
  33. return i, q
  34. }
  35. // Reset clears the modulator phase.
  36. func (m *FMModulator) Reset() {
  37. m.phase = 0
  38. }