Grabación desde RemoteIO: el .caf resultante es el tono más lento + distorsionado
Así que he reunido algunas rutinas para grabar audio basadas en algunas publicaciones aquí. Las publicaciones a las que he hecho referencia son:aquí yaquí, junto con la lectura de los sitios a los que hacen referencia.
Mi configuración: Tengo un AUGraph existente: (varios AUSamplers -> Mixer -> RemoteIO). Los AUSamplers están conectados a pistas en una instancia de MusicPlayer. Eso funciona bien, pero quiero añadirle una grabación.
La grabación está funcionando pero el .caf resultante es el tono / tempo cambiado más lento + tiene una mala calidad de sonido. ¿Debe haber algo mal con el formato que estoy especificando?
¿Alguien puede ver esto y decirme dónde estoy configurando el formato incorrectamente?
EDITAR: ¿Podría ser esto un problema estéreo / mono? Quiero grabar en mono.
Establecí el formato de transmisión en la instancia de RemoteIO a esto:
<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>
Luego, desde una acción de botón, creo un fileRef y adjunto un renderCallback a la instancia de 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>
Finalmente, en mi rendercallback escribo los datos en la fase 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>