首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >合成歌曲时音符之间的精确延迟

合成歌曲时音符之间的精确延迟
EN

Stack Overflow用户
提问于 2012-06-10 13:54:54
回答 3查看 1.3K关注 0票数 1

我正在编写C++代码,它同时播放数字音频(合成音乐)和MIDI音乐(使用RtMidi库)。数字化音乐将通过计算机的音频设备播放,但MIDI音乐可以通过外部合成器播放。我想播放一首同时使用数字化乐器和MIDI乐器的歌曲,我不确定有什么最佳方法来同步这两种音频流:

  • 不可能使用像Sleep()这样的函数,因为延迟时间是不均匀的,而且对我的需要来说太长了(大约是1毫秒)。如果在只请求1ms的情况下定期等待5ms,则生成的歌曲节奏将关闭,除非每次调用时都准确,否则速度将不均匀。
  • 计算放置在音频缓冲器中的样本数可以为数字音频提供超精确的音符之间的计时(一个样本的最小延迟时间--48 the处的0.02ms ),但这个时间不能用于MIDI。由于音频是缓冲的,所以音符是以脉冲方式合成的(一次尽可能快地填充一个音频缓冲区),因此这导致每次需要重新填充数字音频缓冲区时,在它们之间不加延迟地播放大量MIDI音符。
  • 播放现场MIDI数据没有时间信息,所以音符一发出就会播放。因此,音符不能安排在稍后的时间播放,所以我需要在正确的时间准确地发送MIDI事件。

目前,我使用的只是在Linux下才能工作的nanosleep(),而不是Windows --等待笔记之间的正确时间。这允许数字音频和MIDI数据保持同步,但是Nanos休眠()并不十分一致,因此产生的速度非常不均匀。

有谁能想出一种方法来为数字音频和MIDI数据保留准确的音符之间的时间?

EN

回答 3

Stack Overflow用户

发布于 2012-06-10 14:30:40

如果你愿意使用Boost,它有CPU精密定时器。如果不是,在Windows上有一些函数QueryPerformanceCounterQueryPerformanceFrequency,它们可以用于基于CPU的计时,这肯定适合您的所有需求。web上有大量的计时器类实现,其中一些在windows和*ix系统上都可以使用。

票数 2
EN

Stack Overflow用户

发布于 2012-06-11 14:51:21

第一个问题是,您需要知道有多少音频通过音频设备。如果您的延迟足够低,您可能可以根据您所推送的数据量进行猜测,但该延迟与回放之间的延迟是一个移动目标,因此您应该尝试从音频硬件中获取这些信息。这些信息是可用的,所以请使用它,因为从延迟度量的错误中得到的“抖动”可以以一种音乐上明显的方式影响同步。

如果您必须使用睡眠来计时,则有两个问题会使其睡眠时间更长: 1.优先级(如果另一个进程/线程具有更高的优先级,则如果计时器已用完,则该优先级将运行)和2.系统延迟(如果系统需要5毫秒来交换进程/线程,则可能会将其添加到所请求的延迟时间)。这类延迟在音乐上是相关的。大多数midi api都有一个“顺序器”api,它允许您预先对数据进行排队,以避免使用系统定时器。

您可能会发现这个文档很有用,即使您没有将port音频用于音频I/O。

acmc2003.pdf

票数 1
EN

Stack Overflow用户

发布于 2012-06-10 14:42:23

答案不在于小缓冲,而在于大缓冲。

让我们举一首3分钟的歌为例。

其中一个首先呈现数字部分,并用MIDI注释“标记”它。然后,一个人开始播放它,并在时机成熟时触发MIDI音符,可能会使用std::vector来保存一个有序列表。可以通过使用总时间偏移量来更改同步:

可怕的、不完整的,但希望是关于这个主题的示范性伪码:

代码语言:javascript
复制
start_digital_playing_thread();
int midi_time_sync = 10; // ms
if (time >= (midi_note[50]->time + midi_time_sync)) // play note
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10969254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档