and*_*n22 4 audio macos cocoa objective-c
我正在尝试编写一个应用程序,可以安排一些(大多数是微小的)音频文件的定时播放.问题:它需要定时准确的音乐.这些声音将不会播放频繁(它不是,例如采样器或鼓包),但他们将需要绝对精确地放置.这个问题分为两部分:
我该如何组织时间安排?我听说NSTimer不准确,或者至少不可靠?我应该以某种方式使用MIDI吗?还是一个紧凑的循环和一些具有高分辨率的时间获取功能?
一旦我完成了计时,我知道何时播放我的声音......我该怎么玩它们?是否NSSound快速可靠,足以保持所需的准确度?
Rob*_*Rob 19
有关音乐质量音频的一般信息
这是需要从山顶到任何制作iOS乐器的人的呼喊:
如果您正在使用MIDI,那么您将在这些问题上摔跤得更少(声音渲染器必须处理大部分问题),但所有乐器都必须处理这些要求:
音乐家期待什么
第一件事是使AudioQueue使用的缓冲区尽可能小.iPad上的默认值是1024个样本,这是一个痛苦的长23毫秒.当您想播放具有该缓冲区大小的声音时,即使计算机速度非常快,响应也需要0到23毫秒.如果缓冲区长度超过256个样本,那么您将无法使用它完成大量实际工具.在实践中,还要在其上添加多达30ms的开销(从触摸响应到图形等).
// 256 / ( 44.1khz) ~ 5.8ms
float latency = 0.005; //in seconds gives a 256 sample buffer
//on an infinitely fast computer, we'd make sure we got a buffer of size 1.
// but it will take too much CPU. :-) some latency is inevitable.
OSStatus status = AudioSessionSetProperty(
kAudioSessionProperty_PreferredHardwareIOBufferDuration,
sizeof(latency),&latency
);
Run Code Online (Sandbox Code Playgroud)
延迟 - 专业音乐家希望手指到耳朵的延迟大约为8毫秒.对我来说,这似乎是iPad的幻想,但这就是目标.只是为了快速播放,想想每分钟120(四分音符)的节拍,并且目标是16倍音符的准确度等等.即使不能快速播放,音乐家也会因高延迟而烦恼,并且会停止使用超过100毫秒的其他伟大乐器( !!!!)任何超过30毫秒的东西,他们不幸地进入专业工具并将录制的声音时间移动几毫秒以修复你的搞砸了.商店里更好的应用程序大约需要30ms.一些非常好的在大约50ms仍然可以.
通过将麦克风放在ipad表面的顶部并将其运行到混音器的左声道来测量延迟.然后将ipad运行到右侧通道.以立体声录制声音.然后将其放入声音编辑器中,以便查看立体声波形.您可以查看手指触摸触摸屏的时间,然后查看电子声音开始的时间.那个距离是延迟.其中的差异是抖动.
抖动 - 抖动是延迟的变化.抖动超过几毫秒会使节奏听起来错误.我到了大约5ms.它与AudioQueue缓冲区大小直接相关.1024个样本缓冲区的示例:如果您在缓冲区的某个随机时间点按下您的手指,那么当您需要响应时,期望是在样本512处.因此它最小值从0到1024毫秒不等,但平均为512 ...等待缓冲区完成平均情况12毫秒,然后再从其他来源添加延迟.
触摸延迟 - 最重要的是touchesBegan尽快得到服务.即使那意味着touchesMoved,touchesEnded,touchesCancelled需要更长的时间.因此,您可能最终在工作负载中存在一些不对称性以实现此目的.起初这对我来说是一个令人困惑的启示,因为分析器告诉我没有多少时间花在touchesBegan上,但是在触摸结束之前推迟一些工作会有很大的不同.
OpenGL - 你至少应该考虑它.我不相信直接使用UIKit并在我的主应用程序上使用OpenGL时很容易达到这些延迟目标.
实时时钟-对于事情是不是真的乐器,但有一个像鼓机节拍的严格同步的要求,你可以跟踪什么时候它确实是,使样本追踪到时钟并假设有漂移时你不是在看钟.但是我已经厌倦了在我的旧MIDI乐器上打这场战斗......如果你有MIDI,那么MIDI会发出时钟信号; 它可能是将两个电子仪器同步的唯一方法.
声音跳过 - 您的应用程序所做的一切都与CPU时间竞争.鉴于您已经使您的声音引擎尽可能高效,使缓冲区更小使用更多的CPU.您可能需要换一点延迟才能获得更好的连续性.如果声音引擎会有更多的循环回复,我有偏见,减少眼睛糖果的废话,并在你的手段内生活.
计时器.使用CADisplayLink.我没有多想过.这就是我所拥有的.
Run Code Online (Sandbox Code Playgroud)- (NSInteger)animationFrameInterval { return animationFrameInterval; } - (void)setAnimationFrameInterval:(NSInteger)frameInterval { if (frameInterval >= 16) { animationFrameInterval = frameInterval; if (animating) { [self stopAnimation]; [self startAnimation]; } } } - (void)startAnimation { if (!animating) { displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView:)]; [displayLink setFrameInterval:animationFrameInterval]; [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; animating = TRUE; } } - (void)stopAnimation { if (animating) { [displayLink invalidate]; displayLink = nil; animating = FALSE; } }
我没有把这些东西搞定.在解决这些问题之前,请不要在商店中放置"乐器".在谈论iPad/iPhone应用程序时,Jordan Rudess,Leon Gruenbaum,Chris Dudley和其他专业音乐家过去经常提起这些问题.情况似乎有所改善,但我不认为大多数开发人员都知道真正的音乐家所期望的数字.
我怀疑你能否使用NSTimer/NSSound方法实现样本精确的音频定时.
我认为你最好的选择是直接使用Core Audio.不幸的是,学习曲线有点陡峭,因为它是一个没有Cocoa记录的C API.
开始的最简单方法是AudioQueue-它应该提供播放音频所需的所有功能,并提供计时功能.
另一种选择是使用较低级别的AUGraph和音频单元 - 一个带有两个音频单元的简单AUGraph-连接到默认输出单元的AudioFilePlayer(或ScheduledSoundPlayer)也可以正常工作.
| 归档时间: |
|
| 查看次数: |
2151 次 |
| 最近记录: |