2012-01-03 6 views
6

Ho scritto un ciclo per codificare i dati audio pcm generati dalla mia app in aac utilizzando Extended Audio File Services. La codifica avviene in un thread in background in modo sincrono e non in tempo reale.ExtAudioFileWrite a m4a/aac in errore su dispositivi dual-core (ipad 2, iphone 4s)

La codifica funziona perfettamente su ipad 1 e iphone 3gs/4 per entrambi ios 4 e 5. Tuttavia, per i dispositivi dual-core (iphone 4s, ipad 2) la terza chiamata a ExtAudioFileWrite arresta il thread di codifica senza traccia dello stack e nessun codice di errore.

Ecco il codice in questione:

I formati dati

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

Render ciclo

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

Le trame PCM sono creati correttamente, ma ExtAudioFileWrite fallisce il 2 °/3 ° tempo è chiamato.

Qualche idea? Grazie!

+0

Puoi pubblicare come riempire i buffer e come si chiama ExtAudioFileWrite? – sbooth

+0

Dopo molte frustrazioni e nessun aiuto da parte di Apple, il mio collega ha capito il problema. Apparentemente sui nuovi dispositivi iOS (iPad 2 e iPhone 4S), 44.1 kHz non è una frequenza di campionamento valida per la codifica AAC, almeno utilizzando i servizi di file audio esterni. 48 kHz funziona perfettamente. Ho presentato questo ad Apple come un bug, sperando che si prenderanno cura di esso. – roperklacks

risposta

17

Avevo un problema molto simile in cui stavo tentando di utilizzare Extended Audio File Services per trasmettere il suono PCM in un file m4a su un iPad 2. Tutto sembrava funzionare tranne che ogni chiamata a ExtAudioFileWrite ha restituito il codice di errore - 66567 (kExtAudioFileError_MaxPacketSizeUnknown). La soluzione che alla fine ho trovato era quella di impostare il "Codec Manufacturer" sul software anziché sull'hardware. Quindi inserire

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

appena prima di impostare il formato dei dati del client.

Questo mi porterebbe a credere che i codec hardware di Apple possano supportare solo codifiche molto specifiche, ma i codec software possono fare in modo più affidabile ciò che si desidera. Nel mio caso, la traduzione del codec software in m4a richiede il 50% in più rispetto alla scrittura dello stesso file esatto nel formato LPCM.

Qualcuno sa se Apple specifica da qualche parte qual è l'hardware del proprio codec audio in grado di? Sembra che gli ingegneri del software siano costretti a giocare il gioco di indovinello di ore per impostare i parametri ~ 20 in AudioStreamBasicDescription e AudioChannelLayout per il client e per il file su tutte le possibili permutazioni finché qualcosa non funziona ...

+0

Ho passato due giorni a eseguire il debug perché la codifica AAC ha improvvisamente smesso di funzionare su più app sul mio iPhone 4S ma non sui miei altri dispositivi iOS. Questo ha fatto il trucco. Non ho idea di come l'hai capito, ma molti complimenti a te e spero che pubblichi di più su SO. –

+0

Ho appena esaminato la documentazione di Extended Audio File Services e ho provato a impostare ogni combinazione di variabili fino a quando qualcosa non ha funzionato: P Glad I was help to! Ora se qualcuno potrebbe solo spiegare perché le capacità hardware dei dispositivi sono così incoerenti ... – user1021430

+0

Man ... grandi complimenti per te. Mi stavo chiedendo cosa stesse andando così terribilmente male nel mio codice per ExtAudioFileWrite a crash senza backtrace. Grazie per l'aiuto. Ho già riempito un bug, grazie a te. Spero che si unisca con l'altro rapporto sui bug di roperklacks. Grazie ancora. – Dan1one

Problemi correlati