6

拡張オーディオファイルサービスを使用して、アプリによって生成されたpcmオーディオデータをaacにエンコードするループを作成しました。エンコードは、リアルタイムではなく、バックグラウンドスレッドで同期的に行われます。

エンコーディングは、iOS4と5の両方のipad1とiphone3gs / 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は2回目と3回目の呼び出しで失敗します。

何か案は?ありがとうございました!

4

1 に答える 1

18

PCMサウンドをiPad2のm4aファイルにストリーミングするために拡張オーディオファイルサービスを使用しようとしたときに、非常によく似た問題が発生しました。ExtAudioFileWriteを呼び出すたびにエラーコード-66567(kExtAudioFileError_MaxPacketSizeUnknown)が返されることを除いて、すべてが機能しているように見えました。 。私が最終的に見つけた修正は、「コーデックメーカー」をハードウェアではなくソフトウェアに設定することでした。だから場所

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

クライアントのデータ形式を設定する直前。

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

Appleがオーディオコーデックハードウェアの機能をどこかに指定しているかどうかを誰かが知っていますか?ソフトウェアエンジニアは、何かが機能するまで、クライアントとファイルのAudioStreamBasicDescriptionとAudioChannelLayoutで最大20個のパラメータを設定するという何時間にもわたる推測ゲームをプレイし続けているようです...

于 2012-03-22T18:19:14.790 に答える