Nagrywanie z RemoteIO: wynikowy .caf jest przesunięty wolniej + zniekształcony
Więc przygotowałem kilka procedur nagrywania dźwięku na podstawie niektórych postów tutaj. Są to posty, do których się odwołałemtutaj itutaj, wraz z czytaniem stron, do których się odwołują.
Moje ustawienia: Mam istniejący AUGraph: (kilka AUSamplers -> Mixer -> RemoteIO). AUSamplery są połączone z utworami w instancji MusicPlayer. To wszystko działa dobrze, ale chcę dodać do niego nagranie.
Nagrywanie działa, ale wynikowy plik .caf jest przesunięty o tempo / tempo wolniej + ma złą jakość dźwięku. Musi być coś nie tak z formatem, który określam?
Czy ktoś może na to spojrzeć i powiedzieć, gdzie nieprawidłowo ustawiam format?
EDYTOWAĆ: czy może to być problem stereo / mono? Mam na myśli nagrywanie w trybie mono.
Ustawiłem format strumienia w instancji RemoteIO na ten:
<code> 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)); </code>
Następnie z akcji przycisku tworzę fileRef i dołączam renderCallback do instancji RemoteIO:
<code>- (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;} } </code>
W końcu w moim rendercallback zapisuję dane w fazie postRender:
<code>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; } </code>