How to read an AVAudioFile into the same AVAudioPCMBuffer multiple times?

964 Views Asked by At

EDIT:

I was able to prevent readIntoBuffer from returning false by adding audioFileB.framePosition = 0; at the end of my for loop. However, now it looks like bufferB only contains audio from the final readIntoBuffer call (my incomplete loop). Does anyone know why my buffer is discarding data previously loaded into it after each readIntoBuffer call?

Original Question:

I have two AVAudioFiles, audioFileA and audioFileB, where A has a longer duration than B (possibly by several times). I want to create two AVAudioPCMBuffers large enough to hold audioFileA, fill one of them with audioFileA's data, and fill the other with audioFileB's data over and over again until the buffer is full. In other words, the second buffer should contain a "looping" of the audio in audioFileB. Here's my attempt:

AVAudioFile *audioFileA = ...
AVAudioFile *audioFileB = ...
AVAudioPCMBuffer * bufferA = [[AVAudioPCMBuffer alloc] audioFileA.processingFormat frameCapacity:(AVAudioFrameCount)audioFileA.length];
AVAudioPCMBuffer * bufferB = [[AVAudioPCMBuffer alloc] audioFileB.processingFormat frameCapacity:(AVAudioFrameCount)audioFileA.length];
NSError *bufferAError;
NSError *bufferBError;
BOOL bufferASuccess;
BOOL bufferBSuccess;

int timesLarger = audioFileA.length / audioFileB.length;
int remainder = audioFileA.length % audioFileB.length;
for (int i = 0; i < timesLarger; i++) {
    bufferBSuccess = [audioFileB readIntoBuffer:bufferB frameCount:(AVAudioFrameCount)audioFileB.length error:&bufferBError];
    if (!bufferBSuccess || bufferBError != NULL) {
        break;
    }
}
// once we're done appending all of the complete loops (if any) then add the remaining audio to the end of the buffer
if (bufferBSuccess && bufferBError == NULL) {
    bufferBSuccess = [audioFileB readIntoBuffer:bufferB frameCount:(AVAudioFrameCount)remainder error:&bufferBError];
}

The issue is that [audioFileB readIntoBuffer:bufferB frameCount:(AVAudioFrameCount)audioFileB.length error:&bufferBError] returns false when it is called more than once. Any ideas on how I can accomplish this?

0

There are 0 best solutions below