0

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?

Community
  • 1
  • 1
WongWray
  • 1,685
  • 1
  • 18
  • 20
  • What are you doing with the AVAudioPCMBuffers? If you are using AVAudioPlayerNode, you might consider scheduling file segments. – dave234 Sep 28 '17 at 23:53
  • @Dave Kind of hard to fully describe in the length of a comment but the gist is that _B_ contains audio that was playing (and looping) out of the speaker at the time that _A_ was recorded and I need a buffer containing exactly what _B_ played back. I've found a much more AVAudioEngine-ish way to accomplish this (tapping _B_'s playernode) that I'm gonna post as soon at the kinks are worked out and I can simplify it enough to be a more general answer to the question – WongWray Sep 29 '17 at 02:52
  • @Dave of course, still feel free to post any answer/advice – WongWray Sep 29 '17 at 02:54

0 Answers0