Estoy codificando una aplicación de grabación de música usando unidades de audio y tengo algunos problemas para que mi archivo M4A resultante reproduzca algo que no sea un zumbido no tan increíble . He utilizado estos SO sourcesasreferences, y he intentado todo para solucionar los problemas.Escribir y codificar salida I/0 remota a archivo - Core Audio
Tengo un AUGraph
con 2 nodos: un mezclador multicanal y una E/S remota. Tengo dos devoluciones de entrada en mi mezclador: una que extrae la entrada del micrófono y otra que saca de un archivo de audio. La salida del mezclador está conectada al elemento de entrada del alcance de salida en la unidad de E/S. Esto permite E/S simultáneas.
Para capturar la salida he añadido una devolución de llamada y dos métodos:
La devolución de llamada
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;
}
Método de grabación:
- (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];}
}
Método Ahorro:
- (void) saveFile {
OSStatus status = ExtAudioFileDispose(extAudioFileRef);
NSLog(@"OSStatus(ExtAudioFileDispose): %ld\n", status);
}
Esto es lo que veo en mi consola:
Stopping audio processing graph
OSStatus(ExtAudioFileDispose): 0
ExtAudioFileWriteAsync -50
ExtAudioFileWriteAsync -50
ExtAudioFileWriteAsync -50
Me parece que mi código es muy similar a la de las personas que han conseguido que esto funcione, pero está claro que he cometió un error crucial Estoy seguro de que debe haber otros luchando con esto.
¿Alguien tiene alguna idea?
Gracias.
Parece que se llama al método '-saveFile' antes de que finalice' recordAndSaveCallback'. ¿Estás deteniendo el AUGraph antes de llamar a saveFile? – sbooth
como un experimento para descartar cualquier problema con su gráfico, podría ser una buena idea tratar de registrar usando un formato más simple como wav. ASBD puede ser difícil de entender, pero si puedes determinar que el ASBD es el problema (mi opinión), al menos puedes concentrarte en experimentar con el formato de archivo. – dubbeat
ejecutando macerror -50 desde la línea de comandos da esto: Mac OS error -50 (paramErr): error en la lista de parámetros de usuario – morgancodes