我正在编写代码来控制UDP上的外部LED,并且需要保持尽可能恒定的帧速率(例如60 to )。太多的抖动会看上去很糟糕。我用time.NewTicker编写了一个简单的测试,结果并不理想。我想知道是否有一种更精确的间隔来执行代码的不同方法。这个测试是在macOS上运行的,但是也需要在Windows和Linux上运行。至于它的价值,它需要同步到音频,所以可能有一个音频代码API在每个操作系统上,它有可能同步吗?
package main
import (
"encoding/csv"
"fmt"
"log"
"os"
"strconv"
"time"
)
var f *os.File
var testTimeSeconds = 30
func appendToCsv(t time.Time) {
w := csv.NewWriter(f)
defer w.Flush()
records := []string{strconv.FormatInt(t.UnixMicro(), 10)}
w.Write(records)
}
func init() {
var err error
f, err = os.Create("newTicker.csv")
if err != nil {
log.Fatal(err)
}
w := csv.NewWriter(f)
defer w.Flush()
records := []string{"timestamps"}
w.Write(records)
}
func main() {
usPerFrame := 16666
ticker := time.NewTicker(time.Duration(usPerFrame) * time.Microsecond)
defer ticker.Stop()
done := make(chan bool)
go func() {
time.Sleep(time.Duration(testTimeSeconds) * time.Second)
done <- true
}()
for {
select {
case <-done:
fmt.Println("Done!")
return
case t := <-ticker.C:
appendToCsv(t)
}
}
}

更新:我运行了另一个测试,将第一个方法与@jochen的答案中的方法进行比较,但仍然不太准确。

发布于 2022-01-06 15:47:54
一个想法是只使用time.Sleep()而不是滴答器。这使信道发送/接收脱离循环,并可能导致更精确的定时。要做到这一点,您可以在一个单独的goroutine中运行如下函数:
func ticker(step time.Duration, done <-chan struct{}) {
next := time.Now().Add(step)
for {
time.Sleep(time.Until(next))
appendToCsv(time.Now())
select { // check whether `done` was closed
case <-done:
return
default:
// pass
}
next = next.Add(step)
}
}https://stackoverflow.com/questions/70594795
复制相似问题