gpt4 book ai didi

ios - AUSampler 音频丢失

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:46:42 26 4
gpt4 key购买 nike

我正在开发一个 iPad 应用程序,它使用 AUSampler AudioUnit 以及其他 AudioUnit 来播放音频。 AUSampler 从 SoundFont2 文件加载预设。

当一次演奏太多音符或演奏得太快时,音频开始短暂中断,然后完全中断。在从 SoundFont 重新加载预设之前,采样器将无法使用。这只发生在某些乐器上(特别是预设 88、90 和 94,在通用 MIDI 中分别是 Pad 1(新时代)、Pad 3(复音合成器)和 Pad 7(光环)

通过在 XCode 中打开 All Exceptions 断点,我可以看到当 AudioToolbox 尝试为正在播放的音符创建新的 VoiceZone 时会出现问题。但是,此异常在我的代码下方的调用堆栈中的某个较低位置被捕获,并且 AudioUnitRender 未返回任何错误。

我最好的猜测是“pad”乐器使用更长的样本,因此快速/联合演奏许多音符会比 AudioToolbox 占用更多的内存。

有没有人以前遇到过这个问题,如果遇到过,是否有办法避免音频丢失,或者至少检测到它们以便妥善处理?

一些细节:

  • SoundFont 约为 150 MB,包含许多符合通用 MIDI 的不同预设/乐器
  • AUSampler 位于效果单元链的头部,它连接到 AUMultiChannelMixer (me.masterMixerUnit)。 audioOutputCallback设置为RemoteIO单元输出元素的输入回调

回溯(在`AURemoteIO::IOThread 上):

* thread #14: tid = 0x3203, 0x368c8498 libc++abi.dylib`__cxa_throw, stop reason = breakpoint 1.2
frame #0: 0x368c8498 libc++abi.dylib`__cxa_throw
frame #1: 0x35d46a60 AudioToolbox`VoiceZone::operator new(unsigned long) + 340
frame #2: 0x35d46b6a AudioToolbox`VoiceZone::NewVoiceZone(SamplerNote*, ZoneState*, float, float, unsigned long) + 86
frame #3: 0x35d3f846 AudioToolbox`SamplerNote::Configure(InstrumentState*) + 1106
frame #4: 0x35d3ff2c AudioToolbox`non-virtual thunk to SamplerNote::Attack(MusicDeviceNoteParams const&) + 24
frame #5: 0x35d551ea AudioToolbox`SynthNote::AttackNote(SynthPartElement*, SynthGroupElement*, unsigned long, unsigned long long, unsigned long, MusicDeviceNoteParams const&) + 58
frame #6: 0x35d5485a AudioToolbox`SynthGroupElement::NoteOn(SynthNote*, SynthPartElement*, unsigned long, unsigned long, MusicDeviceNoteParams const&) + 70
frame #7: 0x35d3d220 AudioToolbox`SamplerElement::StartNote(SynthPartElement*, unsigned long, unsigned long, MusicDeviceNoteParams const&) + 344
frame #8: 0x35d3c4fa AudioToolbox`Sampler::RealTimeStartNote(SynthGroupElement*, unsigned long, unsigned long, MusicDeviceNoteParams const&) + 94
frame #9: 0x35d530a0 AudioToolbox`AUInstrumentBase::PerformEvents(AudioTimeStamp const&) + 164
frame #10: 0x35d5313c AudioToolbox`AUInstrumentBase::Render(unsigned long&, AudioTimeStamp const&, unsigned long) + 20
frame #11: 0x35d3c564 AudioToolbox`Sampler::Render(unsigned long&, AudioTimeStamp const&, unsigned long) + 68
frame #12: 0x35c2435a AudioToolbox`AUBase::DoRenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, AUOutputElement*, unsigned long, AudioBufferList&) + 210
frame #13: 0x35c24184 AudioToolbox`AUBase::DoRender(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long, AudioBufferList&) + 496
frame #14: 0x35c23f8a AudioToolbox`AUMethodRender(void*, unsigned long*, AudioTimeStamp const*, unsigned long, unsigned long, AudioBufferList*) + 50

... render methods of other AudioUnits in chain ...

frame #32: 0x00081aaa SoundBrush 2`audioOutputCallback + 194 at SoundEngine.mm:1375

在下面的回调中调用 AudioUnitRender 期间抛出异常:

static OSStatus audioOutputCallback(void                       *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
//get a reference to the SoundEngine
SoundEngine *me = (__bridge SoundEngine *)inRefCon;

// render the sound
OSStatus err = AudioUnitRender(me.masterMixerUnit,
ioActionFlags,
inTimeStamp,
kAudioUnitBus_Output,
inNumberFrames,
ioData);
if (err != noErr) NSLog(@"AudioUnitRender failed [%ld]", err);

// ... do some processing ...

return err;
}

最佳答案

如果在正常情况下音质很好,我猜丢失不是由您的 AU 链中的编程错误引起的,而是操作系统无法足够快地处理 block 。

检测音频丢失最简单的方法是在开始处理之前获取以微秒为单位的系统时间,然后在完成后再次测量。通过查看采样率和缓冲区大小,您应该能够确定您是否能够在给定的时间内交付样本。

如果你发现你确实有性能导致的丢失,你应该做的第一件事就是增加缓冲区大小。之后,您应该尝试以几种基本方式优化您的代码。通过 Instruments(即分析器)运行算法并寻找任何明显的瓶颈。避免在渲染回调内部分配对象;这会给系统带来额外的压力。

此外,我建议在台式计算机上运行处理代码,以确保问题确实是由 iPad 的性能引起的。

关于ios - AUSampler 音频丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13810937/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com