我有以下代码块,应该创建一个产生正弦波的AVAudioNode,但它会在标有 - [AUAudioUnitV2Bridge setOutputProvider:]的行上崩溃:无法识别的选择器发送到实例。< / p>
任何想法可能出错?
// TEST
AudioComponentDescription mixerDesc;
mixerDesc.componentType = kAudioUnitType_Generator;
mixerDesc.componentSubType = kAudioUnitSubType_ScheduledSoundPlayer;
mixerDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
mixerDesc.componentFlags = 0;
mixerDesc.componentFlagsMask = 0;
[AVAudioUnit instantiateWithComponentDescription:mixerDesc options:kAudioComponentInstantiation_LoadInProcess completionHandler:^(__kindof AVAudioUnit * _Nullable audioUnit, NSError * _Nullable error) {
NSLog(@"here");
// Crashes here
audioUnit.AUAudioUnit.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList *inputData)
{
const double amplitude = 0.2;
static double theta = 0.0;
double theta_increment = 2.0 * M_PI * 880.0 / 44100.0;
const int channel = 0;
Float32 *buffer = (Float32 *)inputData->mBuffers[channel].mData;
memset(inputData->mBuffers[channel].mData, 0, inputData->mBuffers[channel].mDataByteSize);
memset(inputData->mBuffers[1].mData, 0, inputData->mBuffers[1].mDataByteSize);
// Generate the samples
for (UInt32 frame = 0; frame < inputBusNumber; frame++)
{
buffer[frame] = sin(theta) * amplitude;
theta += theta_increment;
if (theta >= 2.0 * M_PI)
{
theta -= 2.0 * M_PI;
}
}
return noErr;
};
}];
更新
感觉像这样的东西是正确的方法,但唉,状态抛出错误,回调从未调用。:
AVAudioUnitGenerator *unit = [[AVAudioUnitGenerator alloc] init];
// TEST
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Generator;
desc.componentSubType = kAudioUnitSubType_ScheduledSoundPlayer;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
[AVAudioUnit instantiateWithComponentDescription:desc options:kAudioComponentInstantiation_LoadInProcess completionHandler:^(__kindof AVAudioUnit * _Nullable audioUnit, NSError * _Nullable error) {
NSLog(@"here");
self.audioNode = audioUnit;
OSStatus status;
AudioUnit *unit = audioUnit.audioUnit;
UInt32 numBuses = 1;
status = AudioUnitSetProperty(unit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 0, &numBuses, sizeof(UInt32));
NSLog(@"status: %d", status);
AURenderCallbackStruct rcbs;
rcbs.inputProc = callback2;
rcbs.inputProcRefCon = (__bridge void * _Nullable)(self);
status = AudioUnitSetProperty(unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Output, 0, &rcbs, sizeof(rcbs));
NSLog(@"status: %d", status);
}];
答案 0 :(得分:2)
错误消息的确切含义。在实例化您请求的audioUnit类型并确保AUAudioUnit不是nil之后,此代码使其明确:
if (![audioUnit.AUAudioUnit respondsToSelector:@selector(outputProvider)]) {
NSLog(@"selector method not found in this instance of an AUAudioUnit");
}
头文件并未声称绝对需要在所有音频单元中实现此方法。
稍后添加:如果您只想让代码合成AVAudioUnit的样本,并且不关心特定的API或代码结构,那么: 获取AVAudioUnit实例的AudioUnit属性;创建AURenderCallback函数;使用此C函数填写AURenderCallbackStruct;然后在AudioUnit上为kAudioUnitProperty_SetRenderCallback做一个AudioUnitSetProperty。即使没有outputProvider方法可用,这似乎也不会崩溃。