2012-01-03 10 views
6

Escribí un bucle para codificar los datos de audio pcm generados por mi aplicación en aac utilizando Extended Audio File Services. La codificación tiene lugar en una cadena de fondo de forma síncrona, y no en tiempo real.ExtAudioFileWrite a m4a/aac falla en dispositivos de doble núcleo (ipad 2, iphone 4s)

La codificación funciona perfectamente en ipad 1 y iphone 3gs/4 para ios 4 y 5. Sin embargo, para dispositivos de doble núcleo (iphone 4s, ipad 2) la tercera llamada a ExtAudioFileWrite bloquea el hilo de codificación sin rastro de pila y no hay código de error

Aquí está el código en cuestión:

Los formatos de datos

AudioStreamBasicDescription AUCanonicalASBD(Float64 sampleRate, 
             UInt32 channel){ 
AudioStreamBasicDescription audioFormat; 
audioFormat.mSampleRate   = sampleRate; 
audioFormat.mFormatID   = kAudioFormatLinearPCM; 
audioFormat.mFormatFlags  = kAudioFormatFlagsAudioUnitCanonical; 
audioFormat.mChannelsPerFrame = channel; 
audioFormat.mBytesPerPacket  = sizeof(AudioUnitSampleType); 
audioFormat.mBytesPerFrame  = sizeof(AudioUnitSampleType); 
audioFormat.mFramesPerPacket = 1; 
audioFormat.mBitsPerChannel  = 8 * sizeof(AudioUnitSampleType); 
audioFormat.mReserved   = 0; 
return audioFormat; 
} 

AudioStreamBasicDescription MixdownAAC(void){ 
AudioStreamBasicDescription audioFormat; 
audioFormat.mSampleRate   = 44100.0; 
audioFormat.mFormatID   = kAudioFormatMPEG4AAC; 
audioFormat.mFormatFlags  = kMPEG4Object_AAC_Main; 
audioFormat.mChannelsPerFrame = 2; 
audioFormat.mBytesPerPacket  = 0; 
audioFormat.mBytesPerFrame  = 0; 
audioFormat.mFramesPerPacket = 1024; 
audioFormat.mBitsPerChannel  = 0; 
audioFormat.mReserved   = 0; 
return audioFormat; 
} 

El bucle de render

OSStatus err; 
ExtAudioFileRef outFile; 
NSURL *mixdownURL = [NSURL fileURLWithPath:filePath isDirectory:NO]; 

// internal data format 
AudioStreamBasicDescription localFormat = AUCanonicalASBD(44100.0, 2); 

// output file format 
AudioStreamBasicDescription mixdownFormat = MixdownAAC(); 
err = ExtAudioFileCreateWithURL((CFURLRef)mixdownURL, 
          kAudioFileM4AType, 
          &mixdownFormat, 
          NULL, 
          kAudioFileFlags_EraseFile, 
          &outFile); 


err = ExtAudioFileSetProperty(outFile, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &localFormat); 

// prep 
AllRenderData *allData = &allRenderData; 
writeBuffer = malloc(sizeof(AudioBufferList) + (2*sizeof(AudioBuffer))); 
writeBuffer->mNumberBuffers = 2; 
writeBuffer->mBuffers[0].mNumberChannels = 1; 
writeBuffer->mBuffers[0].mDataByteSize = bufferBytes; 
writeBuffer->mBuffers[0].mData = malloc(bufferBytes); 
writeBuffer->mBuffers[1].mNumberChannels = 1; 
writeBuffer->mBuffers[1].mDataByteSize = bufferBytes; 
writeBuffer->mBuffers[1].mData = malloc(bufferBytes); 

memset(writeBuffer->mBuffers[0].mData, 0, bufferBytes); 
memset(writeBuffer->mBuffers[1].mData, 0, bufferBytes); 

UInt32 framesToGet; 
UInt32 frameCount = allData->gLoopStartFrame; 
UInt32 startFrame = allData->gLoopStartFrame; 
UInt32 lastFrame = allData->gLoopEndFrame; 

// write one silent buffer 
ExtAudioFileWrite(outFile, bufferFrames, writeBuffer); 

