我正在尝试在 AudioUnit Mixer 的回调中使用 audioUnit Effect 执行 AudioUnitRender 但没有运气。
我的混音器进入 RemoteIO 单元并在其回调中处理 AudioData(来自文件)。工作得很好。
然后,我在我的图表中添加了一个 AudioUnit 效果节点(一个混响)并将其链接到一个 AudioUnit。我的效果节点未连接到图中的任何内容。
AudioComponentDescription auEffectDescription;
auEffectDescription.componentType = kAudioUnitType_Effect;
auEffectDescription.componentSubType = kAudioUnitSubType_Reverb2;
auEffectDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
auEffectDescription.componentFlags = 0;
auEffectDescription.componentFlagsMask = 0;
我知道 AudioGraph (zerokidz.com/audiograph) 示例中描述的 StreamFormat 问题,并按照 AudioGraph 中的说明设置了我的效果单元的 StreamFormat。
所以我知道存在流格式兼容性问题(请参阅Bit-shifting audio samples from Float32 到 SInt16 导致严重剪辑)。我的 ASBD:
[AudioUnitEffect]------------------------------
[AudioUnitEffect] Sample Rate: 44100
[AudioUnitEffect] Format ID: lpcm
[AudioUnitEffect] Format Flags: 41
[AudioUnitEffect] Bytes per Packet: 4
[AudioUnitEffect] Frames per Packet: 1
[AudioUnitEffect] Bytes per Frame: 4
[AudioUnitEffect] Channels per Frame: 2
[AudioUnitEffect] Bits per Channel: 32
[AudioUnitEffect]------------------------------
[AudioUnitMixer]------------------------------
[AudioUnitMixer] Sample Rate: 44100
[AudioUnitMixer] Format ID: lpcm
[AudioUnitMixer] Format Flags: 3116
[AudioUnitMixer] Bytes per Packet: 4
[AudioUnitMixer] Frames per Packet: 1
[AudioUnitMixer] Bytes per Frame: 4
[AudioUnitMixer] Channels per Frame: 2
[AudioUnitMixer] Bits per Channel: 32
[AudioUnitMixer]------------------------------
我已经理解(如果我错了,请纠正我)我的效果在 Float32 中,而我的混音器使用 AudioUnitSampleType 类型(SInt32)。在效果上调用 AudioUnitRender 之前和之后,我尝试了各种转换数据缓冲区的方法。我试图将混音器的 ASBD 与 AudioUnit 效果匹配,它可以工作,但我得到了一些可怕的失真(如果效果使用 Float32 类型(我猜是在 [-1,+1] 之间?),这是正常的。
苹果文档说:
*Effect Units Stream 格式说明
在输入范围内,按如下方式管理流格式: - 如果输入由音频单元连接馈送,则它从该连接获取其流格式。- 如果输入由渲染回调函数提供,请在总线上设置完整的应用程序流格式。使用与回调提供的数据相同的流格式。在输出范围上,设置与输入相同的完整流格式。*
我发现这没什么帮助..
无论如何,必须有一种方法可以使用效果单元进行 AudioRenderRender。有人成功了吗?谢谢。
安德烈
我的混音器回调:
static OSStatus mainMixerCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
SoundEngine* se = (SoundEngine*)inRefCon;
// init buffers with zeros
memset((Byte *)ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
memset((Byte *)ioData->mBuffers[1].mData, 0, ioData->mBuffers[1].mDataByteSize);
// Render the Audio Track (works fine)
AudioUnitRender((AudioUnit)se.auTrack,ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
// Effect (fails when there. Error:-50)
AudioUnitRender((AudioUnit)se.auEffect, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
return noErr;
}