0
votes

I'm creating an iPhone app in objective-C using the EZAudio library.

I use the EZMicrophone class & EZRecorder class to save audio to disk. Yet I want the recording and the saving to be delayed so I have to pass an AudioBufferList structure received in a delegate method used by EZMicrophone, to an NSMutableArray.

I'm having trouble passing that AudioBufferList struct received in the delegate method to an NSMutableArray for later use.

I encapsulated the AudioBufferList struct in an NSValue.

The source

Here's the delegate methode :

- (void)microphone:(EZMicrophone *)microphone
     hasBufferList:(AudioBufferList *)bufferList
    withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels {

    NSValue *audioData = [NSValue valueWithBytes:bufferList objCType:@encode(AudioBufferList)];

    [self.listOfBufferList addObject:audioData];

}

And here's the method that receives the NSMutableArray of AudioBufferList

- (void)createAudioFile {

    for(int i = 0;i<self.listOfBufferList.count;i++) {

        AudioBufferList bufferList;
        [self.listOfBufferList[i] getBytes:&bufferList length:BufferSize];
        [self.recorder appendDataFromBufferList:&bufferList
                                 withBufferSize:BufferSize];
    }

[self.recorder closeAudioFile];

}

I get the error :

Error: Failed to read audio data from audio file (-66567) when I play the file with my app

But when :

[self.recorder appendDataFromBufferList:&bufferList
                                     withBufferSize:BufferSize];

is right in the delegate method, the audio file reads without any problem so my question is, how can I encapsulate that AudioBufferList struct into an object that wouldn't be lost in the process knowing that for the sake of my app, I need those two separate methods.

Also, when I debug the app, in the createAudioFile method, I can see that the structure variable are copied properly yet the buffer that is a (void*) is different from the one found in the delegate method. (different content and address)

Here are the Core Audio Types AudioBufferList and AudioBuffer that I'm trying to pass through methods.

struct AudioBufferList
{
    UInt32      mNumberBuffers;
    AudioBuffer mBuffers[1]; // this is a variable length array of mNumberBuffers elements

};
typedef struct AudioBufferList  AudioBufferList;

struct AudioBuffer
{
    UInt32  mNumberChannels;
    UInt32  mDataByteSize;
    void*   mData;
};
typedef struct AudioBuffer  AudioBuffer;

Thank you very much for your help, I'm available for more details of course.

1

1 Answers

0
votes

You should save the AudioBufferLists in a c array. You can e.g. create a struct with the number of AudioBufferLists and the array containing the buffer lists. If you know the maximum number of buffer lists you want to use, you can define the array with that size and store the actual number added to the array in the number member.

struct MyBufferLists
{
    UInt32      mNumberBufferLists;
    AudioBufferList mBufferLists[9]; // enter your max number instead of 9
};

The add this struct to the class in which you need it.