从RemoteIO录制:生成的.caf音调移位较慢+失真
所以我已经拼凑了一些基于一些post在这里录制audio的例程。 我引用的post在这里和这里 ,以及阅读他们引用的网站。
我的设置:我有一个现有的AUGraph :(几个AUSamplers – >混音器 – > RemoteIO)。 AUSamplers连接到MusicPlayer实例中的轨道。 这一切工作正常,但我想添加logging。
录音正在工作,但所产生的.caf音调/速度移动得慢+音质差。 必须是我指定的格式有问题吗?
有人可以眼球,并告诉我在哪里设置格式不正确吗?
编辑:这可能是一个立体声/单声道问题? 我的意思是在单声道录音。
我将RemoteIO实例上的stream格式设置为:
AudioStreamBasicDescription audioFormat; audioFormat.mSampleRate = 44100.00; audioFormat.mFormatID = kAudioFormatLinearPCM; audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; audioFormat.mFramesPerPacket = 1; audioFormat.mChannelsPerFrame = 1; audioFormat.mBitsPerChannel = 16; audioFormat.mBytesPerPacket = 2; audioFormat.mBytesPerFrame = 2; // Apply format result = AudioUnitSetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &audioFormat, sizeof(audioFormat));
然后从一个button动作创build一个fileRef并将一个renderCallback附加到RemoteIO实例:
- (void)startRecording { OSStatus result; AudioStreamBasicDescription audioFormat; audioFormat.mSampleRate = 44100.00; audioFormat.mFormatID = kAudioFormatLinearPCM; audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; audioFormat.mFramesPerPacket = 1; audioFormat.mChannelsPerFrame = 1; audioFormat.mBitsPerChannel = 16; audioFormat.mBytesPerPacket = 2; audioFormat.mBytesPerFrame = 2; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *destinationFilePath = [[NSString alloc] initWithFormat: @"%@/output.caf", documentsDirectory]; CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)destinationFilePath, kCFURLPOSIXPathStyle, false); result = ExtAudioFileCreateWithURL(destinationURL, kAudioFileWAVEType, &audioFormat, NULL, kAudioFileFlags_EraseFile, &extAudioFileRef); CFRelease(destinationURL); NSAssert(result == noErr, @"Couldn't create file for writing"); result = ExtAudioFileSetProperty(extAudioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &audioFormat); NSAssert(result == noErr, @"Couldn't create file for format"); result = ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL); NSAssert(result == noErr, @"Couldn't initialize write buffers for audio file"); printf("Adding render to remoteIO \n"); result = AudioUnitAddRenderNotify(ioUnit, renderCallback, (__bridge void*)self); if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result]; return;} }
最后在我的rendercallback中写出postRender阶段的数据:
static OSStatus renderCallback (void * inRefCon, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { OSStatus result; if (*ioActionFlags == kAudioUnitRenderAction_PostRender){ double timeInSeconds = inTimeStamp->mSampleTime / kSampleRate; printf("%fs inBusNumber: %lu inNumberFrames: %lu \n", timeInSeconds, inBusNumber, inNumberFrames); MusicPlayerController* THIS = (__bridge MusicPlayerController *)inRefCon; result = ExtAudioFileWriteAsync(THIS->extAudioFileRef, inNumberFrames, ioData); if(result) printf("ExtAudioFileWriteAsync %ld \n", result); } return noErr; }
好 – find解决这个问题的一些代码 – 虽然我不完全明白为什么。
对于RemoteIO输出stream和mBitsPerChannel
,我都将mBitsPerChannel
设置为16。 结果是放缓和刮擦audio。 将ExtFileRef mBitsPerChannel
设置为32,再加上kAudioFormatFlagsNativeEndian
标志可以解决这个问题:.cafaudio是完美的(同时使RemoteIO输出stream设置保持原样)。
但是,也可以设置RemoteIO输出stream设置以匹配我的新设置。 所以我很困惑。 只要AudioStreamBasicDescription
设置对于RemoteIO实例和ExtFileRef是对称的,不应该这样工作吗?
无论如何…工作环境如下。
size_t bytesPerSample = sizeof (AudioUnitSampleType); AudioStreamBasicDescription audioFormat; audioFormat.mSampleRate= graphSampleRate; audioFormat.mFormatID=kAudioFormatLinearPCM; audioFormat.mFormatFlags=kAudioFormatFlagsNativeEndian|kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked; audioFormat.mBytesPerPacket=bytesPerSample; audioFormat.mBytesPerFrame=bytesPerSample; audioFormat.mFramesPerPacket=1; audioFormat.mChannelsPerFrame=1; audioFormat.mBitsPerChannel= 8 * bytesPerSample; audioFormat.mReserved=0;