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!
Czy umieścisz informacje o tym, w jaki sposób wypełnić bufory i jak dzwonisz do ExtAudioFileWrite? – sbooth
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