Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

54 satır
1.9KB

  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", Description: "simulated soapy sink to file",
  19. })
  20. if err != nil { return "", err }
  21. defer fileBackend.Close(context.Background())
  22. soapyCfg := platform.SoapyConfig{
  23. BackendConfig: output.BackendConfig{
  24. SampleRateHz: float64(cfg.FM.CompositeRateHz), Channels: 2,
  25. IQLevel: float32(cfg.FM.OutputDrive),
  26. },
  27. Driver: "simulated", Device: cfg.Backend.Device,
  28. CenterFreqHz: cfg.FM.FrequencyMHz * 1_000_000,
  29. Simulated: true, SimulationPath: outPath,
  30. }
  31. driver := platform.NewSimulatedDriver(fileBackend)
  32. backend := platform.NewSoapyBackend(soapyCfg, driver)
  33. if err := backend.Configure(context.Background(), soapyCfg.BackendConfig); err != nil { return "", err }
  34. if err := driver.Start(context.Background()); err != nil { return "", err }
  35. gen := offpkg.NewGenerator(cfg)
  36. frame := gen.GenerateFrame(duration)
  37. if _, err := backend.Write(context.Background(), frame); err != nil { return "", err }
  38. if err := backend.Flush(context.Background()); err != nil { return "", err }
  39. _ = driver.Stop(context.Background())
  40. return fmt.Sprintf("simulated transmit: backend=%s output=%s duration=%s input=%s freq=%.1fMHz rate=%d",
  41. backend.Info().Name, outPath, duration, inputLabel(cfg), cfg.FM.FrequencyMHz, cfg.FM.CompositeRateHz), nil
  42. }
  43. func inputLabel(cfg cfgpkg.Config) string {
  44. if cfg.Audio.InputPath != "" { return cfg.Audio.InputPath }
  45. return "tones"
  46. }