Sto codificando un'app di registrazione musicale utilizzando Audio Units e sto riscontrando alcuni problemi che impediscono al mio file M4A di riprodurre qualcosa di diverso da un ronzio non così impressionante . Ho usato questi SO sourcesasreferences, e ho provato tutto per risolvere i problemi.Scrittura e codifica dell'uscita I/O remota su file - Core Audio
Ho un AUGraph
con 2 nodi: un mixer multicanale e un I/O remoto. Ho due callback di input sul mio mixer: uno che tira input dal microfono e uno che tira da un file audio. L'uscita del mixer è collegata all'elemento di ingresso dell'ambito di uscita sull'unità I/O. Ciò consente l'I/O simultaneo.
Per catturare l'output ho aggiunto una funzione di callback e due metodi:
Il callback
static OSStatus recordAndSaveCallback (void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
Mixer* THIS = (__bridge Mixer*)inRefCon;
AudioBufferList bufferList;
OSStatus status;
status = AudioUnitRender(THIS.ioUnit,
ioActionFlags,
inTimeStamp,
0,
inNumberFrames,
&bufferList);
SInt16 samples[inNumberFrames]; // A large enough size to not have to worry about buffer overrun
memset (&samples, 0, sizeof (samples));
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mData = samples;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mDataByteSize = inNumberFrames*sizeof(SInt16);
OSStatus result;
if (*ioActionFlags == kAudioUnitRenderAction_PostRender) {
result = ExtAudioFileWriteAsync(THIS.extAudioFileRef, inNumberFrames, &bufferList);
if(result) printf("ExtAudioFileWriteAsync %ld \n", result);}
return noErr;
}
Metodo di registrazione:
- (void)recordFile
{
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 = 1;
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));
UInt32 clientsize = sizeof(clientFormat);
result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &clientsize);
if(result) printf("AudioUnitGetProperty %ld \n", result);
UInt32 codec = kAppleHardwareAudioCodecManufacturer;
result = ExtAudioFileSetProperty(extAudioFileRef,
kExtAudioFileProperty_CodecManufacturer,
sizeof(codec),
&codec);
if(result) printf("ExtAudioFileSetProperty %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, recordAndSaveCallback, (__bridge void*)self);
if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];}
}
Metodo di risparmio:
- (void) saveFile {
OSStatus status = ExtAudioFileDispose(extAudioFileRef);
NSLog(@"OSStatus(ExtAudioFileDispose): %ld\n", status);
}
Questo è quello che vedo nella mia console:
Stopping audio processing graph
OSStatus(ExtAudioFileDispose): 0
ExtAudioFileWriteAsync -50
ExtAudioFileWriteAsync -50
ExtAudioFileWriteAsync -50
Mi sembra che il mio codice è molto simile a quello delle persone che hanno ottenuto questo lavoro, ma chiaramente ho fatto un errore cruciale. Sono sicuro che ci devono essere altri che lottano con questo.
Qualcuno ha qualche idea?
Grazie.
Sembra che il metodo '-saveFile' venga chiamato prima che 'recordAndSaveCallback' sia finito. Stai fermando l'AUGRAPH prima di chiamare saveFile? – sbooth
come esperimento per escludere eventuali problemi con il grafico potrebbe essere una buona idea provare e registrare utilizzando un formato più semplice come wav. ASBD può essere difficile da ottenere, ma se si può determinare che l'ASBD è il problema (la mia opinione), almeno si può semplicemente concentrarsi sulla sperimentazione con il formato del file. – dubbeat
esegue macerror -50 dalla riga di comando fornisce questo: Errore Mac OS -50 (paramErr): errore nell'elenco dei parametri utente – morgancodes