iOS:同时录制和播放的示例代码

15

我正在设计一个简单的多轨录音机的概念验证。

显然的起点是从文件A.caf播放到耳机,同时将麦克风输入录制到文件B.caf中。

这个问题--同时录制和播放音频--指出了我可以在三个级别上工作:

  • AVFoundation API(AVAudioPlayer + AVAudioRecorder)
  • 音频队列API
  • 音频单元API(RemoteIO)

哪个级别最好?显然,通用答案是在完成任务的最高级别上工作,也就是AVFoundation。

但是我接手这项工作是因为某人由于延迟问题而放弃了(他在文件之间得到了0.3秒的延迟),所以也许我需要在较低的级别上工作以避免这些问题?

此外,有哪些源代码可供启动?我一直在看SpeakHere示例(http://developer.apple.com/library/ios/#samplecode/SpeakHere/Introduction/Intro.html)。如果找不到更简单的东西,我将使用此代码。

但是,有没有人能推荐一些更简单/其他的东西?如果可以避免C++代码,我宁愿不使用。

是否有人知道一些使用AVFoundation完成此操作的公共代码?

编辑:AVFoundation示例在此处:http://www.iphoneam.com/blog/index.php?title=using-the-iphone-to-record-audio-a-guide&more=1&c=1&tb=1&pb=1

编辑(2):这里有一个外观更好的教程:使用AV Foundation框架创建基本的iPhone音频播放器

编辑(3):如何在iPhone上使用AVAudioRecorder录制音频?

3个回答

6
为避免延迟问题,你需要在比 AVFoundation 更低的层次上工作。请查看苹果公司提供的示例代码——Auriotouch。它使用了远程 I/O。

1
实际上,我使用AVFoundation确实完美地使其工作。您只需要确保在启动之前准备好所有内容。除此之外,您需要在播放器之后的70毫秒开始录制,这样它就可以很好地对齐。(这可能会因设备而异)。 - P i
2
好好知道。也许你应该回答自己的问题。 - Viraj

5

根据Viraj的建议,这里是答案。

是的,您可以使用AVFoundation来获得非常好的结果。首先需要注意的是,对于播放器和录音机,启动它们都是一个两步过程。

首先是准备工作。

然后再播放。

所以,先准备好一切,然后再播放。

这将使您的延迟降至约70毫秒。我通过录制节拍器的滴答声,然后将其通过扬声器播放并同时录制时测试了这一点。

第二次录制有明显的回声,我发现大约为70毫秒。我可以在Audacity中分析信号以获取精确的偏移量。

因此,为了将所有内容对齐,我只需在70.0/1000.0秒后使用performSelector:x withObject: y。

可能会有隐藏的陷阱,例如延迟可能因设备而异。甚至可能取决于设备活动。甚至可能在线程启动播放器和录音机之间被中断/重新调度。

但它有效,并且比混乱的音频队列/单元更整洁。


1
你如何“装载”它?能否解释一下你的意思? - Bjorn Roche
1
遗憾的是,目前我还没有找到正确的方法(至少我没有找到)。70毫秒的偏差对我来说太大了,而且由于今天有各种不同的设备,失步的差异也太大了。在iPhone 5s上,我得到了约66毫秒的结果,但在iPhone 6上,我得到了约40毫秒的结果。我注意到这篇文章是2011年的,你有没有找到更好的方法呢? - Sti

1
我曾经遇到这个问题,通过更改AudioSessionPreferredHardwareIOBufferDuration参数来解决。我现在只有6毫秒的延迟,对于我的应用程序已经足够好了。
请查看这个答案,其中有很好的解释。

当然,我现在的代码是用Xamarin写的,但我想用Swift或Objective-C也不难。看一下我在答案中提供的链接,里面有一个例子。另外,请确保在开始录音之前准备好你的录音机(我使用AVAudioRecorder和prepareToRecord)和播放器(我使用文件名创建了一个AVPlayer实例),以便它们以低延迟启动。此外,在激活音频会话时,请确保将类别设置为playAndRecord。在Xamarin中,代码如下:AVAudioSession.SharedInstance().SetPreferredIOBufferDuration(0.005, out error); - ernewston
我有一个名为AudioSessionHelper的类,其中有一个叫做ActivateMyAudioSesion的函数。在这个函数中,我设置了音频会话的类型,模式和首选IO缓冲区持续时间,然后将其激活。在开始第一次录制之前调用此函数(不要每次都调用它,因为这很耗费资源),或者可以在应用程序启动时调用它。希望对你有所帮助! - ernewston
参考这段代码,我无法在蓝牙扬声器中播放音频。在通话时,它只能在耳机(顶部)中播放。我想在通话时在蓝牙扬声器中播放音频。你能帮我吗?我尝试了很多链接和不同的方法,但是都没有成功。 - Ramkumar chintala
有延迟是可能的吗?如果可以,延迟多少才能播放? - Ramkumar chintala
很抱歉,我从未接触过蓝牙,无法在此处为您提供帮助。 - ernewston
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接