/*============================================================================= CAAudioStreamBasicDesc.cp $Log: CAAudioStreamBasicDesc.cpp,v $ Revision 1.16 2003/04/23 22:33:13 dwyatt more fallout of class merge Revision 1.15 2003/04/23 22:09:04 dwyatt CAAudioStreamBasicDescription merged into CAStreamBasicDescription Revision 1.14 2003/04/22 23:06:20 asynth shorter, faster, easier to read operator == Revision 1.13 2003/04/12 01:37:21 jcm10 add sEmpty Revision 1.12 2003/03/02 00:55:13 jcm10 0 is wild card for format flags Revision 1.11 2003/02/22 00:57:20 jcm10 fix the wild card format flags test Revision 1.10 2003/02/21 22:16:37 jcm10 don't use kAudioFormatFlagNotValid directly so that this is still buildable on Jaguar Revision 1.9 2003/02/21 01:59:15 jcm10 add FillOutFormat Revision 1.8 2003/02/10 21:00:52 jcm10 still more tweaks to GetSimpleName Revision 1.7 2003/02/07 22:39:27 jcm10 more GetSimpleName adjustments Revision 1.6 2003/01/30 22:30:59 jcm10 add a flag to return abbreviated strings to GetSimpleName() Revision 1.5 2003/01/27 23:02:59 jcm10 forgot some includes Revision 1.4 2003/01/27 20:07:04 jcm10 add GetSimpleName() Revision 1.3 2002/06/01 02:15:26 ealdrich renamed so MS DevStudio will compile the file Revision 1.3 2002/04/26 19:47:15 jcm10 change it back Revision 1.1 2002/04/26 19:43:33 jcm10 renamed from CAAudioStreamBasicDesc.cp to CAAudioStreamBasicDesc.cpp Revision 1.1 2002/03/01 01:52:40 jcm10 moved here from ../Utility Revision 1.15 2002/02/28 23:24:29 jcm10 added the CA prefix to DebugMacros and LogMacros for more consistency Revision 1.14 2002/01/17 01:36:04 jcm10 use kAudioFormatFlagsNativeEndian instead of a conditional Revision 1.13 2001/11/15 02:20:25 jcm10 call standard C library fucntions without the namespace to make cpp-precomp happy Revision 1.12 2001/10/11 21:24:16 jcm10 finish the first round of AC-3 support Revision 1.11 2001/10/08 19:43:45 jcm10 add AC-3 public API and documentation changes Revision 1.10 2001/07/25 21:43:04 jcm10 Add ResetFormat() Revision 1.9 2001/04/06 02:58:00 jcm10 add NormalizeLinearPCMFormat Revision 1.8 2001/04/05 01:36:43 jcm10 clean things up Revision 1.7 2001/03/27 00:51:47 jcm10 make the release styles build again Revision 1.6 2001/03/27 00:42:20 jcm10 add PrintToLog methods and reverse the logic of the sorting operators Revision 1.5 2001/03/20 22:12:36 jcm10 remove extraneous Assert Revision 1.4 2001/01/05 03:13:06 jcm10 remove the warnings Revision 1.3 2001/01/05 03:09:08 jcm10 implement operator< Revision 1.2 2001/01/04 22:38:58 jcm10 no longer needed Revision 1.1 2001/01/04 21:59:15 jcm10 rename CAAudioStreamBasicDescription to CAAudioStreamBasicDesc Revision 1.1 2001/01/04 20:17:04 jcm10 first checked in Revision 0.0 2000/12/20 12:38:51 jcm10 created $NoKeywords: $ =============================================================================*/ //============================================================================= // Includes //============================================================================= #error "CAAudioStreamBasicDesc is now OBSOLETE -- replace with CAStreamBasicDescription" #if 0 // THIS FILE IS NOW OBSOLETE -- REPLACE WITH CAStreamBasicDescription #include "CADebugMacros.h" #include "CALogMacros.h" #include #include //============================================================================= // CAAudioStreamBasicDescription //============================================================================= const AudioStreamBasicDescription CAAudioStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }; CAAudioStreamBasicDescription::CAAudioStreamBasicDescription() { mSampleRate = 0; mFormatID = 0; mBytesPerPacket = 0; mFramesPerPacket = 0; mBytesPerFrame = 0; mChannelsPerFrame = 0; mBitsPerChannel = 0; mFormatFlags = 0; } CAAudioStreamBasicDescription::CAAudioStreamBasicDescription(const AudioStreamBasicDescription& v) { mSampleRate = v.mSampleRate; mFormatID = v.mFormatID; mBytesPerPacket = v.mBytesPerPacket; mFramesPerPacket = v.mFramesPerPacket; mBytesPerFrame = v.mBytesPerFrame; mChannelsPerFrame = v.mChannelsPerFrame; mBitsPerChannel = v.mBitsPerChannel; mFormatFlags = v.mFormatFlags; } CAAudioStreamBasicDescription::CAAudioStreamBasicDescription(double inSampleRate, UInt32 inFormatID, UInt32 inBytesPerPacket, UInt32 inFramesPerPacket, UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame, UInt32 inBitsPerChannel, UInt32 inFormatFlags) { mSampleRate = inSampleRate; mFormatID = inFormatID; mBytesPerPacket = inBytesPerPacket; mFramesPerPacket = inFramesPerPacket; mBytesPerFrame = inBytesPerFrame; mChannelsPerFrame = inChannelsPerFrame; mBitsPerChannel = inBitsPerChannel; mFormatFlags = inFormatFlags; } CAAudioStreamBasicDescription& CAAudioStreamBasicDescription::operator=(const AudioStreamBasicDescription& v) { mSampleRate = v.mSampleRate; mFormatID = v.mFormatID; mBytesPerPacket = v.mBytesPerPacket; mFramesPerPacket = v.mFramesPerPacket; mBytesPerFrame = v.mBytesPerFrame; mChannelsPerFrame = v.mChannelsPerFrame; mBitsPerChannel = v.mBitsPerChannel; mFormatFlags = v.mFormatFlags; return *this; } void CAAudioStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription) { if(ioDescription.mFormatID == kAudioFormatLinearPCM) { // we have to doctor the linear PCM format because we always // only export 32 bit, native endian, fully packed floats ioDescription.mBitsPerChannel = sizeof(Float32) * 8; ioDescription.mBytesPerFrame = sizeof(Float32) * ioDescription.mChannelsPerFrame; ioDescription.mFramesPerPacket = 1; ioDescription.mBytesPerPacket = ioDescription.mFramesPerPacket * ioDescription.mBytesPerFrame; ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; ioDescription.mFormatFlags |= kAudioFormatFlagsNativeEndian; } } void CAAudioStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription) { ioDescription.mSampleRate = 0; ioDescription.mFormatID = 0; ioDescription.mBytesPerPacket = 0; ioDescription.mFramesPerPacket = 0; ioDescription.mBytesPerFrame = 0; ioDescription.mChannelsPerFrame = 0; ioDescription.mBitsPerChannel = 0; ioDescription.mFormatFlags = 0; } void CAAudioStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription) { if(ioDescription.mSampleRate == 0) { ioDescription.mSampleRate = inTemplateDescription.mSampleRate; } if(ioDescription.mFormatID == 0) { ioDescription.mFormatID = inTemplateDescription.mFormatID; } if(ioDescription.mFormatFlags == 0) { ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags; } if(ioDescription.mBytesPerPacket == 0) { ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket; } if(ioDescription.mFramesPerPacket == 0) { ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket; } if(ioDescription.mBytesPerFrame == 0) { ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame; } if(ioDescription.mChannelsPerFrame == 0) { ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame; } if(ioDescription.mBitsPerChannel == 0) { ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel; } } void CAAudioStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, bool inAbbreviate) { switch(inDescription.mFormatID) { case kAudioFormatLinearPCM: { const char* theEndianString = NULL; if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) { #if TARGET_RT_LITTLE_ENDIAN theEndianString = "Big Endian"; #endif } else { #if TARGET_RT_BIG_ENDIAN theEndianString = "Little Endian"; #endif } const char* theKindString = NULL; if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0) { theKindString = (inAbbreviate ? "Float" : "Floating Point"); } else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) { theKindString = (inAbbreviate ? "SInt" : "Signed Integer"); } else { theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer"); } const char* thePackingString = NULL; if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0) { if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0) { thePackingString = "High"; } else { thePackingString = "Low"; } } if(inAbbreviate) { if(theEndianString != NULL) { if(thePackingString != NULL) { sprintf(outName, "%d Ch %s %s %s%d/%s%d", (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8); } else { sprintf(outName, "%d Ch %s %s%d", (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel); } } else { if(thePackingString != NULL) { sprintf(outName, "%d Ch %s %s%d/%s%d", (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8)); } else { sprintf(outName, "%d Ch %s%d", (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel); } } } else { if(theEndianString != NULL) { if(thePackingString != NULL) { sprintf(outName, "%d Channel %d Bit %s %s Aligned %s in %d Bits", (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8); } else { sprintf(outName, "%d Channel %d Bit %s %s", (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString); } } else { sprintf(outName, "%d Channel %d Bit %s", (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString); if(thePackingString != NULL) { sprintf(outName, "%d Channel %d Bit %s Aligned %s in %d Bits", (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8); } else { sprintf(outName, "%d Channel %d Bit %s", (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString); } } } } break; case kAudioFormatAC3: strcpy(outName, "AC-3"); break; case kAudioFormat60958AC3: strcpy(outName, "AC-3 for SPDIF"); break; default: { char* the4CCString = (char*)&inDescription.mFormatID; outName[0] = the4CCString[0]; outName[1] = the4CCString[1]; outName[2] = the4CCString[2]; outName[3] = the4CCString[3]; outName[4] = 0; } break; }; } #if CoreAudio_Debug void CAAudioStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc) { PrintFloat (" Sample Rate: ", inDesc.mSampleRate); Print4CharCode (" Format ID: ", inDesc.mFormatID); PrintHex (" Format Flags: ", inDesc.mFormatFlags); PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket); PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket); PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame); PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame); PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel); } #endif bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { bool theAnswer = false; bool isDone = false; // note that if either side is 0, that field is skipped // format ID is the first order sort if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0))) { if(x.mFormatID != y.mFormatID) { // formats are sorted numerically except that linear // PCM is always first if(x.mFormatID == kAudioFormatLinearPCM) { theAnswer = true; } else if(y.mFormatID == kAudioFormatLinearPCM) { theAnswer = false; } else { theAnswer = x.mFormatID < y.mFormatID; } isDone = true; } } // floating point vs integer for linear PCM only if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM))) { if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat)) { // floating point is better than integer theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat; isDone = true; } } // bit depth if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0))) { if(x.mBitsPerChannel != y.mBitsPerChannel) { // deeper bit depths are higher quality theAnswer = x.mBitsPerChannel < y.mBitsPerChannel; isDone = true; } } // sample rate if((!isDone) && ((x.mSampleRate != 0) && (y.mSampleRate != 0))) { if(x.mSampleRate != y.mSampleRate) { // higher sample rates are higher quality theAnswer = x.mSampleRate < y.mSampleRate; isDone = true; } } // number of channels if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0))) { if(x.mChannelsPerFrame != y.mChannelsPerFrame) { // more channels is higher quality theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame; isDone = true; } } return theAnswer; } bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { // the semantics for equality are: // 1) Values must match exactly // 2) wildcard's are ignored in the comparison #define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name)) return // check the sample rate MATCH(mSampleRate) // check the format ids && MATCH(mFormatID) // check the format flags && (x.mFormatID == 0 || y.mFormatID == 0 || MATCH(mFormatFlags)) // check the bytes per packet && MATCH(mBytesPerPacket) // check the frames per packet && MATCH(mFramesPerPacket) // check the bytes per frame && MATCH(mBytesPerFrame) // check the channels per frame && MATCH(mChannelsPerFrame) // check the channels per frame && MATCH(mBitsPerChannel) ; } #endif