用于实时音频合成的C ++精确44100Hz时钟

时间:2018-01-25 17:14:02

标签: c++ multithreading audio midi

我目前正在使用我的Raspberry Pi及其内置UART输入编码MIDI合成器。

在某个时间点,为了实现MIDI输入的实时播放,我必须设置一种与OpenAL一起使用的环形缓冲区,这应该很简单,只需填写一个缓冲区,将其排队,等待另一个缓冲区可以自由填充。

我现在遇到的问题实际上是填充缓冲区。我想要一个44100Hz的采样率,所以CD质量。我的计划是运行一个时钟来调用每个tick的合成函数,并根据当前按下的键将一个样本写入内存,我通过监听note和note off事件在另一个线程中跟踪。

但是,我在这里注意到一个问题。睡了一段时间线程并不精确,线程保证在一段时间后醒来,但不是确切时间过去了,所以我真的不认为这是一个好的要走的路。

我是否可以使用某种类型的刻度线生成器,这对于音频合成来说足够精确?

我知道我可能在这里重新发明轮子,因为我可以抓住合成器并根据自己的需要调整,但我对整个过程感兴趣,所以这并不完全一个选项。

我确实有可能整个写一个样本到每个x的内存也不是一个好主意,但这是我最好的猜测,所以如果你有任何其他的建议,我&#39 ;一定要看看它。

2 个答案:

答案 0 :(得分:1)

您需要一个高性能计时器。

睡觉,因为你观察不准确。通常,实现将保证至少在指定的时间内休眠,但允许睡眠时间更长。

此外,典型的系统时钟不够高。

如果使用C ++ '11,则标配高性能时钟。见http://www.cplusplus.com/reference/chrono/high_resolution_clock/

这就是我要去的方式。如果由于某种原因你不能使用C ++'11,那么有选择。

Windows通过Kernel32.dll公开高性能时钟,后者提供以下功能: QueryPerformanceFrequency的 QueryPerformanceCounter的

Linux有sys / time.h,它给你gettimeofday 快速谷歌搜索gettimeofday可能会为您提供更好的选择。

在我的bitbucket上查看我的跨平台高性能计时器 https://bitbucket.org/akfreed/cppcrossplatform/src/e3f71e6d93de?at=default

现在你可以在一个紧凑的循环中轮询时间。

这是非常高的精度。在我的笔记本电脑上,没有什么特别的,(i3-5005U,双2GHz超线程)运行Windows,我的滴答时间为513纳米。这是一个以22.7微秒的间隔进行函数调用的充足时间。你甚至可以做几次原子指令和/或多次去主内存。

答案 1 :(得分:1)

除了已经给出的答案和评论之外,还要阅读Linux中的硬实时内容。特别是,阅读相对较新的SCHED_DEADLINE调度程序以及Ingo Molnar的实时补丁集,其中80%位于主流内核中。