1/**********************************************************************************************************************************
2 *
3 *   OpenAL cross platform audio library
4 *	Copyright (c) 2004, Apple Computer, Inc., Copyright (c) 2012, Apple Inc. All rights reserved.
5 *
6 *   Redistribution and use in source and binary forms, with or without modification, are permitted provided
7 *   that the following conditions are met:
8 *
9 *   1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 *   2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
11 *       disclaimer in the documentation and/or other materials provided with the distribution.
12 *   3.  Neither the name of Apple Inc. ("Apple") nor the names of its contributors may be used to endorse or promote
13 *       products derived from this software without specific prior written permission.
14 *
15 *   THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 *   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS
17 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18 *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
20 *   USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 **********************************************************************************************************************************/
23
24#include <AudioToolbox/AudioToolbox.h>
25
26#ifndef __OpenAL_Aspen__oalRingBuffer__
27#define __OpenAL_Aspen__oalRingBuffer__
28
29// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30#pragma mark _____OALRingBuffer_____
31// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34// OALRingBuffer:
35// This class implements an audio ring buffer. Multi-channel data can be either
36// interleaved or deinterleaved.
37// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39
40enum {
41	kOALRingBufferError_WayBehind = -2, // both fetch times are earlier than buffer start time
42	kOALRingBufferError_SlightlyBehind = -1, // fetch start time is earlier than buffer start time (fetch end time OK)
43	kOALRingBufferError_OK = 0,
44	kOALRingBufferError_SlightlyAhead = 1, // fetch end time is later than buffer end time (fetch start time OK)
45	kOALRingBufferError_WayAhead = 2, // both fetch times are later than buffer end time
46	kOALRingBufferError_TooMuch = 3, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time
47	kOALRingBufferError_CPUOverload = 4 // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds
48};
49
50typedef SInt32 OALRingBufferError;
51typedef SInt64 SampleTime;
52
53const UInt32 kGeneralRingTimeBoundsQueueSize = 32;
54const UInt32 kGeneralRingTimeBoundsQueueMask = kGeneralRingTimeBoundsQueueSize - 1;
55
56class OALRingBuffer {
57public:
58	OALRingBuffer();
59	OALRingBuffer(UInt32 bytesPerFrame, UInt32 capacityFrames);
60	~OALRingBuffer();
61
62	void		Allocate(UInt32 bytesPerFrame, UInt32 capacityFrames);
63	void		Deallocate();
64	void		Clear();
65	bool		Store(const Byte *data, UInt32 nFrames, SInt64 frameNumber);
66	OSStatus	Fetch(Byte *data, UInt32 nFrames, SInt64 frameNumber);
67	Byte*		GetFramePtr(SInt64 frameNumber, UInt32 &outNFrames);
68
69	void		GetTimeBounds(SInt64 &start, SInt64&end) { start = mStartFrame; end = mEndFrame; }
70
71protected:
72	UInt32		FrameOffset(SInt64 frameNumber) { return (mStartOffset + UInt32(frameNumber - mStartFrame) * mBytesPerFrame) % mCapacityBytes; }
73
74protected:
75	Byte *		mBuffer;
76	UInt32		mBytesPerFrame;
77	UInt32		mCapacityFrames;
78	UInt32		mCapacityBytes;
79	UInt32		mStartOffset;
80	SInt64		mStartFrame;
81	SInt64		mEndFrame;
82};
83
84#endif  /* defined(__OpenAL_Aspen__oalRingBuffer__) */