Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

627 行
29KB

  1. package rds
  2. import (
  3. "math"
  4. "sync/atomic"
  5. "time"
  6. )
  7. // RDS encoder — port of PiFmRds, adapted for arbitrary sample rates.
  8. // At 228 kHz: uses exact {0,+1,0,-1} carrier (identical to PiFmRds).
  9. // At other rates: uses sin() carrier, with integer samples-per-bit when possible.
  10. // The biphase waveform from PiFmRds is resampled to the target rate.
  11. const (
  12. refRate = 228000.0 // PiFmRds native rate
  13. rdsBitRate = 1187.5
  14. refSPB = 192 // refRate / rdsBitRate
  15. bitsPerBlock = 26
  16. bitsPerGroup = 4 * bitsPerBlock
  17. refFilterSize = 576 // PiFmRds waveform length at 228k
  18. )
  19. const crcPoly = 0x1B9
  20. var offsetWords = map[byte]uint16{'A': 0x0FC, 'B': 0x198, 'C': 0x168, 'c': 0x350, 'D': 0x1B4}
  21. func crc10(data uint16) uint16 {
  22. var reg uint32 = uint32(data) << 10
  23. for i := 15; i >= 0; i-- {
  24. if reg&(1<<(uint(i)+10)) != 0 { reg ^= uint32(crcPoly) << uint(i) }
  25. }
  26. return uint16(reg & 0x3FF)
  27. }
  28. func encodeBlock(data uint16, offset byte) uint32 {
  29. return (uint32(data) << 10) | uint32(crc10(data)^offsetWords[offset])
  30. }
  31. // GroupScheduler manages priority-based scheduling of all RDS group types.
  32. // Priority 1: 0A (PS/AF) and 2A (RT) — every cycle
  33. // Priority 2: 4A (CT), 11A (RT+), 3A (ODA), 10A (PTYN) — every N cycles
  34. // Priority 3: 14A (EON) — round-robin when slots available
  35. type GroupScheduler struct {
  36. cfg RDSConfig
  37. // Group 0A state
  38. psIdx int
  39. afPairs [][2]uint8 // precomputed AF code pairs
  40. // Group 2A state
  41. rtIdx int
  42. rtABFlag bool
  43. // Group 10A state
  44. ptynIdx int
  45. ptynABFlag bool
  46. // Group 11A state (RT+)
  47. rtPlusTag1 RTPlusTag
  48. rtPlusTag2 RTPlusTag
  49. rtPlusHas2 bool
  50. rtPlusToggle bool
  51. // Group 14A state (EON)
  52. eonStationIdx int
  53. eonVariantIdx int
  54. // Scheduling state
  55. cycle int // overall group counter
  56. phase int // position within current scheduling cycle
  57. lastCT time.Time // last time CT was sent
  58. }
  59. func newGroupScheduler(cfg RDSConfig) *GroupScheduler {
  60. gs := &GroupScheduler{cfg: cfg}
  61. gs.afPairs = buildAFList(cfg.AF)
  62. if cfg.RTPlusEnabled && cfg.RT != "" {
  63. gs.rtPlusTag1, gs.rtPlusTag2, gs.rtPlusHas2 = ParseRTPlus(cfg.RT, cfg.RTPlusSeparator)
  64. }
  65. return gs
  66. }
  67. // refreshRTPlus re-parses RT+ tags after an RT text change.
  68. func (gs *GroupScheduler) refreshRTPlus() {
  69. if gs.cfg.RTPlusEnabled && gs.cfg.RT != "" {
  70. gs.rtPlusTag1, gs.rtPlusTag2, gs.rtPlusHas2 = ParseRTPlus(gs.cfg.RT, gs.cfg.RTPlusSeparator)
  71. gs.rtPlusToggle = !gs.rtPlusToggle
  72. }
  73. }
  74. func (gs *GroupScheduler) NextGroup() [4]uint16 {
  75. gs.cycle++
  76. // --- Priority 1: 0A and 2A alternate ---
  77. // Pattern per cycle: 0A, 2A, 0A, 2A, 0A, 2A, 0A, 2A, [priority 2/3 slot]
  78. // This gives ~5.7 0A groups/sec and ~5.7 2A groups/sec at 11.4 groups/sec.
  79. // Every 8th group: try a priority 2/3 group
  80. if gs.cycle%8 == 0 {
  81. if g, ok := gs.nextPriority2Group(); ok {
  82. return g
  83. }
  84. // No priority 2/3 available — fall through to normal 0A/2A
  85. }
  86. // Alternate 0A and 2A
  87. if gs.cycle%2 == 0 {
  88. return gs.nextGroup0A()
  89. }
  90. return gs.nextGroup2A()
  91. }
  92. func (gs *GroupScheduler) nextGroup0A() [4]uint16 {
  93. var afPair [2]uint8
  94. if gs.psIdx < len(gs.afPairs) {
  95. afPair = gs.afPairs[gs.psIdx]
  96. }
  97. g := buildGroup0A(&gs.cfg, gs.psIdx, afPair)
  98. gs.psIdx = (gs.psIdx + 1) % 4
  99. return g
  100. }
  101. func (gs *GroupScheduler) nextGroup2A() [4]uint16 {
  102. g := buildGroup2A(gs.cfg.PI, gs.cfg.PTY, gs.cfg.TP, gs.rtABFlag, gs.rtIdx, gs.cfg.RT)
  103. gs.rtIdx++
  104. rtSegs := rtSegmentCount(gs.cfg.RT)
  105. if gs.rtIdx >= rtSegs {
  106. gs.rtIdx = 0
  107. }
  108. return g
  109. }
  110. // nextPriority2Group returns a lower-priority group if one is due.
  111. // Round-robins through: CT → RT+ (3A+11A) → PTYN → EON
  112. func (gs *GroupScheduler) nextPriority2Group() ([4]uint16, bool) {
  113. slot := (gs.cycle / 8) % 8 // 8 priority-2 slots, cycling
  114. switch {
  115. case slot == 0 && gs.cfg.CTEnabled:
  116. return gs.nextGroupCT(), true
  117. case slot == 1 && gs.cfg.RTPlusEnabled && gs.cfg.RT != "":
  118. // 3A: ODA announcement for RT+
  119. return buildGroup3A(gs.cfg.PI, gs.cfg.PTY, gs.cfg.TP, rtPlusODA, groupType11A), true
  120. case slot == 2 && gs.cfg.RTPlusEnabled && gs.cfg.RT != "":
  121. // 11A: RT+ tags
  122. return gs.nextGroupRTPlus(), true
  123. case slot == 3 && gs.cfg.PTYN != "":
  124. return gs.nextGroupPTYN(), true
  125. case slot >= 4 && len(gs.cfg.EON) > 0:
  126. return gs.nextGroupEON(), true
  127. }
  128. return [4]uint16{}, false
  129. }
  130. func (gs *GroupScheduler) nextGroupCT() [4]uint16 {
  131. now := time.Now().UTC()
  132. offset := gs.cfg.CTOffsetHalfHours
  133. if offset == 0 {
  134. // Auto-detect from OS timezone
  135. _, tzOffset := time.Now().Zone()
  136. offset = int8(tzOffset / 1800) // seconds → half-hours
  137. }
  138. gs.lastCT = now
  139. return buildGroup4A(gs.cfg.PI, gs.cfg.PTY, gs.cfg.TP, now, offset)
  140. }
  141. func (gs *GroupScheduler) nextGroupRTPlus() [4]uint16 {
  142. t1 := gs.rtPlusTag1
  143. t2 := gs.rtPlusTag2
  144. if !gs.rtPlusHas2 {
  145. t2 = RTPlusTag{} // dummy tag
  146. }
  147. // Length encoding: RT+ uses length-1 (0 = 1 char)
  148. t1Len := t1.Length
  149. if t1Len > 0 {
  150. t1Len--
  151. }
  152. t2Len := t2.Length
  153. if t2Len > 0 {
  154. t2Len--
  155. }
  156. return buildGroup11A(gs.cfg.PI, gs.cfg.PTY, gs.cfg.TP, true,
  157. t1.ContentType, t1.Start, t1Len,
  158. t2.ContentType, t2.Start, t2Len)
  159. }
  160. func (gs *GroupScheduler) nextGroupPTYN() [4]uint16 {
  161. g := buildGroup10A(gs.cfg.PI, gs.cfg.PTY, gs.cfg.TP, gs.ptynABFlag, gs.ptynIdx, gs.cfg.PTYN)
  162. gs.ptynIdx = (gs.ptynIdx + 1) % 2
  163. return g
  164. }
  165. func (gs *GroupScheduler) nextGroupEON() [4]uint16 {
  166. if len(gs.cfg.EON) == 0 {
  167. return gs.nextGroup0A() // fallback
  168. }
  169. eon := &gs.cfg.EON[gs.eonStationIdx]
  170. g := buildGroup14A(gs.cfg.PI, gs.cfg.PTY, gs.cfg.TP, gs.eonVariantIdx, eon)
  171. gs.eonVariantIdx++
  172. maxVariant := 4 // PS segments 0-3
  173. if len(eon.AF) >= 2 {
  174. maxVariant = 5 // +AF pair
  175. }
  176. if gs.eonVariantIdx >= maxVariant {
  177. gs.eonVariantIdx = 0
  178. gs.eonStationIdx = (gs.eonStationIdx + 1) % len(gs.cfg.EON)
  179. }
  180. return g
  181. }
  182. // Encoder generates RDS subcarrier samples at any sample rate.
  183. // Uses the PiFmRds waveform resampled to the target rate.
  184. type Encoder struct {
  185. config RDSConfig
  186. scheduler *GroupScheduler
  187. sampleRate float64
  188. spb int // samples per bit at target rate
  189. waveform []float64 // resampled PiFmRds waveform
  190. wfLen int // length of resampled waveform
  191. ring []float64 // overlap-add ring buffer
  192. ringSize int
  193. bitBuffer [bitsPerGroup]int
  194. bitPos int
  195. prevOutput int
  196. curOutput int
  197. sampleCount int
  198. inSampleIdx int
  199. outSampleIdx int
  200. carrierPhase float64 // for sin() carrier at non-228k rates
  201. carrierStep float64
  202. SampleRate float64
  203. // Live-updatable text — written by control API, read at group boundaries.
  204. // Zero-contention: atomic swap, checked once per RDS group (~88ms at 228kHz).
  205. // pendingText.set distinguishes "no pending update" from "update to empty string"
  206. // so that PS/RT can be explicitly cleared via UpdateText.
  207. livePS atomic.Value // pendingText
  208. liveRT atomic.Value // pendingText
  209. liveTA atomic.Int32 // -1=no change, 0=false, 1=true
  210. liveTP atomic.Int32 // -1=no change, 0=false, 1=true
  211. }
  212. // pendingText carries a pending text update for PS or RT.
  213. // set=false means no update is pending; set=true means apply val (even if empty).
  214. type pendingText struct {
  215. val string
  216. set bool
  217. }
  218. func NewEncoder(cfg RDSConfig) (*Encoder, error) {
  219. if cfg.SampleRate <= 0 { cfg.SampleRate = refRate }
  220. cfg.PS = normalizePS(cfg.PS); cfg.RT = normalizeRT(cfg.RT)
  221. rate := cfg.SampleRate
  222. spb := int(math.Round(rate / rdsBitRate))
  223. ratio := rate / refRate
  224. // Resample PiFmRds waveform to target rate
  225. wfLen := int(math.Round(float64(refFilterSize) * ratio))
  226. waveform := make([]float64, wfLen)
  227. for i := range waveform {
  228. srcPos := float64(i) / ratio
  229. idx := int(srcPos)
  230. frac := srcPos - float64(idx)
  231. if idx+1 < refFilterSize {
  232. waveform[i] = refWaveform[idx]*(1-frac) + refWaveform[idx+1]*frac
  233. } else if idx < refFilterSize {
  234. waveform[i] = refWaveform[idx]
  235. }
  236. }
  237. // Normalize to peak=1.0 so rdsInjection directly maps to injection %.
  238. // The raw PiFmRds waveform peaks at ~0.543, which would make config
  239. // values misleading (0.05 would give 2.7% instead of 5%).
  240. var peak float64
  241. for _, v := range waveform {
  242. if a := math.Abs(v); a > peak { peak = a }
  243. }
  244. if peak > 0 {
  245. for i := range waveform {
  246. waveform[i] /= peak
  247. }
  248. }
  249. ringSize := spb + wfLen
  250. enc := &Encoder{
  251. config: cfg,
  252. scheduler: newGroupScheduler(cfg),
  253. sampleRate: rate,
  254. spb: spb,
  255. waveform: waveform,
  256. wfLen: wfLen,
  257. ring: make([]float64, ringSize),
  258. ringSize: ringSize,
  259. bitPos: bitsPerGroup,
  260. sampleCount: spb,
  261. outSampleIdx: ringSize - 1,
  262. carrierStep: 57000.0 / rate,
  263. SampleRate: rate,
  264. }
  265. enc.liveTA.Store(-1)
  266. enc.liveTP.Store(-1)
  267. return enc, nil
  268. }
  269. func (e *Encoder) Reset() {
  270. e.scheduler = newGroupScheduler(e.config)
  271. e.bitPos = bitsPerGroup; e.sampleCount = e.spb
  272. e.prevOutput = 0; e.curOutput = 0
  273. e.inSampleIdx = 0; e.outSampleIdx = e.ringSize - 1
  274. e.carrierPhase = 0
  275. for i := range e.ring { e.ring[i] = 0 }
  276. }
  277. // UpdateText hot-swaps PS and/or RT. Thread-safe — called from HTTP handlers,
  278. // applied at the next RDS group boundary by the DSP goroutine.
  279. //
  280. // Pass empty string to leave a field unchanged. To explicitly clear a field
  281. // (set PS to 8 spaces, or RT to empty), use ClearPS/ClearRT instead.
  282. func (e *Encoder) UpdateText(ps, rt string) {
  283. if ps != "" {
  284. e.livePS.Store(pendingText{val: normalizePS(ps), set: true})
  285. }
  286. if rt != "" {
  287. e.liveRT.Store(pendingText{val: normalizeRT(rt), set: true})
  288. }
  289. }
  290. // ClearPS resets the Program Service name to 8 spaces at the next group boundary.
  291. func (e *Encoder) ClearPS() {
  292. e.livePS.Store(pendingText{val: normalizePS(""), set: true})
  293. }
  294. // ClearRT resets RadioText to an empty string at the next group boundary.
  295. // Per RDS spec, an empty RT causes receivers to clear their display.
  296. func (e *Encoder) ClearRT() {
  297. e.liveRT.Store(pendingText{val: "", set: true})
  298. }
  299. // UpdateTA sets the Traffic Announcement flag live. Thread-safe.
  300. // When TA goes true, receivers with TP-seek will interrupt CD playback.
  301. func (e *Encoder) UpdateTA(ta bool) {
  302. if ta {
  303. e.liveTA.Store(1)
  304. } else {
  305. e.liveTA.Store(0)
  306. }
  307. }
  308. // UpdateTP sets the Traffic Program flag live. Thread-safe.
  309. func (e *Encoder) UpdateTP(tp bool) {
  310. if tp {
  311. e.liveTP.Store(1)
  312. } else {
  313. e.liveTP.Store(0)
  314. }
  315. }
  316. // CurrentText returns the currently active PS and RT from the encoder scheduler.
  317. // It reflects the last text applied at an RDS group boundary.
  318. func (e *Encoder) CurrentText() (ps, rt string) {
  319. return e.scheduler.cfg.PS, e.scheduler.cfg.RT
  320. }
  321. // NextSample returns the next RDS subcarrier sample at the configured rate.
  322. // Uses the internal free-running 57 kHz carrier. Prefer NextSampleWithCarrier
  323. // for phase-locked operation in a stereo MPX chain.
  324. func (e *Encoder) NextSample() float64 {
  325. carrier := math.Sin(2 * math.Pi * e.carrierPhase)
  326. e.carrierPhase += e.carrierStep
  327. if e.carrierPhase >= 1.0 { e.carrierPhase -= 1.0 }
  328. return e.NextSampleWithCarrier(carrier)
  329. }
  330. // NextSampleWithCarrier returns the next RDS sample modulated onto the
  331. // supplied carrier value. The caller must provide sin(3 × pilotPhase × 2π)
  332. // so that the 57 kHz RDS carrier is phase-locked to the 19 kHz pilot.
  333. func (e *Encoder) NextSampleWithCarrier(carrier float64) float64 {
  334. if e.sampleCount >= e.spb {
  335. if e.bitPos >= bitsPerGroup {
  336. // Apply live text updates at group boundaries (~88ms at 228kHz).
  337. // Atomics are consumed (cleared) after reading to prevent
  338. // re-applying the same text every group and toggling A/B flag.
  339. if pt, ok := e.livePS.Load().(pendingText); ok && pt.set {
  340. e.scheduler.cfg.PS = pt.val
  341. e.livePS.Store(pendingText{}) // consumed
  342. }
  343. if pt, ok := e.liveRT.Load().(pendingText); ok && pt.set {
  344. e.scheduler.cfg.RT = pt.val
  345. e.scheduler.rtIdx = 0 // restart RT transmission for new text
  346. e.scheduler.rtABFlag = !e.scheduler.rtABFlag // toggle A/B per RDS spec
  347. e.scheduler.refreshRTPlus() // re-parse RT+ tags
  348. e.liveRT.Store(pendingText{}) // consumed
  349. }
  350. // Live TA/TP flags (no restart needed — applied immediately)
  351. if v := e.liveTA.Swap(-1); v >= 0 {
  352. e.scheduler.cfg.TA = v == 1
  353. }
  354. if v := e.liveTP.Swap(-1); v >= 0 {
  355. e.scheduler.cfg.TP = v == 1
  356. }
  357. e.getRDSGroup()
  358. e.bitPos = 0
  359. }
  360. // Differential encoding (PiFmRds-exact)
  361. curBit := e.bitBuffer[e.bitPos]
  362. e.prevOutput = e.curOutput
  363. e.curOutput = e.prevOutput ^ curBit
  364. inverting := (e.curOutput == 1)
  365. // Overlap-add waveform
  366. idx := e.inSampleIdx
  367. for j := 0; j < e.wfLen; j++ {
  368. val := e.waveform[j]
  369. if inverting { val = -val }
  370. e.ring[idx] += val
  371. idx++; if idx >= e.ringSize { idx = 0 }
  372. }
  373. e.inSampleIdx += e.spb
  374. if e.inSampleIdx >= e.ringSize { e.inSampleIdx -= e.ringSize }
  375. e.bitPos++
  376. e.sampleCount = 0
  377. }
  378. // Read envelope from ring buffer
  379. envelope := e.ring[e.outSampleIdx]
  380. e.ring[e.outSampleIdx] = 0
  381. e.outSampleIdx++; if e.outSampleIdx >= e.ringSize { e.outSampleIdx = 0 }
  382. e.sampleCount++
  383. return envelope * carrier
  384. }
  385. // NextSample228k is an alias for backward compat
  386. func (e *Encoder) NextSample228k() float64 { return e.NextSample() }
  387. func (e *Encoder) Generate(n int) []float64 {
  388. out := make([]float64, n); for i := range out { out[i] = e.NextSample() }; return out
  389. }
  390. func (e *Encoder) Symbol() float64 {
  391. // Populate the bit buffer on first call (bitPos starts at bitsPerGroup
  392. // after NewEncoder/Reset, so the guard below would return -1 immediately
  393. // without this bootstrap step).
  394. if e.bitPos >= bitsPerGroup {
  395. e.getRDSGroup()
  396. e.bitPos = 0
  397. }
  398. sym := 1.0
  399. if e.bitBuffer[e.bitPos] == 0 {
  400. sym = -1.0
  401. }
  402. e.sampleCount++
  403. if e.sampleCount >= e.spb {
  404. e.sampleCount = 0
  405. e.bitPos++
  406. if e.bitPos >= bitsPerGroup {
  407. e.getRDSGroup()
  408. e.bitPos = 0
  409. }
  410. }
  411. return sym
  412. }
  413. func (e *Encoder) getRDSGroup() {
  414. group := e.scheduler.NextGroup(); pos := 0
  415. for blk, off := range [4]byte{'A', 'B', 'C', 'D'} {
  416. encoded := encodeBlock(group[blk], off)
  417. for bit := bitsPerBlock - 1; bit >= 0; bit-- {
  418. e.bitBuffer[pos] = int((encoded >> uint(bit)) & 1); pos++
  419. }
  420. }
  421. }
  422. // refWaveform — exact PiFmRds waveform_biphase (576 samples at 228 kHz)
  423. var refWaveform = [576]float64{
  424. 2.532651330219518743e-03, 2.555044910373570170e-03, 2.566671021257086772e-03, 2.567238549701184643e-03,
  425. 2.556496746672830885e-03, 2.534237165729987841e-03, 2.500295472534516759e-03, 2.454553115509106563e-03,
  426. 2.396938848057333059e-03, 2.327430093141364103e-03, 2.246054141429317842e-03, 2.152889174683249481e-03,
  427. 2.048065106558019741e-03, 1.931764233519830953e-03, 1.804221689169753116e-03, 1.665725695871127275e-03,
  428. 1.516617608227482320e-03, 1.357291743639731877e-03, 1.188194995883951532e-03, 1.009826228393920439e-03,
  429. 8.227354447016149448e-04, 6.275227342843667493e-04, 4.248369928834821877e-04, 2.153744171968115500e-04,
  430. -1.232252981576898894e-07, -2.208705497650993482e-04, -4.460407281680368592e-04, -6.747678807736505729e-04,
  431. -9.061496807071534867e-04, -1.139250166374730904e-03, -1.373102755669571148e-03, -1.606713454985107814e-03,
  432. -1.839064255174424622e-03, -2.069116705719896768e-03, -2.295815657515722953e-03, -2.518093163822523149e-03,
  433. -2.734872528130168675e-03, -2.945072486864876073e-03, -3.147611514104867864e-03, -3.341412234726898710e-03,
  434. -3.525405931697330516e-03, -3.698537132549940647e-03, -3.859768259460998226e-03, -4.008084326742814528e-03,
  435. -4.142497669033530158e-03, -4.262052682966127777e-03, -4.365830564655405997e-03, -4.452954024951411884e-03,
  436. -4.522591964073326663e-03, -4.573964086961633882e-03, -4.606345440470235343e-03, -4.619070853366329284e-03,
  437. -4.611539260015793187e-03, -4.583217888607013166e-03, -4.533646294807957243e-03, -4.462440221861094410e-03,
  438. -4.369295268298792508e-03, -4.253990344709691375e-03, -4.116390901303888447e-03, -3.956451908412099601e-03,
  439. -3.774220572511344761e-03, -3.569838770897127041e-03, -3.343545188717922216e-03, -3.095677142753055708e-03,
  440. -2.826672077047463587e-03, -2.537068716315400187e-03, -2.227507863888385838e-03, -1.898732831910291503e-03,
  441. -1.551589492469313079e-03, -1.187025939403796478e-03, -8.060917516227311674e-04, -4.099368499382796552e-04,
  442. 1.900593832358028364e-07, 4.229434598897815903e-04, 8.568834232677739271e-04, 1.300478433616307234e-03,
  443. 1.752108639186909398e-03, 2.210069531690153112e-03, 2.672576051828062533e-03, 3.137767118244720512e-03,
  444. 3.603710575596331869e-03, 4.068408555938784511e-03, 4.529803246113349099e-03, 4.985783052286746689e-03,
  445. 5.434189151275972511e-03, 5.872822416766181226e-03, 6.299450707012693891e-03, 6.711816499117106809e-03,
  446. 7.107644853482626354e-03, 7.484651690592414135e-03, 7.840552360821295350e-03, 8.173070486592225875e-03,
  447. 8.479947054827158270e-03, 8.758949736324453048e-03, 9.007882407426009638e-03, 9.224594848121719579e-03,
  448. 9.406992589581098657e-03, 9.553046883008396370e-03, 9.660804760689966145e-03, 9.728399159148424027e-03,
  449. 9.754059073439845171e-03, 9.736119710831808022e-03, 9.673032611387005070e-03, 9.563375702351037400e-03,
  450. 9.405863252709357331e-03, 9.199355693838612638e-03, 8.942869271836061465e-03, 8.635585496870153838e-03,
  451. 8.276860354756325477e-03, 7.866233245929400361e-03, 7.403435617058454557e-03, 6.888399250731210011e-03,
  452. 6.321264178928198696e-03, 5.702386186409919011e-03, 5.032343870653735625e-03, 4.311945225603512621e-03,
  453. 3.542233717233159249e-03, 2.724493819771388933e-03, 1.860255982396226328e-03, 9.513009972738021430e-04,
  454. -3.362590087872507610e-07, -9.923637372837323424e-04, -2.022229806201048148e-03, -3.087121544982383836e-03,
  455. -4.183963760744797630e-03, -5.309418750929982035e-03, -6.459886829603163697e-03, -7.631507634530486361e-03,
  456. -8.820162230001177273e-03, -1.002147601834123269e-02, -1.123082247097366773e-02, -1.244332768771695338e-02,
  457. -1.365387579078745396e-02, -1.485711515769077770e-02, -1.604746549484995649e-02, -1.721912575143924595e-02,
  458. -1.836608287047301891e-02, -1.948212137174597930e-02, -2.056083375874448449e-02, -2.159563173915068912e-02,
  459. -2.257975824605283968e-02, -2.350630024446240945e-02, -2.436820230522675906e-02, -2.515828092592677437e-02,
  460. -2.586923957586502801e-02, -2.649368443979239693e-02, -2.702414083259563338e-02, -2.745307025478293042e-02,
  461. -2.777288805626721910e-02, -2.797598167366384739e-02, -2.805472940409954943e-02, -2.800151967637884431e-02,
  462. -2.780877077828078359e-02, -2.746895099676937430e-02, -2.697459912600155829e-02, -2.631834529621684959e-02,
  463. -2.549293207489373297e-02, -2.449123578997222314e-02, -2.330628802347053594e-02, -2.193129722247495056e-02,
  464. -2.035967037326144244e-02, -1.858503468321714980e-02, -1.660125921427981280e-02, -1.440247641080375819e-02,
  465. -1.198310346409471074e-02, -9.337863455345842695e-03, -6.461806218342813941e-03, -3.350328863101498331e-03,
  466. 8.040984433930472399e-07, 3.595441083468180719e-03, 7.437024284502863521e-03, 1.152857108893870150e-02,
  467. 1.587265612925233688e-02, 2.047139402062919666e-02, 2.532642284173815955e-02, 3.043888841331177791e-02,
  468. 3.580942942793266526e-02, 4.143816348300550373e-02, 4.732467406731786369e-02, 5.346799854986208217e-02,
  469. 5.986661721770201311e-02, 6.651844340763700403e-02, 7.342081477423043068e-02, 8.057048573445227402e-02,
  470. 8.796362112672609368e-02, 9.559579111958180220e-02, 1.034619674024025021e-01, 1.115565206879204074e-01,
  471. 1.198732195531727329e-01, 1.284052306425759737e-01, 1.371451202536290992e-01, 1.460848573225170255e-01,
  472. 1.552158178235605868e-01, 1.645287905930657713e-01, 1.740139845846588318e-01, 1.836610375596755829e-01,
  473. 1.934590262126028026e-01, 2.033964777279658187e-01, 2.134613827614141035e-01, 2.236412098341045707e-01,
  474. 2.339229211258132823e-01, 2.442929896485369901e-01, 2.547374177786905780e-01, 2.652417571223665282e-01,
  475. 2.757911296845135252e-01, 2.863702503093192853e-01, 2.969634503555686478e-01, 3.075547025672780710e-01,
  476. 3.181276470965210823e-01, 3.286656186320493500e-01, 3.391516745840755798e-01, 3.495686242724773130e-01,
  477. 3.598990590626389707e-01, 3.701253833902611312e-01, 3.802298466136770361e-01, 3.901945756295767120e-01,
  478. 4.000016081911345056e-01, 4.096329268202659746e-01, 4.190704933607786176e-01, 4.282962839026540069e-01,
  479. 4.372923241989370990e-01, 4.460407253805190875e-01, 4.545237199298762798e-01, 4.627236978285061975e-01,
  480. 4.706232427973597865e-01, 4.782051685485750880e-01, 4.854525549661181105e-01, 4.923487841323866965e-01,
  481. 4.988775761175122669e-01, 5.050230244479789743e-01, 5.107696311712632831e-01, 5.161023414335079718e-01,
  482. 5.210065774877549183e-01, 5.254682720509856741e-01, 5.294739009291574705e-01, 5.330105148305670504e-01,
  483. 5.360657702892279719e-01, 5.386279596215074461e-01, 5.406860398410284763e-01, 5.422296604588032753e-01,
  484. 5.432491900977250987e-01, 5.437357418528805386e-01, 5.436811973316860724e-01, 5.430782293105560488e-01,
  485. 5.419203229476984296e-01, 5.402017954946758405e-01, 5.379178144525937899e-01, 5.350644141221254646e-01,
  486. 5.316385105000952516e-01, 5.276379144789866693e-01, 5.230613433094983833e-01, 5.179084302901690862e-01,
  487. 5.121797326520726168e-01, 5.058767376106826363e-01, 4.990018665611814508e-01, 4.915584773977406674e-01,
  488. 4.835508649416218607e-01, 4.749842594673260865e-01, 4.658648233204350508e-01, 4.561996456252422338e-01,
  489. 4.459967350847497403e-01, 4.352650108800791839e-01, 4.240142916808554152e-01, 4.122552827825399224e-01,
  490. 3.999995613968218566e-01, 3.872595600805870397e-01, 3.740485484506272384e-01, 3.603806130210642222e-01,
  491. 3.462706353977916263e-01, 3.317342687539049928e-01, 3.167879126713797899e-01, 3.014486863933045213e-01,
  492. 2.857344005404113818e-01, 2.696635273493745433e-01, 2.532551694939167986e-01, 2.365290275532226649e-01,
  493. 2.195053661954201318e-01, 2.022049791470396651e-01, 1.846491530223047517e-01, 1.668596300888892936e-01,
  494. 1.488585700493792463e-01, 1.306685109200720063e-01, 1.123123290909592703e-01, 9.381319865274144465e-02,
  495. 7.519455007851447159e-02, 5.648002834935082067e-02, 3.769345061436135680e-02, 1.885876347696378158e-02,
  496. 0.000000000000000000e+00, -1.885876347696378158e-02, -3.769345061436135680e-02, -5.648002834935082067e-02,
  497. -7.519455007851447159e-02, -9.381319865274144465e-02, -1.123123290909592703e-01, -1.306685109200720063e-01,
  498. -1.488585700493792463e-01, -1.668596300888892936e-01, -1.846491530223047517e-01, -2.022049791470396651e-01,
  499. -2.195053661954201318e-01, -2.365290275532226649e-01, -2.532551694939167986e-01, -2.696635273493745433e-01,
  500. -2.857344005404113818e-01, -3.014486863933045213e-01, -3.167879126713797899e-01, -3.317342687539049928e-01,
  501. -3.462706353977916263e-01, -3.603806130210642222e-01, -3.740485484506272384e-01, -3.872595600805870397e-01,
  502. -3.999995613968218566e-01, -4.122552827825399224e-01, -4.240142916808554152e-01, -4.352650108800791839e-01,
  503. -4.459967350847497403e-01, -4.561996456252422338e-01, -4.658648233204350508e-01, -4.749842594673260865e-01,
  504. -4.835508649416218607e-01, -4.915584773977406674e-01, -4.990018665611814508e-01, -5.058767376106826363e-01,
  505. -5.121797326520726168e-01, -5.179084302901690862e-01, -5.230613433094983833e-01, -5.276379144789866693e-01,
  506. -5.316385105000952516e-01, -5.350644141221254646e-01, -5.379178144525937899e-01, -5.402017954946758405e-01,
  507. -5.419203229476984296e-01, -5.430782293105560488e-01, -5.436811973316860724e-01, -5.437357418528805386e-01,
  508. -5.432491900977250987e-01, -5.422296604588032753e-01, -5.406860398410284763e-01, -5.386279596215074461e-01,
  509. -5.360657702892279719e-01, -5.330105148305670504e-01, -5.294739009291574705e-01, -5.254682720509856741e-01,
  510. -5.210065774877549183e-01, -5.161023414335079718e-01, -5.107696311712632831e-01, -5.050230244479789743e-01,
  511. -4.988775761175122669e-01, -4.923487841323866965e-01, -4.854525549661181105e-01, -4.782051685485750880e-01,
  512. -4.706232427973597865e-01, -4.627236978285061975e-01, -4.545237199298762798e-01, -4.460407253805190875e-01,
  513. -4.372923241989370990e-01, -4.282962839026540069e-01, -4.190704933607786176e-01, -4.096329268202659746e-01,
  514. -4.000016081911345056e-01, -3.901945756295767120e-01, -3.802298466136770361e-01, -3.701253833902611312e-01,
  515. -3.598990590626389707e-01, -3.495686242724773130e-01, -3.391516745840755798e-01, -3.286656186320493500e-01,
  516. -3.181276470965210823e-01, -3.075547025672780710e-01, -2.969634503555686478e-01, -2.863702503093192853e-01,
  517. -2.757911296845135252e-01, -2.652417571223665282e-01, -2.547374177786905780e-01, -2.442929896485369901e-01,
  518. -2.339229211258132823e-01, -2.236412098341045707e-01, -2.134613827614141035e-01, -2.033964777279658187e-01,
  519. -1.934590262126028026e-01, -1.836610375596755829e-01, -1.740139845846588318e-01, -1.645287905930657713e-01,
  520. -1.552158178235605868e-01, -1.460848573225170255e-01, -1.371451202536290992e-01, -1.284052306425759737e-01,
  521. -1.198732195531727329e-01, -1.115565206879204074e-01, -1.034619674024025021e-01, -9.559579111958180220e-02,
  522. -8.796362112672609368e-02, -8.057048573445227402e-02, -7.342081477423043068e-02, -6.651844340763700403e-02,
  523. -5.986661721770201311e-02, -5.346799854986208217e-02, -4.732467406731786369e-02, -4.143816348300550373e-02,
  524. -3.580942942793266526e-02, -3.043888841331177791e-02, -2.532642284173815955e-02, -2.047139402062919666e-02,
  525. -1.587265612925233688e-02, -1.152857108893870150e-02, -7.437024284502863521e-03, -3.595441083468180719e-03,
  526. -8.040984433930472399e-07, 3.350328863101498331e-03, 6.461806218342813941e-03, 9.337863455345842695e-03,
  527. 1.198310346409471074e-02, 1.440247641080375819e-02, 1.660125921427981280e-02, 1.858503468321714980e-02,
  528. 2.035967037326144244e-02, 2.193129722247495056e-02, 2.330628802347053594e-02, 2.449123578997222314e-02,
  529. 2.549293207489373297e-02, 2.631834529621684959e-02, 2.697459912600155829e-02, 2.746895099676937430e-02,
  530. 2.780877077828078359e-02, 2.800151967637884431e-02, 2.805472940409954943e-02, 2.797598167366384739e-02,
  531. 2.777288805626721910e-02, 2.745307025478293042e-02, 2.702414083259563338e-02, 2.649368443979239693e-02,
  532. 2.586923957586502801e-02, 2.515828092592677437e-02, 2.436820230522675906e-02, 2.350630024446240945e-02,
  533. 2.257975824605283968e-02, 2.159563173915068912e-02, 2.056083375874448449e-02, 1.948212137174597930e-02,
  534. 1.836608287047301891e-02, 1.721912575143924595e-02, 1.604746549484995649e-02, 1.485711515769077770e-02,
  535. 1.365387579078745396e-02, 1.244332768771695338e-02, 1.123082247097366773e-02, 1.002147601834123269e-02,
  536. 8.820162230001177273e-03, 7.631507634530486361e-03, 6.459886829603163697e-03, 5.309418750929982035e-03,
  537. 4.183963760744797630e-03, 3.087121544982383836e-03, 2.022229806201048148e-03, 9.923637372837323424e-04,
  538. 3.362590087872507610e-07, -9.513009972738021430e-04, -1.860255982396226328e-03, -2.724493819771388933e-03,
  539. -3.542233717233159249e-03, -4.311945225603512621e-03, -5.032343870653735625e-03, -5.702386186409919011e-03,
  540. -6.321264178928198696e-03, -6.888399250731210011e-03, -7.403435617058454557e-03, -7.866233245929400361e-03,
  541. -8.276860354756325477e-03, -8.635585496870153838e-03, -8.942869271836061465e-03, -9.199355693838612638e-03,
  542. -9.405863252709357331e-03, -9.563375702351037400e-03, -9.673032611387005070e-03, -9.736119710831808022e-03,
  543. -9.754059073439845171e-03, -9.728399159148424027e-03, -9.660804760689966145e-03, -9.553046883008396370e-03,
  544. -9.406992589581098657e-03, -9.224594848121719579e-03, -9.007882407426009638e-03, -8.758949736324453048e-03,
  545. -8.479947054827158270e-03, -8.173070486592225875e-03, -7.840552360821295350e-03, -7.484651690592414135e-03,
  546. -7.107644853482626354e-03, -6.711816499117106809e-03, -6.299450707012693891e-03, -5.872822416766181226e-03,
  547. -5.434189151275972511e-03, -4.985783052286746689e-03, -4.529803246113349099e-03, -4.068408555938784511e-03,
  548. -3.603710575596331869e-03, -3.137767118244720512e-03, -2.672576051828062533e-03, -2.210069531690153112e-03,
  549. -1.752108639186909398e-03, -1.300478433616307234e-03, -8.568834232677739271e-04, -4.229434598897815903e-04,
  550. -1.900593832358028364e-07, 4.099368499382796552e-04, 8.060917516227311674e-04, 1.187025939403796478e-03,
  551. 1.551589492469313079e-03, 1.898732831910291503e-03, 2.227507863888385838e-03, 2.537068716315400187e-03,
  552. 2.826672077047463587e-03, 3.095677142753055708e-03, 3.343545188717922216e-03, 3.569838770897127041e-03,
  553. 3.774220572511344761e-03, 3.956451908412099601e-03, 4.116390901303888447e-03, 4.253990344709691375e-03,
  554. 4.369295268298792508e-03, 4.462440221861094410e-03, 4.533646294807957243e-03, 4.583217888607013166e-03,
  555. 4.611539260015793187e-03, 4.619070853366329284e-03, 4.606345440470235343e-03, 4.573964086961633882e-03,
  556. 4.522591964073326663e-03, 4.452954024951411884e-03, 4.365830564655405997e-03, 4.262052682966127777e-03,
  557. 4.142497669033530158e-03, 4.008084326742814528e-03, 3.859768259460998226e-03, 3.698537132549940647e-03,
  558. 3.525405931697330516e-03, 3.341412234726898710e-03, 3.147611514104867864e-03, 2.945072486864876073e-03,
  559. 2.734872528130168675e-03, 2.518093163822523149e-03, 2.295815657515722953e-03, 2.069116705719896768e-03,
  560. 1.839064255174424622e-03, 1.606713454985107814e-03, 1.373102755669571148e-03, 1.139250166374730904e-03,
  561. 9.061496807071534867e-04, 6.747678807736505729e-04, 4.460407281680368592e-04, 2.208705497650993482e-04,
  562. 1.232252981576898894e-07, -2.153744171968115500e-04, -4.248369928834821877e-04, -6.275227342843667493e-04,
  563. -8.227354447016149448e-04, -1.009826228393920439e-03, -1.188194995883951532e-03, -1.357291743639731877e-03,
  564. -1.516617608227482320e-03, -1.665725695871127275e-03, -1.804221689169753116e-03, -1.931764233519830953e-03,
  565. -2.048065106558019741e-03, -2.152889174683249481e-03, -2.246054141429317842e-03, -2.327430093141364103e-03,
  566. -2.396938848057333059e-03, -2.454553115509106563e-03, -2.500295472534516759e-03, -2.534237165729987841e-03,
  567. -2.556496746672830885e-03, -2.567238549701184643e-03, -2.566671021257086772e-03, -2.555044910373570170e-03,
  568. }