核心audio:文件播放呈现callback函数

我用kAudioUnitProperty_ScheduledFileIDs在我的应用程序中使用RemoteIOaudio单元进行audio播放。 audio文件是PCM格式。 我怎样才能实现这种情况下的渲染callback函数,所以我可以手动修改缓冲区样本?
这是我的代码:

 static AudioComponentInstance audioUnit; AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AudioComponent comp = AudioComponentFindNext(NULL, &desc); CheckError(AudioComponentInstanceNew(comp, &audioUnit), "error AudioComponentInstanceNew"); NSURL *playerFile = [[NSBundle mainBundle] URLForResource:@"short" withExtension:@"wav"]; AudioFileID audioFileID; CheckError(AudioFileOpenURL((__bridge CFURLRef)playerFile, kAudioFileReadPermission, 0, &audioFileID), "error AudioFileOpenURL"); // Determine file properties UInt64 packetCount; UInt32 size = sizeof(packetCount); CheckError(AudioFileGetProperty(audioFileID, kAudioFilePropertyAudioDataPacketCount, &size, &packetCount), "AudioFileGetProperty(kAudioFilePropertyAudioDataPacketCount)"); AudioStreamBasicDescription dataFormat; size = sizeof(dataFormat); CheckError(AudioFileGetProperty(audioFileID, kAudioFilePropertyDataFormat, &size, &dataFormat), "AudioFileGetProperty(kAudioFilePropertyDataFormat)"); // Assign the region to play ScheduledAudioFileRegion region; memset (&region.mTimeStamp, 0, sizeof(region.mTimeStamp)); region.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid; region.mTimeStamp.mSampleTime = 0; region.mCompletionProc = NULL; region.mCompletionProcUserData = NULL; region.mAudioFile = audioFileID; region.mLoopCount = 0; region.mStartFrame = 0; region.mFramesToPlay = (UInt32)packetCount * dataFormat.mFramesPerPacket; CheckError(AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0, &region, sizeof(region)), "AudioUnitSetProperty(kAudioUnitProperty_ScheduledFileRegion)"); // Prime the player by reading some frames from disk UInt32 defaultNumberOfFrames = 0; CheckError(AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ScheduledFilePrime, kAudioUnitScope_Global, 0, &defaultNumberOfFrames, sizeof(defaultNumberOfFrames)), "AudioUnitSetProperty(kAudioUnitProperty_ScheduledFilePrime)"); AURenderCallbackStruct callbackStruct; callbackStruct.inputProc = MyCallback; callbackStruct.inputProcRefCon = (__bridge void * _Nullable)(self); CheckError(AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackStruct, sizeof(callbackStruct)), "error AudioUnitSetProperty[kAudioUnitProperty_setRenderCallback]"); CheckError(AudioUnitInitialize(audioUnit), "error AudioUnitInitialize"); 

callback函数:

 static OSStatus MyCallback(void *inRefCon, AudioUnitRenderActionFlags *ioFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData){ printf("my callback"); return noErr; } 

audio单元按下button开始播放:

 - (IBAction)playSound:(id)sender { CheckError(AudioOutputUnitStart(audioUnit), "error AudioOutputUnitStart"); } 

在使用kAudioUnitErr_InvalidProperty (-10879)错误编译期间,此代码失败。 目标是修改从AudioFileID读取的缓冲区采样并将结果发送给扬声器。

看你如何才能熟悉核心audio,我build议你先让remoteIOcallback独立于你的文件播放器工作。 只要删除所有的文件播放器相关的代码,并试图让工作第一。

然后,一旦你有这个工作,继续join你的文件播放器。

至于我可以看到这是错误的,我认为你是audio文件服务API与audio单元混淆。 这个API用于将文件读取到您要手动input到remoteIO的缓冲区中,如果您想要使用此路由,请使用扩展audio文件服务API,这样做更容易。 kAudioUnitProperty_ScheduledFileRegion属性应该在文件播放器audio单元上调用。 为了得到其中的一个,你需要像remmoteIO一样创build它,除了AudioComponentDescription的componentSubType和componentType分别是kAudioUnitSubType_AudioFilePlayerkAudioUnitType_Generator 。 然后,一旦你有这个单位,你需要使用kAudioUnitProperty_MakeConnection属性将它连接到kAudioUnitProperty_MakeConnection

但严重的是,只要让remoteIOcallback工作,然后尝试制作一个文件播放器audio单元并连接(没有callback),然后从那里开始。

询问有关这些步骤的独立问题的具体问题,张贴您尝试过的代码不工作,您将得到很多帮助。