2012-01-03 14 views
6

Napisałem pętlę do zakodowania danych dźwiękowych pcm wygenerowanych przez moją aplikację do aac przy użyciu usług Extended Audio File Services. Kodowanie odbywa się w wątku tła synchronicznie, a nie w czasie rzeczywistym.ExtAudioFileWrite na awaria m4a/aac na urządzeniach dwurdzeniowych (ipad 2, iphone 4s)

Kodowanie działa bezbłędnie na iPadzie 1 i iphone 3gs/4 dla ios 4 i 5. Jednak w przypadku urządzeń dwurdzeniowych (iphone 4s, ipad 2) trzecie wywołanie ExtAudioFileWrite powoduje przerwanie wątku kodowania bez śledzenia stosu i bez kodu błędu.

Oto kod w pytaniu:

Formaty danych

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

Masę tynkarską pętla

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

Ramy PCM są prawidłowo utworzone, ale ExtAudioFileWrite nie 2nd/3rd czas to się nazywa.

Wszelkie pomysły? Dziękuję Ci!

+0

Czy umieścisz informacje o tym, w jaki sposób wypełnić bufory i jak dzwonisz do ExtAudioFileWrite? – sbooth

+0

Po długiej frustracji i braku pomocy ze strony Apple, mój współpracownik zrozumiał problem. Najwyraźniej na nowszych urządzeniach z systemem iOS (iPad 2 i iPhone 4S) częstotliwość 44,1 kHz nie jest poprawną częstotliwością próbkowania dla kodowania AAC, przynajmniej przy użyciu zewnętrznych usług plików audio. 48 kHz działa dobrze. Złożyłem to do Apple jako błąd, mam nadzieję, że się tym zajmą. – roperklacks

Odpowiedz

17

Miałem bardzo podobny problem, gdy próbowałem korzystać z usług Extended Audio File Services, aby przesyłać strumieniowo dźwięk PCM do pliku m4a na iPadzie 2. Wszystko wyglądało na to, że działa, z tym że każde wywołanie ExtAudioFileWrite zwróciło kod błędu - 66567 (kExtAudioFileError_MaxPacketSizeUnknown). Rozwiązaniem, które w końcu znalazłem, było ustawienie "Producenta kodeków" na oprogramowanie zamiast na sprzęcie. Dlatego tuż przed ustawieniem formatu danych klienta należy umieścić urządzenie.

To doprowadziłoby mnie do przekonania, że ​​kodeki sprzętowe Apple obsługują tylko bardzo specyficzne kodowanie, ale kodeki oprogramowania mogą bardziej niezawodnie wykonywać to, co się chce. W moim przypadku tłumaczenie kodeków oprogramowania na m4a trwa o 50% dłużej niż zapisanie dokładnie tego samego pliku w formacie LPCM.

Czy ktoś wie, czy Apple określa, w jakim miejscu może działać sprzęt audio z kodem kodeka? Wygląda na to, że inżynierowie oprogramowania utknęli w wielogodzinnej grze o odgadywaniu, ustawiającej ~ 20 parametrów w AudioStreamBasicDescription i AudioChannelLayout dla klienta i pliku dla każdej możliwej permutacji, dopóki coś nie zadziała ...

+0

Spędziłem dwa dni na debugowaniu, dlaczego kodowanie AAC nagle przestało działać w wielu aplikacjach na moim iPhone 4S, ale nie w moich innych urządzeniach z systemem iOS. To załatwiło sprawę. Nie mam pojęcia, jak to rozgryzłeś, ale masz wiele do zaoferowania i mam nadzieję, że opublikujesz więcej w SO. –

+0

Właśnie przeszukałem referencje usług Extended Audio File Services i próbowałem ustawić każdą kombinację zmiennych, aż coś zadziałało: P Cieszę się, że mogłem pomóc! Teraz, jeśli ktoś mógłby po prostu wyjaśnić, dlaczego możliwości sprzętowe urządzeń są tak niespójne ... – user1021430

+0

Człowieku ... Wielkie szczęście dla ciebie. Zastanawiam się, co było tak strasznie nie tak w moim kodzie dla ExtAudioFileWrite, aby zawiesić się bez backtrace. Dzięki za pomoc. Wypełniłem już błąd, na tym dziękuję. Mamy nadzieję, że zostanie on połączony z innym raportem o błędach z roperklacks. Dzięki jeszcze raz. – Dan1one