2017-11-21 2 views
0

AudioFileWriteBytes(CoreAudio/iOS)を使用してステレオウェーブファイルを作成しています。これを動作させる唯一の方法は、各チャンネルのサンプルごとに呼び出すことです。AudioFileWriteBytesのステレオファイルのパフォーマンス

次のコードは動作します:

// Prepare the format AudioStreamBasicDescription; 
AudioStreamBasicDescription asbd = { 
    .mSampleRate  = session.samplerate, 
    .mFormatID   = kAudioFormatLinearPCM, 
    .mFormatFlags  = kAudioFormatFlagIsBigEndian| kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked, 
    .mChannelsPerFrame = 2, 
    .mBitsPerChannel = 16, 
    .mFramesPerPacket = 1, // Always 1 for uncompressed formats 
    .mBytesPerPacket = 4, // 16 bits for 2 channels = 4 bytes 
    .mBytesPerFrame = 4 // 16 bits for 2 channels = 4 bytes 
}; 

// Set up the file 
AudioFileID audioFile; 
OSStatus audioError = noErr; 
audioError = AudioFileCreateWithURL((__bridge CFURLRef)fileURL, kAudioFileAIFFType, &asbd, kAudioFileFlags_EraseFile, &audioFile); 
if (audioError != noErr) { 
    NSLog(@"Error creating file"); 
    return; 
}  

// Write samples 
UInt64 currentFrame = 0; 
while (currentFrame < totalLengthInFrames) { 
    UInt64 numberOfFramesToWrite = totalLengthInFrames - currentFrame; 
    if (numberOfFramesToWrite > 2048) { 
     numberOfFramesToWrite = 2048; 
    } 

    UInt32 sampleByteCount = sizeof(int16_t); 
    UInt32 bytesToWrite = (UInt32)numberOfFramesToWrite * sampleByteCount; 
    int16_t *sampleBufferLeft = (int16_t *)malloc(bytesToWrite); 
    int16_t *sampleBufferRight = (int16_t *)malloc(bytesToWrite); 

    // Some magic to fill the buffers 

    for (int j = 0; j < numberOfFramesToWrite; j++) { 
     int16_t left = CFSwapInt16HostToBig(sampleBufferLeft[j]); 
     int16_t right = CFSwapInt16HostToBig(sampleBufferRight[j]); 

     audioError = AudioFileWriteBytes(audioFile, false, (currentFrame + j) * 4, &sampleByteCount, &left); 
     assert(audioError == noErr); 
     audioError = AudioFileWriteBytes(audioFile, false, (currentFrame + j) * 4 + 2, &sampleByteCount, &right); 
     assert(audioError == noErr); 
    } 

    free(sampleBufferLeft); 
    free(sampleBufferRight); 

    currentFrame += numberOfFramesToWrite; 
} 

しかし、それは非常に遅く、非効率的な(明らかに)です。 2つのチャンネルを書きながら1つ以上のサンプルを書き込むことができるように、大きいバッファでの使用方法については何も見つかりません。

私は、LRLRLRLR(左/右)に行くバッファを作って、AudioFileWriteBytesコールを1つだけ書きました。私はそれが働くことを期待しましたが、ノイズで満たされたファイルを作りました。 は、これはコードです:

UInt64 currentFrame = 0; 
UInt64 bytePos = 0; 
while (currentFrame < totalLengthInFrames) { 
    UInt64 numberOfFramesToWrite = totalLengthInFrames - currentFrame; 
    if (numberOfFramesToWrite > 2048) { 
     numberOfFramesToWrite = 2048; 
    } 

    UInt32 sampleByteCount = sizeof(int16_t); 
    UInt32 bytesInBuffer = (UInt32)numberOfFramesToWrite * sampleByteCount; 
    UInt32 bytesInOutputBuffer = (UInt32)numberOfFramesToWrite * sampleByteCount * 2; 
    int16_t *sampleBufferLeft = (int16_t *)malloc(bytesInBuffer); 
    int16_t *sampleBufferRight = (int16_t *)malloc(bytesInBuffer); 
    int16_t *outputBuffer = (int16_t *)malloc(bytesInOutputBuffer); 

    // Some magic to fill the buffers 

    for (int j = 0; j < numberOfFramesToWrite; j++) { 
     int16_t left = CFSwapInt16HostToBig(sampleBufferLeft[j]); 
     int16_t right = CFSwapInt16HostToBig(sampleBufferRight[j]); 

     outputBuffer[(j * 2)] = left; 
     outputBuffer[(j * 2) + 1] = right; 
    } 

    audioError = AudioFileWriteBytes(audioFile, false, bytePos, &bytesInOutputBuffer, &outputBuffer); 
    assert(audioError == noErr); 

    free(sampleBufferLeft); 
    free(sampleBufferRight); 
    free(outputBuffer); 

    bytePos += bytesInOutputBuffer; 
    currentFrame += numberOfFramesToWrite; 
} 

私もちょうど一度バッファを書き込もうとしました(2048 *のL、2048 *のRなど)私は仕事に期待していなかった、それはしませんでした。

これをスピードアップして、動作するwaveファイルを取得するにはどうすればよいですか?

+1

サンプルLRLRLR ...を記述するためのコードを表示すると、そのコードにはおそらく配列の添え字やエンディアンのある単純なバグがあります。 – hotpaw2

答えて

2

私は、LRLRLRLR(左/右)に行くバッファを作って、AudioFileWriteBytesコールを1つだけ書きました。

(かなり難しい)オーディオファイルサービスを使用する場合は、これが正しい方法です。

可能であれば、非常に低いレベルのオーディオファイルサービスではなく、Extended Audio File Servicesを使用してください。これは、フォーマットコンバータを組み込んだAudio File Servicesのラッパーです。それ以上の場合は、AVAudioFileを使用してください。は、最も一般的な使用例をカバーする拡張オーディオファイルサービスのラッパーです。

オーディオファイルサービスを使用するように設定されている場合、試したように手動でオーディオをインターリーブする必要があります。あなたがこれを試みた場所のコードを表示するかもしれません。

+0

私は壊れたコードを追加しました。私はより高いレベルのAPIを試しますが、今はどこが間違っているのか不思議です! –

関連する問題