summaryrefslogtreecommitdiff
path: root/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h')
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h424
1 files changed, 424 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
new file mode 100644
index 0000000000..8b81dba69a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
@@ -0,0 +1,424 @@
+/*
+ File: CAStreamBasicDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+ 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.
+
+*/
+#ifndef __CAStreamBasicDescription_h__
+#define __CAStreamBasicDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include "CoreAudioTypes.h"
+ #include "CoreFoundation.h"
+#endif
+
+#include "CADebugMacros.h"
+#include <string.h> // for memset, memcpy
+#include <stdio.h> // for FILE *
+
+#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
+
+extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize);
+
+// define Leopard specific symbols for backward compatibility if applicable
+#if COREAUDIOTYPES_VERSION < 1050
+typedef Float32 AudioSampleType;
+enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
+#endif
+#if COREAUDIOTYPES_VERSION < 1051
+typedef Float32 AudioUnitSampleType;
+enum {
+ kLinearPCMFormatFlagsSampleFractionShift = 7,
+ kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
+};
+#endif
+
+// define the IsMixable format flag for all versions of the system
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+ enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
+#else
+ enum { kIsNonMixableFlag = (1L << 6) };
+#endif
+
+//=============================================================================
+// CAStreamBasicDescription
+//
+// This is a wrapper class for the AudioStreamBasicDescription struct.
+// It adds a number of convenience routines, but otherwise adds nothing
+// to the footprint of the original struct.
+//=============================================================================
+class CAStreamBasicDescription :
+ public AudioStreamBasicDescription
+{
+
+// Constants
+public:
+ static const AudioStreamBasicDescription sEmpty;
+
+ enum CommonPCMFormat {
+ kPCMFormatOther = 0,
+ kPCMFormatFloat32 = 1,
+ kPCMFormatInt16 = 2,
+ kPCMFormatFixed824 = 3,
+ kPCMFormatFloat64 = 4
+ };
+
+// Construction/Destruction
+public:
+ CAStreamBasicDescription();
+
+ CAStreamBasicDescription(const AudioStreamBasicDescription &desc);
+
+ CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID,
+ UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
+ UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
+ UInt32 inBitsPerChannel, UInt32 inFormatFlags);
+
+ CAStreamBasicDescription( double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) {
+ unsigned wordsize;
+
+ mSampleRate = inSampleRate;
+ mFormatID = kAudioFormatLinearPCM;
+ mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
+ mFramesPerPacket = 1;
+ mChannelsPerFrame = inNumChannels;
+ mBytesPerFrame = mBytesPerPacket = 0;
+ mReserved = 0;
+
+ switch (pcmf) {
+ default:
+ return;
+ case kPCMFormatFloat32:
+ wordsize = 4;
+ mFormatFlags |= kAudioFormatFlagIsFloat;
+ break;
+ case kPCMFormatFloat64:
+ wordsize = 8;
+ mFormatFlags |= kAudioFormatFlagIsFloat;
+ break;
+ case kPCMFormatInt16:
+ wordsize = 2;
+ mFormatFlags |= kAudioFormatFlagIsSignedInteger;
+ break;
+ case kPCMFormatFixed824:
+ wordsize = 4;
+ mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift);
+ break;
+ }
+ mBitsPerChannel = wordsize * 8;
+ if (inIsInterleaved)
+ mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels;
+ else {
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ mBytesPerFrame = mBytesPerPacket = wordsize;
+ }
+ }
+
+// Assignment
+ CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
+
+ void SetFrom(const AudioStreamBasicDescription &desc)
+ {
+ memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
+ }
+
+ bool FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); }
+ static bool FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc);
+ // return true if parsing was successful
+
+ static const char *sTextParsingUsageString;
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // interrogation
+
+ bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
+
+ bool PackednessIsSignificant() const
+ {
+ Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
+ return (SampleWordSize() << 3) != mBitsPerChannel;
+ }
+
+ bool AlignmentIsSignificant() const
+ {
+ return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
+ }
+
+ bool IsInterleaved() const
+ {
+ return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
+ }
+
+ bool IsSignedInteger() const
+ {
+ return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger);
+ }
+
+ bool IsFloat() const
+ {
+ return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat);
+ }
+
+ bool IsNativeEndian() const
+ {
+ return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
+ }
+
+ // for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
+ UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
+ UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
+ UInt32 NumberChannels() const { return mChannelsPerFrame; }
+ UInt32 SampleWordSize() const {
+ return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0;
+ }
+
+ UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; }
+ UInt32 BytesToFrames(UInt32 nbytes) const {
+ Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
+ return nbytes / mBytesPerFrame;
+ }
+
+ bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
+ {
+ return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
+ }
+
+ bool IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const
+ { // return true if it's a valid PCM format.
+
+ outFormat = kPCMFormatOther;
+ // trap out patently invalid formats.
+ if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0)
+ return false;
+ bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+ if (outIsInterleaved != NULL) *outIsInterleaved = interleaved;
+ unsigned wordsize = mBytesPerFrame;
+ if (interleaved) {
+ if (wordsize % mChannelsPerFrame != 0) return false;
+ wordsize /= mChannelsPerFrame;
+ }
+
+ if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian
+ && wordsize * 8 == mBitsPerChannel) {
+ // packed and native endian, good
+ if (mFormatFlags & kLinearPCMFormatFlagIsFloat) {
+ // float: reject nonsense bits
+ if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask))
+ return false;
+ if (wordsize == 4)
+ outFormat = kPCMFormatFloat32;
+ if (wordsize == 8)
+ outFormat = kPCMFormatFloat64;
+ } else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) {
+ // signed int
+ unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+ if (wordsize == 4 && fracbits == 24)
+ outFormat = kPCMFormatFixed824;
+ else if (wordsize == 2 && fracbits == 0)
+ outFormat = kPCMFormatInt16;
+ }
+ }
+ return true;
+ }
+
+ bool IsCommonFloat32(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32;
+ }
+ bool IsCommonFloat64(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64;
+ }
+ bool IsCommonFixed824(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824;
+ }
+ bool IsCommonInt16(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16;
+ }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // manipulation
+
+ void SetCanonical(UInt32 nChannels, bool interleaved)
+ // note: leaves sample rate untouched
+ {
+ mFormatID = kAudioFormatLinearPCM;
+ UInt32 sampleSize = SizeOf32(AudioSampleType);
+ mFormatFlags = kAudioFormatFlagsCanonical;
+ mBitsPerChannel = 8 * sampleSize;
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ if (interleaved)
+ mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
+ else {
+ mBytesPerPacket = mBytesPerFrame = sampleSize;
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ bool IsCanonical() const
+ {
+ if (mFormatID != kAudioFormatLinearPCM) return false;
+ UInt32 reqFormatFlags;
+ UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask);
+ bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+ unsigned sampleSize = SizeOf32(AudioSampleType);
+ reqFormatFlags = kAudioFormatFlagsCanonical;
+ UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
+
+ return ((mFormatFlags & flagsMask) == reqFormatFlags
+ && mBitsPerChannel == 8 * sampleSize
+ && mFramesPerPacket == 1
+ && mBytesPerFrame == reqFrameSize
+ && mBytesPerPacket == reqFrameSize);
+ }
+
+ void SetAUCanonical(UInt32 nChannels, bool interleaved)
+ {
+ mFormatID = kAudioFormatLinearPCM;
+#if CA_PREFER_FIXED_POINT
+ mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
+#else
+ mFormatFlags = kAudioFormatFlagsCanonical;
+#endif
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
+ if (interleaved)
+ mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
+ else {
+ mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
+ // alter an existing format
+ {
+ Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
+ UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
+ if (wordSize == 0)
+ wordSize = (mBitsPerChannel + 7) / 8;
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ if (interleaved) {
+ mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
+ mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved);
+ } else {
+ mBytesPerPacket = mBytesPerFrame = wordSize;
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // other
+
+ bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const;
+ static bool FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
+ static bool IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
+
+ void Print() const {
+ Print (stdout);
+ }
+
+ void Print(FILE* file) const {
+ PrintFormat (file, "", "AudioStreamBasicDescription:");
+ }
+
+ void PrintFormat(FILE *f, const char *indent, const char *name) const {
+ char buf[256];
+ fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
+ }
+
+ void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
+ char buf[256];
+ fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
+ }
+
+ char * AsString(char *buf, size_t bufsize, bool brief=false) const;
+
+ static void Print (const AudioStreamBasicDescription &inDesc)
+ {
+ CAStreamBasicDescription desc(inDesc);
+ desc.Print ();
+ }
+
+ OSStatus Save(CFPropertyListRef *outData) const;
+
+ OSStatus Restore(CFPropertyListRef &inData);
+
+// Operations
+ static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
+ static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
+ static void NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
+ static void ResetFormat(AudioStreamBasicDescription& ioDescription);
+ static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
+ static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false);
+ static void ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly);
+
+#if CoreAudio_Debug
+ static void PrintToLog(const AudioStreamBasicDescription& inDesc);
+#endif
+};
+
+bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
+inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
+inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+bool SanityCheck(const AudioStreamBasicDescription& x);
+
+
+#endif // __CAStreamBasicDescription_h__