Working with AVAudioPCMBuffer

This thread has been locked by a moderator.

A few developers have asked how to populate AVAudioPCMBuffer(s) without an AVAudioFile and therefore not using one of the readIntoBuffer… methods.


An AVAudioPCMBuffer is a subclass of AVAudioBuffer for PCM audio formats. Those with some Core Audio background will notice that basically these buffer classes wrap the AudioStreamBasicDescription (via AVAudioFormat) and AudioBufferList/AudioBuffer structs.


When you create a AVAudioPCMBuffer object, the format of the buffer is required as is the buffers capacity which allocates the AudioBufferList/AudioBuffer(s) as required for the specified format and buffer size. The maximum number of frames you can store is represented by the read only frameCapacity property described as "The buffer's capacity, in audio sample frames. (read-only)”.


The frameLength property contains the current number of *valid* frames in the buffer which may be modified (and should be if you modify the contents of the underlying AudioBuffers directly). This frame length cannot be more than the capacity of the buffer. When you modify this length, the mDataByteSize field in each of the underlying AudioBuffers are updated accordingly.


AVAudioPCMBuffer provides three properties to get a pointer to the audio data contained in the buffer object:


floatChannelData - Returns a pointer to the buffer’s 32-bit float audio samples. It returns nil if it is another format.


int16ChannelData - Returns a pointer to the buffer's 2-byte integer audio samples. It returns nil if it is another format.


int32ChannelData - Returns a pointer to the buffer's 4-byte integer audio samples. It returns nil if it is another format.


In addition to this, the AVAudioBuffer class provides a couple of properties allowing access to the underlying AudioBufferList struct directly:


audioBufferList - The non-mutable version does not allow the AudioBufferList structure to be modified but you may modify the buffer contents. The contained AudioBuffer(s)mDataByteSize fields express the AVAudioPCMBuffer's current frameLength.


mutableAudioBufferList - The mutable version allows the AudioBufferList structure to be modified as well as being able to modify the buffer contents. The contained AudioBuffer(s)mDataByteSize fields expresses the AVAudioPCMBuffer's current frameCapacity. If this size is altered, you should modify the AVAudioPCMBuffer'sframeLength to match. Some lower-level Core Audio and Audio Toolbox APIs such as AudioConverterConvertComplexBuffer require a mutable AudioBufferList.


Here’s a simple example demonstrating how to allocate a floating point AVAudioPCMBuffer and filling it up with silence:


// make a silent stereo buffer
AVAudioChannelLayout *chLayout = [[AVAudioChannelLayout alloc] initWithLayoutTag:kAudioChannelLayoutTag_Stereo];
AVAudioFormat *chFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
                                                          sampleRate:44100.0
                                                          interleaved:NO
                                                        channelLayout:chLayout];

AVAudioPCMBuffer *thePCMBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:chFormat frameCapacity:1024];

thePCMBuffer.frameLength = thePCMBuffer.frameCapacity;

for (AVAudioChannelCount ch = 0; ch < chFormat.channelCount; ++ch) {
    memset(thePCMBuffer.floatChannelData[ch], 0, thePCMBuffer.frameLength * chFormat.streamDescription->mBytesPerFrame);
}


Reference:


https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioBuffer_Class/index.html

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioPCMBuffer_Class/index.html

Up vote post of theanalogkid
18k views