2012-01-03 12 views
6

拡張オーディオファイルサービスを使用して自分のアプリケーションで生成されたpcmオーディオデータをaacにエンコードするループを作成しました。エンコーディングはリアルタイムではなくバックグラウンドスレッドで同期して行われます。デュアルコアデバイス(ipad 2、iphone 4s)で失敗したm4a/aacへのExtAudioFileWrite

ios 4と5の両方でipad 1とiphone 3gs/4でエンコーディングが問題なく動作します。ただし、デュアルコアデバイス(iphone 4s、ipad 2)の場合、ExtAudioFileWriteへの3回目の呼び出しで、エラーコードはありません。

データ形式

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

レンダリングループ

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

PCMフレームが適切に作成されますが、ExtAudioFileWriteは、第二/第三の時間を失敗しています。ここ

は、問題のコードですいわゆる。

アイデア?ありがとうございました!

+0

バッファを埋めて、ExtAudioFileWriteをどのように呼び出していますか? – sbooth

+0

多くの不満とアップルからの助けなしに、私の同僚は問題を把握しました。明らかに、新しいiOSデバイス(iPad 2とiPhone 4S)では、44.1 kHzは、少なくとも外部オーディオファイルサービスを使用する場合、AACエンコーディングの有効なサンプルレートではありません。 48 kHzでうまくいきます。私はこれをAppleにバグとして提出しました。うまくいけば、彼らはそれを世話するでしょう。 – roperklacks

答えて

17

PCMサウンドをiPad 2のm4aファイルにストリーミングするために、拡張オーディオファイルサービスを使用しようとしたところ、非常に似た問題がありました。ExtAudioFileWriteを呼び出すたびに、 66567(kExtAudioFileError_MaxPacketSizeUnknown)。最終的に見つかった修正は、 "コーデック製造元"をハードウェアではなくソフトウェアに設定することでした。したがって、クライアントのデータ形式を設定する直前に

の直前に配置してください。

これは、Appleのハードウェアコーデックが非常に特殊なエンコーディングしかサポートしていないと思うようになりますが、ソフトウェアコーデックはより確実にあなたが望むことをすることができます。私の場合、m4aへのソフトウェアコーデック変換は、まったく同じファイルをLPCMフォーマットに書き込むよりも50%長くかかります。

アップルがオーディオコーデックハードウェアの能力をどこかに指定しているかどうかは誰にも分かりますか?ソフトウェアエンジニアは、AudioStreamBasicDescription〜AudioChannelLayoutの〜20個のパラメータをクライアントとファイルのすべての可能な順列に設定するという長時間の推測ゲームを何かが働くまで続けることができないようです...

+0

私は2日間、なぜAACエンコーディングがiPhone 4Sでは複数のアプリケーションで突然機能しなくなりましたが、他のiOSデバイスでは機能しなくなりました。これはトリックでした。どのようにあなたがそれを理解したのか分かりませんが、あなたには多くの名声があります。 –

+0

私はExtended Audio File Servicesのリファレンスを掘り下げて、何かが働くまで変数のあらゆる組み合わせを設定しようとしました:P喜んで助けてくれました!今、誰かがなぜデバイスのハードウェア能力がそんなに矛盾しているのかを説明できたら... – user1021430

+0

男...あなたに大きな誇りを持っています。 ExtAudioFileWriteがバックトレースなしでクラッシュするように、私のコードで何がひどく間違っているのだろうと思っていました。ご協力いただきありがとうございます。私はすでにあなたにこのバグを埋めました。うまくいけば、それはroperklacksからの他のバグレポートとマージされるでしょう。再度、感謝します。 – Dan1one

関連する問題