Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

64 lignes
2.0KB

  1. package app
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "fmt"
  6. "path/filepath"
  7. "time"
  8. cfgpkg "github.com/jan/fm-rds-tx/internal/config"
  9. offpkg "github.com/jan/fm-rds-tx/internal/offline"
  10. "github.com/jan/fm-rds-tx/internal/output"
  11. "github.com/jan/fm-rds-tx/internal/platform"
  12. )
  13. func RunSimulatedTransmit(cfg cfgpkg.Config, outPath string, duration time.Duration) (string, error) {
  14. if outPath == "" {
  15. outPath = filepath.Join("build", "sim", "simulated-soapy.iqf32")
  16. }
  17. fileBackend, err := output.NewFileBackend(outPath, binary.LittleEndian, output.BackendInfo{
  18. Name: "simulated-soapy-file",
  19. Description: "simulated soapy sink to file",
  20. })
  21. if err != nil {
  22. return "", err
  23. }
  24. defer fileBackend.Close(context.Background())
  25. soapyCfg := platform.SoapyConfig{
  26. BackendConfig: output.BackendConfig{
  27. SampleRateHz: float64(cfg.FM.CompositeRateHz),
  28. Channels: 2,
  29. IQLevel: float32(cfg.FM.OutputDrive),
  30. },
  31. Driver: "simulated",
  32. Device: cfg.Backend.Device,
  33. CenterFreqHz: cfg.FM.FrequencyMHz * 1_000_000,
  34. Simulated: true,
  35. SimulationPath: outPath,
  36. }
  37. backend := platform.NewSoapyBackend(soapyCfg, platform.NewSimulatedDriver(fileBackend))
  38. if err := backend.Configure(context.Background(), soapyCfg.BackendConfig); err != nil {
  39. return "", err
  40. }
  41. gen := offpkg.NewGenerator(cfg)
  42. frame := gen.GenerateFrame(duration)
  43. if _, err := backend.Write(context.Background(), frame); err != nil {
  44. return "", err
  45. }
  46. if err := backend.Flush(context.Background()); err != nil {
  47. return "", err
  48. }
  49. return fmt.Sprintf("simulated transmit: backend=%s output=%s duration=%s input=%s", backend.Info().Name, outPath, duration, inputLabel(cfg)), nil
  50. }
  51. func inputLabel(cfg cfgpkg.Config) string {
  52. if cfg.Audio.InputPath != "" {
  53. return cfg.Audio.InputPath
  54. }
  55. return "tones"
  56. }