Aufnahme von RemoteIO auf AAC: Daten werden geschrieben, aber die Datei kann nicht abgespielt werden

Ich habe versucht, mit einem RenderCallback in iOS 5 auf einem iPad 2 von einem RemoteIO-Gerät direkt auf AAC aufzunehmen. Ich habe widersprüchliche Informationen gesehen, die besagten, dass dies nicht möglich ist und dass dies möglich ist (in den Kommentaren)Hier). Mein Grund dafür ist, dass das Aufzeichnen auf PCM so viel Speicherplatz für eine Aufzeichnung beliebiger Länge erfordert - auch wenn sie später in AAC konvertiert wird.

Ich bin bereit aufzugeben. Ich habe Google, SO, das Core Audio-Buch und die Apple Core-Audio-Mailingliste und -Foren durchsucht und bin an dem Punkt angelangt, an dem keine Fehler mehr auftreten - und ich nehme aufetwas auf die Festplatte, aber die resultierende Datei ist nicht abspielbar. Dies ist sowohl beim Simulator als auch beim Gerät der Fall.

Also ... wenn jemand Erfahrung damit hat, würde ich mich sehr über einen Schubs in die richtige Richtung freuen. Das Setup sieht so aus, dass RemoteIO die Ausgabe von AUSamplern abspielt und das funktioniert einwandfrei.

Hier ist, was ich im Code unten mache

Präzisiere dasAudioStreamBasicDescription Formate für das RemoteIO-Gerät ankAudioFormatLinearPCM

Erstellen Sie das Zielformat für dieExtAudioFileRef Geben Sie das Client-Format an, indem Sie es vom RemoteIO-Gerät beziehen

Geben Sie den renderCallback für die RemoteID-Einheit an

Schreiben Sie im renderCallback Daten in daskAudioUnitRenderAction_PostRender Phase

Wie gesagt, es werden keine Fehler angezeigt, und die daraus resultierenden Audiodateigrößen zeigen an, dass etwas geschrieben wird, die Datei ist jedoch nicht abspielbar. Vielleicht habe ich meine Formate vermasselt?

Wie auch immer, dies ist meine Flaschenpost und / oder "Be Here Dragons" -Flagge für alle anderen, die sich dem dunklen Wasser von Core-Audio stellen.

// Die unglückliche Nachricht, die ich bekomme, wenn ich versuche, die Datei abzuspielen:

// Teil des RemoteIO-Setups

<code>    // Enable IO for recording

UInt32 flag = 1;
result = AudioUnitSetProperty(ioUnit, 
                              kAudioOutputUnitProperty_EnableIO, 
                              kAudioUnitScope_Input, 
                              kInputBus, // == 1
                              &flag, 
                              sizeof(flag));
if (noErr != result) {[self printErrorMessage: @"Enable IO for recording" withStatus: result]; return;}

// Describe format - - - - - - - - - -
size_t bytesPerSample = sizeof (AudioUnitSampleType);
AudioStreamBasicDescription audioFormat;
memset(&audioFormat, 0, sizeof(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;

result = AudioUnitSetProperty(ioUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Output, 
                              kInputBus, // == 1
                              &audioFormat, 
                              sizeof(audioFormat));


result = AudioUnitSetProperty(ioUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Input, 
                              kOutputBus, // == 0
                              &audioFormat, 
                              sizeof(audioFormat));
</code>

// Funktion zum Einrichten von file & rendercallback

<code> - (void)startRecordingAAC
{

OSStatus result;

NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *recordFile = [documentsDirectory stringByAppendingPathComponent: @"audio.m4a"];

CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, 
                                                        (__bridge   CFStringRef)recordFile, 
                                                        kCFURLPOSIXPathStyle, 
                                                        false);

AudioStreamBasicDescription destinationFormat;
memset(&destinationFormat, 0, sizeof(destinationFormat));
destinationFormat.mChannelsPerFrame = 2;
destinationFormat.mFormatID = kAudioFormatMPEG4AAC;
UInt32 size = sizeof(destinationFormat);
result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);        
if(result) printf("AudioFormatGetProperty %ld \n", result);


result = ExtAudioFileCreateWithURL(destinationURL, 
                                   kAudioFileM4AType, 
                                   &destinationFormat, 
                                   NULL, 
                                   kAudioFileFlags_EraseFile, 
                                   &extAudioFileRef);
if(result) printf("ExtAudioFileCreateWithURL %ld \n", result);

AudioStreamBasicDescription clientFormat;
memset(&clientFormat, 0, sizeof(clientFormat));


result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, & clientFormat, &size);
 if(result) printf("AudioUnitGetProperty %ld \n", result);

result = ExtAudioFileSetProperty(extAudioFileRef,kExtAudioFileProperty_ClientDataFormat,sizeof(clientFormat),&clientFormat);
if(result) printf("ExtAudioFileSetProperty %ld \n", result);

result =  ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL);
if (result) {[self printErrorMessage: @"ExtAudioFileWriteAsync error" withStatus: result];}

result = AudioUnitAddRenderNotify(ioUnit, renderCallback, (__bridge void*)self);
if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];}
}
</code>

// Und zum Schluss der Rendercallback

<code>static OSStatus renderCallback (void *                       inRefCon,
                            AudioUnitRenderActionFlags * ioActionFlags,
                            const AudioTimeStamp *       inTimeStamp,
                            UInt32                       inBusNumber,
                            UInt32                       inNumberFrames,
                            AudioBufferList *            ioData) 
{

OSStatus result;
if (*ioActionFlags == kAudioUnitRenderAction_PostRender){
    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(3)

Ihre Antwort auf die Frage