Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 line
2.1KB

  1. package main
  2. import (
  3. "context"
  4. "flag"
  5. "fmt"
  6. "log"
  7. "os/signal"
  8. "syscall"
  9. "time"
  10. "aoiprxkit"
  11. )
  12. func main() {
  13. mode := flag.String("mode", "rtp", "rtp|sap")
  14. group := flag.String("group", "239.69.0.1", "IPv4 multicast group")
  15. port := flag.Int("port", 5004, "UDP port")
  16. iface := flag.String("iface", "", "network interface name")
  17. pt := flag.Int("pt", 97, "expected RTP payload type")
  18. rate := flag.Int("rate", 48000, "sample rate")
  19. ch := flag.Int("ch", 2, "channels")
  20. flag.Parse()
  21. ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
  22. defer stop()
  23. switch *mode {
  24. case "sap":
  25. listener, err := aoiprxkit.NewSAPListener(aoiprxkit.SAPListenerConfig{
  26. Group: aoiprxkit.DefaultSAPGroup,
  27. Port: aoiprxkit.DefaultSAPPort,
  28. InterfaceName: *iface,
  29. ReadBuffer: 1 << 20,
  30. }, func(a aoiprxkit.SAPAnnouncement) {
  31. fmt.Printf("SAP session: name=%q group=%s port=%d pt=%d encoding=%s rate=%d ch=%d delete=%v\n",
  32. a.ParsedSDP.SessionName,
  33. a.ParsedSDP.MulticastGroup,
  34. a.ParsedSDP.Port,
  35. a.ParsedSDP.PayloadType,
  36. a.ParsedSDP.Encoding,
  37. a.ParsedSDP.SampleRateHz,
  38. a.ParsedSDP.Channels,
  39. a.Delete,
  40. )
  41. })
  42. if err != nil {
  43. log.Fatal(err)
  44. }
  45. if err := listener.Start(ctx); err != nil {
  46. log.Fatal(err)
  47. }
  48. defer listener.Stop()
  49. <-ctx.Done()
  50. default:
  51. cfg := aoiprxkit.DefaultConfig()
  52. cfg.MulticastGroup = *group
  53. cfg.Port = *port
  54. cfg.InterfaceName = *iface
  55. cfg.PayloadType = uint8(*pt)
  56. cfg.SampleRateHz = *rate
  57. cfg.Channels = *ch
  58. var packets uint64
  59. rx, err := aoiprxkit.NewReceiver(cfg, func(frame aoiprxkit.PCMFrame) {
  60. packets++
  61. if packets%100 == 0 {
  62. fmt.Printf("delivered packet seq=%d ts=%d samples=%d source=%s\n", frame.SequenceNumber, frame.Timestamp, len(frame.Samples), frame.Source)
  63. }
  64. })
  65. if err != nil {
  66. log.Fatal(err)
  67. }
  68. if err := rx.Start(ctx); err != nil {
  69. log.Fatal(err)
  70. }
  71. defer rx.Stop()
  72. ticker := time.NewTicker(2 * time.Second)
  73. defer ticker.Stop()
  74. for {
  75. select {
  76. case <-ctx.Done():
  77. fmt.Println("stopping")
  78. return
  79. case <-ticker.C:
  80. fmt.Printf("stats: %+v\n", rx.Stats())
  81. }
  82. }
  83. }
  84. }