Aufnahme von RemoteIO: Das resultierende .caf wird langsamer verschoben und verzerrt

Daher habe ich einige Routinen zum Aufnehmen von Audio zusammengestellt, die auf einigen Posts hier basieren. Die Beiträge, auf die ich verwiesen habe, sindHier undHierzusammen mit dem Lesen der Sites, auf die sie verweisen.

Mein Setup: Ich habe einen vorhandenen AUGraph: (mehrere AUSamplers -> Mixer -> RemoteIO). Die AUSampler sind mit Tracks in einer MusicPlayer-Instanz verbunden. Das alles funktioniert gut, aber ich möchte die Aufnahme hinzufügen.

Die Aufnahme funktioniert, aber das resultierende .caf ist langsamer mit Pitch / Tempo-Verschiebung + und hat eine schlechte Klangqualität. Muss etwas mit dem von mir angegebenen Format nicht stimmen?

Kann mir jemand sagen, wo ich das Format falsch einstelle?

BEARBEITEN: Könnte dies ein Stereo / Mono-Problem sein? Ich meine, in Mono aufzunehmen.

Ich habe das Stream-Format auf der RemoteIO-Instanz folgendermaßen eingestellt:

<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>

Dann erstelle ich aus einer Tastenaktion ein fileRef und hänge einen renderCallback an die RemoteIO-Instanz an:

<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>

Schließlich schreibe ich in meinem Rendercallback die Daten in der postRender-Phase aus:

<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>

Antworten auf die Frage(1)

Ihre Antwort auf die Frage