summaryrefslogtreecommitdiff
path: root/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp')
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
new file mode 100644
index 0000000000..d3644ed2e4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
@@ -0,0 +1,239 @@
+/*
+ File: CAAudioBufferList.cpp
+ Abstract: CAAudioBufferList.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAAudioBufferList.h"
+#include "CADebugMacros.h"
+#include "CALogMacros.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+// CAAudioBufferList
+//=============================================================================
+
+AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers)
+{
+ UInt32 theSize = CalculateByteSize(inNumberBuffers);
+ AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize));
+ if(theAnswer != NULL)
+ {
+ theAnswer->mNumberBuffers = inNumberBuffers;
+ }
+ return theAnswer;
+}
+
+void CAAudioBufferList::Destroy(AudioBufferList* inBufferList)
+{
+ free(inBufferList);
+}
+
+UInt32 CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers)
+{
+ UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer);
+ theSize += inNumberBuffers * SizeOf32(AudioBuffer);
+ return theSize;
+}
+
+UInt32 CAAudioBufferList::GetTotalNumberChannels(const AudioBufferList& inBufferList)
+{
+ UInt32 theAnswer = 0;
+
+ for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+ {
+ theAnswer += inBufferList.mBuffers[theIndex].mNumberChannels;
+ }
+
+ return theAnswer;
+}
+
+bool CAAudioBufferList::GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel)
+{
+ bool theAnswer = false;
+ UInt32 theIndex = 0;
+
+ while((theIndex < inBufferList.mNumberBuffers) && (inChannel >= inBufferList.mBuffers[theIndex].mNumberChannels))
+ {
+ inChannel -= inBufferList.mBuffers[theIndex].mNumberChannels;
+ ++theIndex;
+ }
+
+ if(theIndex < inBufferList.mNumberBuffers)
+ {
+ outBufferNumber = theIndex;
+ outBufferChannel = inChannel;
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+void CAAudioBufferList::Clear(AudioBufferList& outBufferList)
+{
+ // assumes that "0" is actually the 0 value for this stream format
+ for(UInt32 theBufferIndex = 0; theBufferIndex < outBufferList.mNumberBuffers; ++theBufferIndex)
+ {
+ if(outBufferList.mBuffers[theBufferIndex].mData != NULL)
+ {
+ memset(outBufferList.mBuffers[theBufferIndex].mData, 0, outBufferList.mBuffers[theBufferIndex].mDataByteSize);
+ }
+ }
+}
+
+void CAAudioBufferList::Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel)
+{
+ // This is a brute force copy method that can handle ABL's that have different buffer layouts
+ // This means that this method is probably not the fastest way to do this for all cases.
+ // This method also assumes that both the source and destination sample formats are Float32
+
+ UInt32 theInputChannel = inStartingSourceChannel;
+ UInt32 theNumberInputChannels = GetTotalNumberChannels(inSource);
+ UInt32 theOutputChannel = inStartingDestinationChannel;
+ UInt32 theNumberOutputChannels = GetTotalNumberChannels(outDestination);
+
+ UInt32 theInputBufferIndex = 0;
+ UInt32 theInputBufferChannel = 0;
+ UInt32 theOutputBufferIndex = 0;
+ UInt32 theOutputBufferChannel = 0;
+ while((theInputChannel < theNumberInputChannels) && (theOutputChannel < theNumberOutputChannels))
+ {
+ GetBufferForChannel(inSource, theInputChannel, theInputBufferIndex, theInputBufferChannel);
+
+ GetBufferForChannel(inSource, theOutputChannel, theOutputBufferIndex, theOutputBufferChannel);
+
+ CopyChannel(inSource.mBuffers[theInputBufferIndex], theInputBufferChannel, outDestination.mBuffers[theOutputBufferIndex], theOutputBufferChannel);
+
+ ++theInputChannel;
+ ++theOutputChannel;
+ }
+}
+
+void CAAudioBufferList::CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel)
+{
+ // set up the stuff for the loop
+ UInt32 theNumberFramesToCopy = outDestination.mDataByteSize / (outDestination.mNumberChannels * SizeOf32(Float32));
+ const Float32* theSource = static_cast<const Float32*>(inSource.mData);
+ Float32* theDestination = static_cast<Float32*>(outDestination.mData);
+
+ // loop through the data and copy the samples
+ while(theNumberFramesToCopy > 0)
+ {
+ // copy the data
+ theDestination[inDestinationChannel] = theSource[inSourceChannel];
+
+ // adjust the pointers
+ --theNumberFramesToCopy;
+ theSource += inSource.mNumberChannels;
+ theDestination += outDestination.mNumberChannels;
+ }
+}
+
+void CAAudioBufferList::Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList)
+{
+ // assumes that the buffers are Float32 samples and the listst have the same layout
+ // this is a lame algorithm, by the way. it could at least be unrolled a couple of times
+ for(UInt32 theBufferIndex = 0; theBufferIndex < ioSummedBufferList.mNumberBuffers; ++theBufferIndex)
+ {
+ Float32* theSourceBuffer = static_cast<Float32*>(inSourceBufferList.mBuffers[theBufferIndex].mData);
+ Float32* theSummedBuffer = static_cast<Float32*>(ioSummedBufferList.mBuffers[theBufferIndex].mData);
+ UInt32 theNumberSamplesToMix = ioSummedBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(Float32);
+ if((theSourceBuffer != NULL) && (theSummedBuffer != NULL) && (theNumberSamplesToMix > 0))
+ {
+ while(theNumberSamplesToMix > 0)
+ {
+ *theSummedBuffer += *theSourceBuffer;
+ ++theSummedBuffer;
+ ++theSourceBuffer;
+ --theNumberSamplesToMix;
+ }
+ }
+ }
+}
+
+bool CAAudioBufferList::HasData(AudioBufferList& inBufferList)
+{
+ bool hasData = false;
+ for(UInt32 theBufferIndex = 0; !hasData && (theBufferIndex < inBufferList.mNumberBuffers); ++theBufferIndex)
+ {
+ if(inBufferList.mBuffers[theBufferIndex].mData != NULL)
+ {
+ UInt32* theBuffer = (UInt32*)inBufferList.mBuffers[theBufferIndex].mData;
+ UInt32 theNumberSamples = inBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(UInt32);
+ for(UInt32 theSampleIndex = 0; !hasData && (theSampleIndex < theNumberSamples); ++theSampleIndex)
+ {
+ hasData = theBuffer[theSampleIndex] != 0;
+ }
+ }
+ }
+ return hasData;
+}
+
+#if CoreAudio_Debug
+void CAAudioBufferList::PrintToLog(const AudioBufferList& inBufferList)
+{
+ PrintInt(" Number streams: ", inBufferList.mNumberBuffers);
+
+ for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+ {
+ PrintIndexedInt(" Channels in stream", theIndex + 1, inBufferList.mBuffers[theIndex].mNumberChannels);
+ PrintIndexedInt(" Buffer size of stream", theIndex + 1, inBufferList.mBuffers[theIndex].mDataByteSize);
+ }
+}
+#endif
+
+const AudioBufferList* CAAudioBufferList::GetEmptyBufferList()
+{
+ static bool sInitializer = false;
+ static AudioBufferList sEmptyABL;
+ if(!sInitializer)
+ {
+ memset(&sEmptyABL, 0, sizeof(AudioBufferList));
+ }
+ return &sEmptyABL;
+}