while (frameCount < lastFrame){ 

    // how many frames do we need to get 
    if (lastFrame - frameCount > bufferFrames) 
     framesToGet = bufferFrames; 
    else 
     framesToGet = lastFrame - frameCount; 

    // get dem frames 
    err = theBigOlCallback((void*)&allRenderData, 
          NULL, NULL, 1, 
          framesToGet, writeBuffer); 

    // write to output file 
    ExtAudioFileWrite(outFile, framesToGet, writeBuffer); 

    frameCount += framesToGet; 
} 

// write one trailing silent buffer 
memset(writeBuffer->mBuffers[0].mData, 0, bufferBytes); 
memset(writeBuffer->mBuffers[1].mData, 0, bufferBytes); 
processLimiterInPlace8p24(limiter, writeBuffer->mBuffers[0].mData, writeBuffer->mBuffers[1].mData, bufferFrames); 
ExtAudioFileWrite(outFile, bufferFrames, writeBuffer); 

err = ExtAudioFileDispose(outFile); 

Las tramas de PCM se crean correctamente, pero ExtAudioFileWrite falla el segundo tercio del tiempo/se llama.

¿Alguna idea? ¡Gracias!

+0

¿Puedes publicar cómo llenar los búferes y cómo está llamando a ExtAudioFileWrite? – sbooth

+0

Después de mucha frustración y sin ayuda de Apple, mi compañero de trabajo descubrió el problema. Aparentemente en los dispositivos iOS más nuevos (iPad 2 y iPhone 4S), 44.1 kHz no es una frecuencia de muestreo válida para la codificación AAC, al menos utilizando los Servicios de archivos de audio externos. 48 kHz funciona bien. He archivado esto a Apple como un error, con suerte se encargarán de eso. – roperklacks

Respuesta

17

Tuve un problema muy similar cuando intentaba utilizar Extended Audio File Services para transmitir sonido PCM a un archivo m4a en un iPad 2. Todo parecía funcionar, excepto que cada llamada a ExtAudioFileWrite devolvía el código de error: 66567 (kExtAudioFileError_MaxPacketSizeUnknown). La solución que finalmente encontré fue configurar el "Fabricante de códecs" para el software en lugar de hardware. Así que coloque

UInt32 codecManf = kAppleSoftwareAudioCodecManufacturer; 
ExtAudioFileSetProperty(FileToWrite, kExtAudioFileProperty_CodecManufacturer, sizeof(UInt32), &codecManf); 

justo antes de establecer el formato de datos del cliente.

Esto me llevaría a creer que los códecs de hardware de Apple solo pueden admitir una codificación muy específica, pero los códecs de software pueden hacer más confiablemente lo que usted desea. En mi caso, la traducción del códec de software a m4a toma un 50% más de tiempo que escribir el mismo archivo exacto en formato LPCM.

¿Alguien sabe si Apple especifica en alguna parte de qué es capaz su hardware de códec de audio? Parece que los ingenieros de software están atrapados jugando el juego de adivinanzas de una hora de establecer los ~ 20 parámetros en el AudioStreamBasicDescription y AudioChannelLayout para el cliente y para el archivo en cada permutación posible hasta que algo funcione ...

+0

Pasé dos días depurando por qué la codificación AAC dejó de funcionar repentinamente en varias aplicaciones en mi iPhone 4S pero no en mis otros dispositivos iOS. Esto hizo el truco. No tengo idea de cómo lo descubriste, pero te felicito mucho y espero que publiques más en SO. –

+0

Acabo de excavar a través de la referencia de Extended Audio File Services e intenté establecer cada combinación de variables hasta que algo funcionó: P Me alegro de poder ayudar. Ahora, si alguien pudiera explicar por qué las capacidades de hardware de los dispositivos son tan inconsistentes ... – user1021430

+0

Hombre ... grandes felicitaciones para usted. Me preguntaba qué estaba pasando tan terriblemente mal en mi código para que ExtAudioFileWrite se bloqueara sin rastrear. Gracias por tu ayuda. Ya he llenado un error, en esto gracias a ti. Con suerte, se fusionará con el otro informe de errores de roperklacks. Gracias de nuevo. – Dan1one

Cuestiones relacionadas