···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFile.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAAudioFile_h__
4444+#define __CAAudioFile_h__
4545+4646+#include <AvailabilityMacros.h>
4747+4848+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4949+ #include <AudioToolbox/AudioToolbox.h>
5050+#else
5151+ #include <AudioToolbox.h>
5252+#endif
5353+5454+#include "CAStreamBasicDescription.h"
5555+#include "CABufferList.h"
5656+#include "CAAudioChannelLayout.h"
5757+#include "CAXException.h"
5858+#include "CAMath.h"
5959+6060+#ifndef CAAF_USE_EXTAUDIOFILE
6161+// option: use AudioToolbox/ExtAudioFile.h? Only available on Tiger.
6262+ #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
6363+ // we are building software that must be deployable on Panther or earlier
6464+ #define CAAF_USE_EXTAUDIOFILE 0
6565+ #else
6666+ // else we require Tiger and can use the API
6767+ #define CAAF_USE_EXTAUDIOFILE 1
6868+ #endif
6969+#endif
7070+7171+#ifndef MAC_OS_X_VERSION_10_4
7272+ // we have pre-Tiger headers; add our own declarations
7373+ typedef UInt32 AudioFileTypeID;
7474+ enum {
7575+ kExtAudioFileError_InvalidProperty = -66561,
7676+ kExtAudioFileError_InvalidPropertySize = -66562,
7777+ kExtAudioFileError_NonPCMClientFormat = -66563,
7878+ kExtAudioFileError_InvalidChannelMap = -66564, // number of channels doesn't match format
7979+ kExtAudioFileError_InvalidOperationOrder = -66565,
8080+ kExtAudioFileError_InvalidDataFormat = -66566,
8181+ kExtAudioFileError_MaxPacketSizeUnknown = -66567,
8282+ kExtAudioFileError_InvalidSeek = -66568, // writing, or offset out of bounds
8383+ kExtAudioFileError_AsyncWriteTooLarge = -66569,
8484+ kExtAudioFileError_AsyncWriteBufferOverflow = -66570 // an async write could not be completed in time
8585+ };
8686+#else
8787+ #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
8888+ #include <AudioToolbox/ExtendedAudioFile.h>
8989+ #else
9090+ #include "ExtendedAudioFile.h"
9191+ #endif
9292+#endif
9393+9494+// _______________________________________________________________________________________
9595+// Wrapper class for an AudioFile, supporting encode/decode to/from a PCM client format
9696+class CAAudioFile {
9797+public:
9898+ // implementation-independent helpers
9999+ void Open(const char *filePath) {
100100+ FSRef fsref;
101101+ XThrowIfError(FSPathMakeRef((UInt8 *)filePath, &fsref, NULL), "locate audio file");
102102+ Open(fsref);
103103+ }
104104+105105+ bool HasConverter() const { return GetConverter() != NULL; }
106106+107107+ double GetDurationSeconds() {
108108+ double sr = GetFileDataFormat().mSampleRate;
109109+ return fnonzero(sr) ? GetNumberFrames() / sr : 0.;
110110+ }
111111+ // will be 0 if the file's frames/packet is 0 (variable)
112112+ // or the file's sample rate is 0 (unknown)
113113+114114+#if CAAF_USE_EXTAUDIOFILE
115115+public:
116116+ CAAudioFile() : mExtAF(NULL) { }
117117+ virtual ~CAAudioFile() { if (mExtAF) Close(); }
118118+119119+ void Open(const FSRef &fsref) {
120120+ // open an existing file
121121+ XThrowIfError(ExtAudioFileOpen(&fsref, &mExtAF), "ExtAudioFileOpen failed");
122122+ }
123123+124124+ void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL) {
125125+ XThrowIfError(ExtAudioFileCreateNew(&inParentDir, inFileName, inFileType, &inStreamDesc, inChannelLayout, &mExtAF), "ExtAudioFileCreateNew failed");
126126+ }
127127+128128+ void Wrap(AudioFileID fileID, bool forWriting) {
129129+ // use this to wrap an AudioFileID opened externally
130130+ XThrowIfError(ExtAudioFileWrapAudioFileID(fileID, forWriting, &mExtAF), "ExtAudioFileWrapAudioFileID failed");
131131+ }
132132+133133+ void Close() {
134134+ XThrowIfError(ExtAudioFileDispose(mExtAF), "ExtAudioFileClose failed");
135135+ mExtAF = NULL;
136136+ }
137137+138138+ const CAStreamBasicDescription &GetFileDataFormat() {
139139+ UInt32 size = sizeof(mFileDataFormat);
140140+ XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileDataFormat, &size, &mFileDataFormat), "Couldn't get file's data format");
141141+ return mFileDataFormat;
142142+ }
143143+144144+ const CAAudioChannelLayout & GetFileChannelLayout() {
145145+ return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout);
146146+ }
147147+148148+ void SetFileChannelLayout(const CAAudioChannelLayout &layout) {
149149+ XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set file's channel layout");
150150+ mFileChannelLayout = layout;
151151+ }
152152+153153+ const CAStreamBasicDescription &GetClientDataFormat() {
154154+ UInt32 size = sizeof(mClientDataFormat);
155155+ XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, &size, &mClientDataFormat), "Couldn't get client data format");
156156+ return mClientDataFormat;
157157+ }
158158+159159+ const CAAudioChannelLayout & GetClientChannelLayout() {
160160+ return FetchChannelLayout(mClientChannelLayout, kExtAudioFileProperty_ClientChannelLayout);
161161+ }
162162+163163+ void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL) {
164164+ XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat), "Couldn't set client format");
165165+ if (layout)
166166+ SetClientChannelLayout(*layout);
167167+ }
168168+169169+ void SetClientChannelLayout(const CAAudioChannelLayout &layout) {
170170+ XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set client channel layout");
171171+ }
172172+173173+ AudioConverterRef GetConverter() const {
174174+ UInt32 size = sizeof(AudioConverterRef);
175175+ AudioConverterRef converter;
176176+ XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_AudioConverter, &size, &converter), "Couldn't get file's AudioConverter");
177177+ return converter;
178178+ }
179179+180180+ OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false)
181181+ {
182182+ OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData);
183183+ if (!inCanFail)
184184+ XThrowIfError(err, "Couldn't set audio converter property");
185185+ if (!err) {
186186+ // must tell the file that we have changed the converter; a NULL converter config is sufficient
187187+ CFPropertyListRef config = NULL;
188188+ XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config), "couldn't signal the file that the converter has changed");
189189+ }
190190+ return err;
191191+ }
192192+193193+ SInt64 GetNumberFrames() {
194194+ SInt64 length;
195195+ UInt32 size = sizeof(SInt64);
196196+ XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, &size, &length), "Couldn't get file's length");
197197+ return length;
198198+ }
199199+200200+ void SetNumberFrames(SInt64 length) {
201201+ XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, sizeof(SInt64), &length), "Couldn't set file's length");
202202+ }
203203+204204+ void Seek(SInt64 pos) {
205205+ XThrowIfError(ExtAudioFileSeek(mExtAF, pos), "Couldn't seek in audio file");
206206+ }
207207+208208+ SInt64 Tell() {
209209+ SInt64 pos;
210210+ XThrowIfError(ExtAudioFileTell(mExtAF, &pos), "Couldn't get file's mark");
211211+ return pos;
212212+ }
213213+214214+ void Read(UInt32 &ioFrames, AudioBufferList *ioData) {
215215+ XThrowIfError(ExtAudioFileRead(mExtAF, &ioFrames, ioData), "Couldn't read audio file");
216216+ }
217217+218218+ void Write(UInt32 inFrames, const AudioBufferList *inData) {
219219+ XThrowIfError(ExtAudioFileWrite(mExtAF, inFrames, inData), "Couldn't write audio file");
220220+ }
221221+222222+ void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) {
223223+ XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_IOBufferSizeBytes, sizeof(UInt32), &bufferSizeBytes), "Couldn't set audio file's I/O buffer size");
224224+ }
225225+226226+private:
227227+ const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) {
228228+ UInt32 size;
229229+ XThrowIfError(ExtAudioFileGetPropertyInfo(mExtAF, propID, &size, NULL), "Couldn't get info about channel layout");
230230+ AudioChannelLayout *layout = (AudioChannelLayout *)malloc(size);
231231+ OSStatus err = ExtAudioFileGetProperty(mExtAF, propID, &size, layout);
232232+ if (err) {
233233+ free(layout);
234234+ XThrowIfError(err, "Couldn't get channel layout");
235235+ }
236236+ layoutObj = layout;
237237+ free(layout);
238238+ return layoutObj;
239239+ }
240240+241241+242242+private:
243243+ ExtAudioFileRef mExtAF;
244244+245245+ CAStreamBasicDescription mFileDataFormat;
246246+ CAAudioChannelLayout mFileChannelLayout;
247247+248248+ CAStreamBasicDescription mClientDataFormat;
249249+ CAAudioChannelLayout mClientChannelLayout;
250250+#endif
251251+252252+#if !CAAF_USE_EXTAUDIOFILE
253253+ CAAudioFile();
254254+ virtual ~CAAudioFile();
255255+256256+ // --- second-stage initializers ---
257257+ // Use exactly one of the following:
258258+ // - Open
259259+ // - PrepareNew followed by Create
260260+ // - Wrap
261261+262262+ void Open(const FSRef &fsref);
263263+ // open an existing file
264264+265265+ void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL);
266266+267267+ void Wrap(AudioFileID fileID, bool forWriting);
268268+ // use this to wrap an AudioFileID opened externally
269269+270270+ // ---
271271+272272+ void Close();
273273+ // In case you want to close the file before the destructor executes
274274+275275+ // --- Data formats ---
276276+277277+ // Allow specifying the file's channel layout. Must be called before SetClientFormat.
278278+ // When writing, the specified channel layout is written to the file (if the file format supports
279279+ // the channel layout). When reading, the specified layout overrides the one read from the file,
280280+ // if any.
281281+ void SetFileChannelLayout(const CAAudioChannelLayout &layout);
282282+283283+ // This specifies the data format which the client will use for reading/writing the file,
284284+ // which may be different from the file's format. An AudioConverter is created if necessary.
285285+ // The client format must be linear PCM.
286286+ void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL);
287287+ void SetClientDataFormat(const CAStreamBasicDescription &dataFormat) { SetClientFormat(dataFormat, NULL); }
288288+ void SetClientChannelLayout(const CAAudioChannelLayout &layout) { SetClientFormat(mClientDataFormat, &layout); }
289289+290290+ // Wrapping the underlying converter, if there is one
291291+ OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID,
292292+ UInt32 inPropertyDataSize,
293293+ const void * inPropertyData,
294294+ bool inCanFail = false);
295295+ void SetConverterConfig(CFArrayRef config) {
296296+ SetConverterProperty(kAudioConverterPropertySettings, sizeof(config), &config); }
297297+ CFArrayRef GetConverterConfig();
298298+299299+ // --- I/O ---
300300+ // All I/O is sequential, but you can seek to an arbitrary position when reading.
301301+ // SeekToPacket and TellPacket's packet numbers are in the file's data format, not the client's.
302302+ // However, ReadPackets/WritePackets use packet counts in the client data format.
303303+304304+ void Read(UInt32 &ioNumFrames, AudioBufferList *ioData);
305305+ void Write(UInt32 numFrames, const AudioBufferList *data);
306306+307307+ // These can fail for files without a constant mFramesPerPacket
308308+ void Seek(SInt64 frameNumber);
309309+ SInt64 Tell() const; // frameNumber
310310+311311+ // --- Accessors ---
312312+ // note: client parameters only valid if SetClientFormat has been called
313313+ AudioFileID GetAudioFileID() const { return mAudioFile; }
314314+ const CAStreamBasicDescription &GetFileDataFormat() const { return mFileDataFormat; }
315315+ const CAStreamBasicDescription &GetClientDataFormat() const { return mClientDataFormat; }
316316+ const CAAudioChannelLayout & GetFileChannelLayout() const { return mFileChannelLayout; }
317317+ const CAAudioChannelLayout & GetClientChannelLayout() const { return mClientChannelLayout; }
318318+ AudioConverterRef GetConverter() const { return mConverter; }
319319+320320+ UInt32 GetFileMaxPacketSize() const { return mFileMaxPacketSize; }
321321+ UInt32 GetClientMaxPacketSize() const { return mClientMaxPacketSize; }
322322+ SInt64 GetNumberPackets() const {
323323+ SInt64 npackets;
324324+ UInt32 propertySize = sizeof(npackets);
325325+ XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &propertySize, &npackets), "get audio file's packet count");
326326+ return npackets;
327327+ }
328328+ SInt64 GetNumberFrames() const;
329329+ // will be 0 if the file's frames/packet is 0 (variable)
330330+ void SetNumberFrames(SInt64 length); // should only be set on a PCM file
331331+332332+ // --- Tunable performance parameters ---
333333+ void SetUseCache(bool b) { mUseCache = b; }
334334+ void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) { mIOBufferSizeBytes = bufferSizeBytes; }
335335+ UInt32 GetIOBufferSizeBytes() { return mIOBufferSizeBytes; }
336336+ void * GetIOBuffer() { return mIOBufferList.mBuffers[0].mData; }
337337+ void SetIOBuffer(void *buf);
338338+339339+ // -- Profiling ---
340340+#if CAAUDIOFILE_PROFILE
341341+ void EnableProfiling(bool b) { mProfiling = b; }
342342+ UInt64 TicksInConverter() const { return (mTicksInConverter > 0) ? (mTicksInConverter - mTicksInReadInConverter) : 0; }
343343+ UInt64 TicksInIO() const { return mTicksInIO; }
344344+#endif
345345+346346+// _______________________________________________________________________________________
347347+private:
348348+ SInt64 FileDataOffset();
349349+ void SeekToPacket(SInt64 packetNumber);
350350+ SInt64 TellPacket() const { return mPacketMark; } // will be imprecise if SeekToFrame was called
351351+352352+ void SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout);
353353+ void WritePacketsFromCallback(
354354+ AudioConverterComplexInputDataProc inInputDataProc,
355355+ void * inInputDataProcUserData);
356356+ // will use I/O buffer size
357357+ void InitFileMaxPacketSize();
358358+ void FileFormatChanged(const FSRef *parentDir=0, CFStringRef filename=0, AudioFileTypeID filetype=0);
359359+360360+ void GetExistingFileInfo();
361361+ void FlushEncoder();
362362+ void CloseConverter();
363363+ void UpdateClientMaxPacketSize();
364364+ void AllocateBuffers(bool okToFail=false);
365365+ SInt64 PacketToFrame(SInt64 packet) const;
366366+ SInt64 FrameToPacket(SInt64 inFrame) const;
367367+368368+ static OSStatus ReadInputProc( AudioConverterRef inAudioConverter,
369369+ UInt32* ioNumberDataPackets,
370370+ AudioBufferList* ioData,
371371+ AudioStreamPacketDescription** outDataPacketDescription,
372372+ void* inUserData);
373373+374374+ static OSStatus WriteInputProc( AudioConverterRef inAudioConverter,
375375+ UInt32* ioNumberDataPackets,
376376+ AudioBufferList* ioData,
377377+ AudioStreamPacketDescription** outDataPacketDescription,
378378+ void* inUserData);
379379+// _______________________________________________________________________________________
380380+private:
381381+382382+ // the file
383383+ FSRef mFSRef;
384384+ AudioFileID mAudioFile;
385385+ bool mOwnOpenFile;
386386+ bool mUseCache;
387387+ bool mFinishingEncoding;
388388+ enum { kClosed, kReading, kPreparingToCreate, kPreparingToWrite, kWriting } mMode;
389389+390390+// SInt64 mNumberPackets; // in file's format
391391+ SInt64 mFileDataOffset;
392392+ SInt64 mPacketMark; // in file's format
393393+ SInt64 mFrameMark; // this may be offset from the start of the file
394394+ // by the codec's latency; i.e. our frame 0 could
395395+ // lie at frame 2112 of a decoded AAC file
396396+ SInt32 mFrame0Offset;
397397+ UInt32 mFramesToSkipFollowingSeek;
398398+399399+ // buffers
400400+ UInt32 mIOBufferSizeBytes;
401401+ UInt32 mIOBufferSizePackets;
402402+ AudioBufferList mIOBufferList; // only one buffer -- USE ACCESSOR so it can be lazily initialized
403403+ bool mClientOwnsIOBuffer;
404404+ AudioStreamPacketDescription *mPacketDescs;
405405+ UInt32 mNumPacketDescs;
406406+407407+ // formats/conversion
408408+ AudioConverterRef mConverter;
409409+ CAStreamBasicDescription mFileDataFormat;
410410+ CAStreamBasicDescription mClientDataFormat;
411411+ CAAudioChannelLayout mFileChannelLayout;
412412+ CAAudioChannelLayout mClientChannelLayout;
413413+ UInt32 mFileMaxPacketSize;
414414+ UInt32 mClientMaxPacketSize;
415415+416416+ // cookie
417417+ Byte * mMagicCookie;
418418+ UInt32 mMagicCookieSize;
419419+420420+ // for ReadPackets
421421+ UInt32 mMaxPacketsToRead;
422422+423423+ // for WritePackets
424424+ UInt32 mWritePackets;
425425+ CABufferList * mWriteBufferList;
426426+427427+#if CAAUDIOFILE_PROFILE
428428+ // performance
429429+ bool mProfiling;
430430+ UInt64 mTicksInConverter;
431431+ UInt64 mTicksInReadInConverter;
432432+ UInt64 mTicksInIO;
433433+ bool mInConverter;
434434+#endif
435435+436436+#endif // CAAF_USE_EXTAUDIOFILE
437437+};
438438+439439+#endif // __CAAudioFile_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFilePlayer.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAAudioFilePlayer.h"
4444+#include "CAXException.h"
4545+4646+CAAudioFilePlayer::CAAudioFilePlayer(int nBuffers, UInt32 bufferSizeFrames) :
4747+ CAAudioFileReader(nBuffers, bufferSizeFrames),
4848+ mOutputUnit(NULL)
4949+{
5050+ // open output unit
5151+ Component comp;
5252+ ComponentDescription desc;
5353+5454+ desc.componentType = kAudioUnitType_Output;
5555+ desc.componentSubType = kAudioUnitSubType_DefaultOutput;
5656+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
5757+ desc.componentFlags = 0;
5858+ desc.componentFlagsMask = 0;
5959+ comp = FindNextComponent(NULL, &desc);
6060+6161+ // if we can't find the default one, look explicitly for AUHAL
6262+ if(comp == NULL)
6363+ {
6464+ desc.componentType = kAudioUnitType_Output;
6565+ desc.componentSubType = kAudioUnitSubType_HALOutput;
6666+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
6767+ desc.componentFlags = 0;
6868+ desc.componentFlagsMask = 0;
6969+ comp = FindNextComponent(NULL, &desc);
7070+ }
7171+7272+ XThrowIf(comp == NULL, -1, "find audio output unit");
7373+ XThrowIfError(OpenAComponent(comp, &mOutputUnit), "open audio output unit");
7474+ XThrowIfError(AudioUnitInitialize(mOutputUnit), "initialize audio output unit");
7575+7676+#if 0
7777+ AudioStreamBasicDescription theFormat;
7878+ UInt32 theSize = sizeof(AudioStreamBasicDescription);
7979+ AudioUnitGetProperty(mOutputUnit, 'sfmt', kAudioUnitScope_Output, 0, &theFormat, &theSize);
8080+8181+ theFormat.mChannelsPerFrame = 6;
8282+ theFormat.mBytesPerFrame = theFormat.mChannelsPerFrame * (theFormat.mBitsPerChannel / 8);
8383+ theFormat.mBytesPerPacket = theFormat.mBytesPerFrame;
8484+ AudioUnitSetProperty(mOutputUnit, 'sfmt', kAudioUnitScope_Output, 0, &theFormat, theSize);
8585+#endif
8686+}
8787+8888+CAAudioFilePlayer::~CAAudioFilePlayer()
8989+{
9090+ if (mOutputUnit)
9191+ CloseComponent(mOutputUnit);
9292+}
9393+9494+void CAAudioFilePlayer::SetFile(const FSRef &inFile)
9595+{
9696+ Stop();
9797+ CAAudioFileReader::SetFile(inFile);
9898+ SetupChannelMapping();
9999+}
100100+101101+void CAAudioFilePlayer::SetupChannelMapping()
102102+{
103103+ // set render callback
104104+ AURenderCallbackStruct input;
105105+ input.inputProc = InputProc;
106106+ input.inputProcRefCon = this;
107107+ XThrowIfError(AudioUnitSetProperty(
108108+ mOutputUnit,
109109+ kAudioUnitProperty_SetRenderCallback,
110110+ kAudioUnitScope_Global,
111111+ 0,
112112+ &input,
113113+ sizeof(input)), "connect input proc to output unit");
114114+115115+ const CAStreamBasicDescription &fmt = GetFile().GetClientDataFormat();
116116+ XThrowIfError(AudioUnitSetProperty(
117117+ mOutputUnit,
118118+ kAudioUnitProperty_StreamFormat,
119119+ kAudioUnitScope_Input,
120120+ 0,
121121+ (void *)&fmt,
122122+ sizeof(AudioStreamBasicDescription)), "set audio output format");
123123+ const CAAudioChannelLayout &layoutObj = GetFile().GetFileChannelLayout();
124124+ if (layoutObj.IsValid()) {
125125+ const AudioChannelLayout *layout = layoutObj;
126126+ /*OSStatus err =*/ AudioUnitSetProperty(
127127+ mOutputUnit,
128128+ kAudioUnitProperty_AudioChannelLayout,
129129+ kAudioUnitScope_Input,
130130+ 0,
131131+ layout,
132132+ layoutObj.Size());
133133+ // $$$ FIXME: why does this fail sometimes?
134134+ }
135135+}
136136+137137+void CAAudioFilePlayer::Start()
138138+{
139139+ if (IsRunning())
140140+ Stop();
141141+ if (ReachedEndOfStream())
142142+ SetCurrentPosition(0.);
143143+ CAAudioFileReader::Start();
144144+ XThrowIfError(AudioOutputUnitStart(mOutputUnit), "start audio output unit");
145145+}
146146+147147+void CAAudioFilePlayer::Stop()
148148+{
149149+ if (IsRunning()) {
150150+ XThrowIfError(AudioOutputUnitStop(mOutputUnit), "stop audio output unit");
151151+ CAAudioFileReader::Stop();
152152+ }
153153+}
154154+155155+void CAAudioFilePlayer::SetVolume(double volume)
156156+{
157157+ AudioUnitSetParameter(mOutputUnit, kHALOutputParam_Volume,
158158+ kAudioUnitScope_Global, 0, volume, 0);
159159+}
160160+161161+OSStatus CAAudioFilePlayer::GetPlayBuffer(
162162+ UInt32 inNumberFrames,
163163+ AudioBufferList * ioData)
164164+{
165165+ UInt32 nFrames = inNumberFrames;
166166+ PullBuffer(nFrames, ioData);
167167+// printf("read %ld frames\n", nFrames);
168168+ if (nFrames < inNumberFrames) {
169169+ AudioBuffer *buf = ioData->mBuffers;
170170+ UInt32 bytesPerFrame = buf->mNumberChannels * sizeof(Float32);
171171+ for (UInt32 i = 0; i < ioData->mNumberBuffers; ++i, ++buf) {
172172+ memset((Byte *)buf->mData + nFrames * bytesPerFrame, 0,
173173+ (inNumberFrames - nFrames) * bytesPerFrame);
174174+ }
175175+ }
176176+ return noErr;
177177+}
178178+179179+OSStatus CAAudioFilePlayer::InputProc(
180180+ void * inRefCon,
181181+ AudioUnitRenderActionFlags *ioActionFlags,
182182+ const AudioTimeStamp * inTimeStamp,
183183+ UInt32 inBusNumber,
184184+ UInt32 inNumberFrames,
185185+ AudioBufferList * ioData)
186186+{
187187+ CAAudioFilePlayer *This = static_cast<CAAudioFilePlayer *>(inRefCon);
188188+ return This->GetPlayBuffer(inNumberFrames, ioData);
189189+}
190190+191191+
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFilePlayer.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAAudioFilePlayer_h__
4444+#define __CAAudioFilePlayer_h__
4545+4646+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4747+ #include <AudioUnit/AudioUnit.h>
4848+#else
4949+ #include <AudioUnit.h>
5050+#endif
5151+#include "CAAudioFileStreamer.h"
5252+5353+// Simple player -- owns an output unit
5454+class CAAudioFilePlayer : public CAAudioFileReader {
5555+public:
5656+ CAAudioFilePlayer(int nBuffers, UInt32 bufferSizeFrames);
5757+ virtual ~CAAudioFilePlayer();
5858+5959+ // $$$ to add: change device, HAL I/O buffer size
6060+6161+ virtual void Start();
6262+ virtual void Stop();
6363+ void SetVolume(double volume); // 0-1
6464+6565+ void SetFile(const FSRef &inFile);
6666+6767+protected:
6868+ // our virtual methods:
6969+ virtual void SetupChannelMapping();
7070+7171+ AudioUnit GetOutputUnit() { return mOutputUnit; }
7272+7373+protected:
7474+ static OSStatus InputProc(
7575+ void * inRefCon,
7676+ AudioUnitRenderActionFlags *ioActionFlags,
7777+ const AudioTimeStamp * inTimeStamp,
7878+ UInt32 inBusNumber,
7979+ UInt32 inNumberFrames,
8080+ AudioBufferList * ioData);
8181+8282+ OSStatus GetPlayBuffer(
8383+ UInt32 inNumberFrames,
8484+ AudioBufferList * ioData);
8585+8686+ AudioUnit mOutputUnit;
8787+};
8888+8989+#endif // __CAAudioFilePlayer_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFileRecorder.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAAudioFileRecorder.h"
4444+#include "CAXException.h"
4545+4646+CAAudioFileRecorder::CAAudioFileRecorder(int nBuffers, UInt32 bufferSizeFrames) :
4747+ CAAudioFileWriter(nBuffers, bufferSizeFrames),
4848+ mInputUnit(NULL),
4949+ mAudioInputPtrs(NULL)
5050+{
5151+ // open input unit
5252+ Component comp;
5353+ ComponentDescription desc;
5454+5555+ desc.componentType = kAudioUnitType_Output;
5656+ desc.componentSubType = kAudioUnitSubType_HALOutput;
5757+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
5858+ desc.componentFlags = 0;
5959+ desc.componentFlagsMask = 0;
6060+ comp = FindNextComponent(NULL, &desc);
6161+ XThrowIf(comp == NULL, -1, "find audio input unit");
6262+ XThrowIfError(OpenAComponent(comp, &mInputUnit), "open audio input unit");
6363+6464+ UInt32 enableIO;
6565+ UInt32 propSize;
6666+6767+ enableIO = 0;
6868+ XThrowIfError(AudioUnitSetProperty(mInputUnit,
6969+ kAudioOutputUnitProperty_EnableIO,
7070+ kAudioUnitScope_Output,
7171+ 0,
7272+ &enableIO,
7373+ sizeof(enableIO)), "failed to disable output");
7474+7575+ enableIO = 1;
7676+ XThrowIfError(AudioUnitSetProperty(mInputUnit,
7777+ kAudioOutputUnitProperty_EnableIO,
7878+ kAudioUnitScope_Input,
7979+ 1,
8080+ &enableIO,
8181+ sizeof(enableIO)), "failed to enable input");
8282+8383+ // select the default input device
8484+ propSize = sizeof(AudioDeviceID);
8585+ AudioDeviceID inputDevice;
8686+ XThrowIfError(
8787+ AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propSize, &inputDevice),
8888+ "failed to get default input device");
8989+9090+ XThrowIfError(
9191+ AudioUnitSetProperty(mInputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(inputDevice)),
9292+ "failed to select input device");
9393+9494+ // set render callback
9595+ AURenderCallbackStruct input;
9696+ input.inputProc = InputProc;
9797+ input.inputProcRefCon = this;
9898+ XThrowIfError(AudioUnitSetProperty(
9999+ mInputUnit,
100100+ kAudioOutputUnitProperty_SetInputCallback,
101101+ kAudioUnitScope_Global,
102102+ 0,
103103+ &input,
104104+ sizeof(input)), "connect input proc to output unit");
105105+106106+ XThrowIfError(AudioUnitInitialize(mInputUnit), "initialize audio input unit");
107107+108108+ // get the hardware format
109109+ propSize = sizeof(mInputDataFormat);
110110+ XThrowIfError(AudioUnitGetProperty(mInputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &mInputDataFormat, &propSize), "couldn't get input unit's stream format");
111111+}
112112+113113+CAAudioFileRecorder::~CAAudioFileRecorder()
114114+{
115115+ if (mInputUnit)
116116+ CloseComponent(mInputUnit);
117117+ delete mAudioInputPtrs;
118118+}
119119+120120+void CAAudioFileRecorder::SetFile(const FSRef &parentFSRef, CFStringRef filename, AudioFileTypeID filetype, const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout)
121121+{
122122+ delete mAudioInputPtrs; mAudioInputPtrs = NULL;
123123+124124+ CAStreamBasicDescription fileDataFormat = dataFormat;
125125+ if (fileDataFormat.mSampleRate == 0.)
126126+ fileDataFormat.mSampleRate = mInputDataFormat.mSampleRate;
127127+128128+ CAAudioFileWriter::SetFile(parentFSRef, filename, filetype, fileDataFormat, layout);
129129+130130+ const CAStreamBasicDescription &fmt = GetFile().GetClientDataFormat();
131131+ XThrowIfError(AudioUnitSetProperty(
132132+ mInputUnit,
133133+ kAudioUnitProperty_StreamFormat,
134134+ kAudioUnitScope_Output,
135135+ 1,
136136+ (void *)&fmt,
137137+ sizeof(AudioStreamBasicDescription)), "set audio input format");
138138+139139+ GetFile().SetIOBufferSizeBytes(GetBufferSizeFrames() * fmt.mBytesPerFrame);
140140+141141+ mAudioInputPtrs = CABufferList::New("audio input ptrs", fmt);
142142+}
143143+144144+/*
145145+void CAAudioFileRecorder::SetFile(AudioFileID fileID)
146146+{
147147+ delete mAudioInputPtrs; mAudioInputPtrs = NULL;
148148+149149+ CAAudioFileWriter::SetFile(fileID, mInputDataFormat.mSampleRate);
150150+151151+ const CAStreamBasicDescription &fmt = GetFile().GetClientDataFormat();
152152+ XThrowIfError(AudioUnitSetProperty(
153153+ mInputUnit,
154154+ kAudioUnitProperty_StreamFormat,
155155+ kAudioUnitScope_Output,
156156+ 1,
157157+ (void *)&fmt,
158158+ sizeof(AudioStreamBasicDescription)), "set audio input format");
159159+160160+ GetFile().SetIOBufferSize(GetBufferSizeFrames() * fmt.mBytesPerFrame);
161161+162162+ mAudioInputPtrs = CABufferList::New("audio input ptrs", fmt);
163163+}
164164+*/
165165+166166+void CAAudioFileRecorder::Start()
167167+{
168168+ CAAudioFileWriter::Start();
169169+ XThrowIfError(AudioOutputUnitStart(mInputUnit), "start audio input unit");
170170+}
171171+172172+void CAAudioFileRecorder::Stop()
173173+{
174174+ XThrowIfError(AudioOutputUnitStop(mInputUnit), "stop audio input unit");
175175+ CAAudioFileWriter::Stop();
176176+}
177177+178178+OSStatus CAAudioFileRecorder::InputProc(
179179+ void * inRefCon,
180180+ AudioUnitRenderActionFlags *ioActionFlags,
181181+ const AudioTimeStamp * inTimeStamp,
182182+ UInt32 inBusNumber,
183183+ UInt32 inNumberFrames,
184184+ AudioBufferList * ioData)
185185+{
186186+ CAAudioFileRecorder *This = static_cast<CAAudioFileRecorder *>(inRefCon);
187187+ AudioUnitRenderActionFlags flags = 0;
188188+ AudioBufferList *abl = &This->mAudioInputPtrs->GetModifiableBufferList();
189189+ for (UInt32 i = 0; i < abl->mNumberBuffers; ++i)
190190+ abl->mBuffers[i].mData = NULL;
191191+ OSStatus err = AudioUnitRender(This->mInputUnit, &flags, inTimeStamp, 1, inNumberFrames, abl);
192192+ if (err)
193193+ return err;
194194+195195+ This->PushBuffer(inNumberFrames, abl);
196196+ return noErr;
197197+}
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFileRecorder.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAAudioFileRecorder_h__
4444+#define __CAAudioFileRecorder_h__
4545+4646+#include "CAAudioFileStreamer.h"
4747+#include <AudioUnit/AudioUnit.h>
4848+4949+// Simple file recorder using the HAL audio "output" unit as an input unit.
5050+class CAAudioFileRecorder : public CAAudioFileWriter {
5151+public:
5252+ CAAudioFileRecorder(int nBuffers, UInt32 bufferSizeFrames);
5353+ ~CAAudioFileRecorder();
5454+5555+ void Start();
5656+ void Stop();
5757+5858+ void SetFile(AudioFileID fileID);
5959+ void SetFile(const FSRef &parentFSRef, CFStringRef filename, AudioFileTypeID filetype, const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout);
6060+6161+ const CAStreamBasicDescription & IODataFormat() { return mInputDataFormat; }
6262+6363+protected:
6464+ static OSStatus InputProc(
6565+ void * inRefCon,
6666+ AudioUnitRenderActionFlags *ioActionFlags,
6767+ const AudioTimeStamp * inTimeStamp,
6868+ UInt32 inBusNumber,
6969+ UInt32 inNumberFrames,
7070+ AudioBufferList * ioData);
7171+7272+ AudioUnit mInputUnit;
7373+ CABufferList * mAudioInputPtrs;
7474+ CAStreamBasicDescription mInputDataFormat;
7575+};
7676+7777+#endif // __CAAudioFileRecorder_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFileStreamer.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAAudioFileStreamer.h"
4444+4545+// ____________________________________________________________________________
4646+4747+void CAAudioFileReader::FileReadBuffer::UpdateAfterRead(SInt64 curFrame, UInt32 nFrames)
4848+{
4949+ //printf("read %ld PCM packets, file packets %qd-%qd\n", nPackets, b->mStartPacket, b->mEndPacket);
5050+ mEndFrame = nFrames;
5151+ mEndOfStream = (nFrames == 0);
5252+ mBufferStartFileFrame = curFrame;
5353+}
5454+5555+// ____________________________________________________________________________
5656+5757+void CAAudioFileReader::SetFile(const FSRef &inFile)
5858+{
5959+ Stop();
6060+ CancelAndDisposeBuffers();
6161+6262+ delete mFile; mFile = NULL;
6363+ mFile = new CAAudioFile;
6464+ mFile->Open(inFile);
6565+6666+ const CAStreamBasicDescription &fileFmt = mFile->GetFileDataFormat();
6767+ CAStreamBasicDescription iofmt;
6868+ iofmt.SetCanonical(fileFmt.mChannelsPerFrame, false); // deinterleaved
6969+ iofmt.mSampleRate = fileFmt.mSampleRate;
7070+ mFile->SetClientFormat(iofmt, NULL);
7171+7272+ SetFormat(iofmt);
7373+}
7474+7575+void CAAudioFileReader::Start()
7676+{
7777+ mErrorCount = 0;
7878+ mEndOfStream = false;
7979+ Prime();
8080+ mRunning = true;
8181+}
8282+8383+void CAAudioFileReader::Stop()
8484+{
8585+ mRunning = false;
8686+}
8787+8888+void CAAudioFileReader::ReadBuffer(FileReadBuffer *b)
8989+{
9090+ b->SetEmpty();
9191+ CABufferList *ioMemory = b->GetBufferList();
9292+ CABufferList *fileBuffers = GetBufferList();
9393+ fileBuffers->SetFrom(ioMemory);
9494+ UInt32 nFrames = GetBufferSizeFrames();
9595+ SInt64 curFrame = mFile->Tell();
9696+ mFile->Read(nFrames, &fileBuffers->GetModifiableBufferList());
9797+ b->UpdateAfterRead(curFrame, nFrames);
9898+}
9999+100100+double CAAudioFileReader::GetCurrentPosition() const
101101+{
102102+ return double(GetCurrentFrame()) / double(GetNumberFrames());
103103+#if 0
104104+ double nFrames = double(GetNumberFrames()); // +1 to account for leftovers from decoder
105105+ if (!mRunning)
106106+ return double(GetCurrentFrame()) / nFrames;
107107+108108+ if (mEndOfStream) {
109109+ //printf("EOF\n");
110110+ return 1.0;
111111+ }
112112+113113+ const FileReadBuffer *b = static_cast<const FileReadBuffer *>(GetCurrentBuffer());
114114+ // the buffer from which we're reading
115115+ UInt32 startFrame, endFrame;
116116+ b->GetLocation(startFrame, endFrame);
117117+ //printf("%qd + %ld / %.f\n", b->mBufferStartFileFrame, startFrame, nFrames);
118118+ return double(b->mBufferStartFileFrame + startFrame) / nFrames;
119119+ //if (endFrame > 0) {
120120+ //double frac = (double(startFrame) / double(endFrame)) * double(endPacket - startPacket);
121121+ //packetIndex += frac;
122122+ //printf("frames %ld-%ld, packets %qd-%qd, frac %.3f\n",
123123+ // startFrame, endFrame, startPacket, endPacket, frac);
124124+ //}
125125+ //double pos = packetIndex / nPacketsPlus1;
126126+ //printf("%.3f / %.0f = %.3f\n", packetIndex, nPacketsPlus1, pos);
127127+ //return pos;
128128+129129+ //return double(GetCurrentFrame()) / nFrames;
130130+#endif
131131+}
132132+133133+SInt64 CAAudioFileReader::GetCurrentFrame() const
134134+{
135135+ if (!mRunning)
136136+ return mFile->Tell();
137137+ if (mEndOfStream)
138138+ return GetNumberFrames();
139139+ const FileReadBuffer *b = static_cast<const FileReadBuffer *>(GetCurrentBuffer());
140140+ // the buffer from which we're reading
141141+ UInt32 startFrame, endFrame;
142142+ b->GetLocation(startFrame, endFrame);
143143+ //printf("%qd + %ld / %.f\n", b->mBufferStartFileFrame, startFrame, nFrames);
144144+ return b->mBufferStartFileFrame + startFrame;
145145+}
146146+147147+void CAAudioFileReader::SetCurrentPosition(double loc)
148148+{
149149+ bool wasRunning = IsRunning();
150150+ if (wasRunning)
151151+ Stop();
152152+ SInt64 frameNumber = SInt64(loc * GetFile().GetNumberFrames() + 0.5);
153153+ try {
154154+ GetFile().Seek(frameNumber);
155155+ }
156156+ catch (...) {
157157+158158+ }
159159+ if (wasRunning)
160160+ Start();
161161+}
162162+163163+// ____________________________________________________________________________
164164+165165+void CAAudioFileWriter::SetFile(AudioFileID fileID)
166166+{
167167+ Stop();
168168+ CancelAndDisposeBuffers();
169169+170170+ delete mFile; mFile = NULL;
171171+ mFile = new CAAudioFile;
172172+ mFile->Wrap(fileID, true);
173173+174174+ const CAStreamBasicDescription &fileFmt = mFile->GetFileDataFormat();
175175+ CAStreamBasicDescription iofmt;
176176+ iofmt.SetCanonical(fileFmt.mChannelsPerFrame, false); // deinterleaved
177177+ iofmt.mSampleRate = fileFmt.mSampleRate;
178178+ mFile->SetClientFormat(iofmt, NULL);
179179+180180+ SetFormat(iofmt);
181181+}
182182+183183+void CAAudioFileWriter::SetFile(const FSRef &parentDir, CFStringRef filename, AudioFileTypeID filetype, const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout)
184184+{
185185+ Stop();
186186+ CancelAndDisposeBuffers();
187187+188188+ delete mFile; mFile = NULL;
189189+ mFile = new CAAudioFile;
190190+ mFile->CreateNew(parentDir, filename, filetype, dataFormat, layout ? &layout->Layout() : NULL);
191191+192192+ const CAStreamBasicDescription &fileFmt = mFile->GetFileDataFormat();
193193+ CAStreamBasicDescription iofmt;
194194+ iofmt.SetCanonical(fileFmt.mChannelsPerFrame, false); // deinterleaved
195195+ iofmt.mSampleRate = fileFmt.mSampleRate;
196196+ mFile->SetClientFormat(iofmt, NULL);
197197+198198+ SetFormat(iofmt);
199199+}
200200+201201+void CAAudioFileWriter::Start()
202202+{
203203+ mErrorCount = 0;
204204+ mRunning = true;
205205+}
206206+207207+void CAAudioFileWriter::Stop()
208208+{
209209+ Flush();
210210+ mRunning = false;
211211+}
212212+213213+void CAAudioFileWriter::WriteBuffer(CABufferQueue::Buffer *b)
214214+{
215215+ CABufferList *ioMemory = b->GetBufferList();
216216+ CABufferList *fileBuffers = GetBufferList();
217217+ UInt32 nFrames = b->FrameCount();
218218+ fileBuffers->SetFrom(ioMemory, GetBytesPerFrame() * nFrames);
219219+ mFile->Write(nFrames, &fileBuffers->GetModifiableBufferList());
220220+ b->SetEmpty();
221221+}
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFileStreamer.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAAudioFileStreamer_h__
4444+#define __CAAudioFileStreamer_h__
4545+4646+#include "CABufferQueue.h"
4747+#include "CAAudioFile.h"
4848+4949+// ____________________________________________________________________________
5050+// Base class for CAAudioFileReader and CAAudioFileWriter
5151+class CAAudioFileStreamer {
5252+public:
5353+ CAAudioFileStreamer() : mRunning(false), mFile(NULL) { }
5454+ virtual ~CAAudioFileStreamer() { delete mFile; }
5555+5656+ CAAudioFile & GetFile() { return *mFile; }
5757+ const CAAudioFile & GetFile() const { return *mFile; }
5858+5959+ bool IsRunning() { return mRunning; }
6060+6161+protected:
6262+ bool mRunning;
6363+ CAAudioFile * mFile;
6464+};
6565+6666+// ____________________________________________________________________________
6767+6868+class CAAudioFileReader : public CAPullBufferQueue, public CAAudioFileStreamer {
6969+public:
7070+ CAAudioFileReader(int nBuffers, UInt32 bufferSizeFrames) :
7171+ CAPullBufferQueue(nBuffers, bufferSizeFrames) { }
7272+7373+ void SetFile(const FSRef &inFile);
7474+ virtual void Start();
7575+ virtual void Stop();
7676+ double GetCurrentPosition() const; // 0-1
7777+ SInt64 GetCurrentFrame() const;// { return mFile->Tell(); }
7878+ SInt64 GetNumberFrames() const { return mFile->GetNumberFrames(); }
7979+8080+ void SetCurrentPosition(double loc); // 0-1
8181+8282+private:
8383+ class FileReadBuffer : public CABufferQueue::Buffer {
8484+ public:
8585+ FileReadBuffer(CABufferQueue *queue, const CAStreamBasicDescription &fmt, UInt32 nBytes) :
8686+ CABufferQueue::Buffer(queue, fmt, nBytes)
8787+ { }
8888+8989+ void UpdateAfterRead(SInt64 curFrame, UInt32 nFramesRead);
9090+ void GetLocation(UInt32 &frm0, UInt32 &frame1) const {
9191+ frm0 = mStartFrame; frame1 = mEndFrame;
9292+ }
9393+9494+ SInt64 mBufferStartFileFrame;
9595+ };
9696+9797+ virtual CABufferQueue::Buffer * CreateBuffer(const CAStreamBasicDescription &fmt, UInt32 nBytes) {
9898+ return new FileReadBuffer(this, fmt, nBytes);
9999+ }
100100+ virtual void ProcessBuffer(CABufferQueue::Buffer *b) {
101101+ ReadBuffer(static_cast<FileReadBuffer *>(b));
102102+ }
103103+ void ReadBuffer(FileReadBuffer *b);
104104+};
105105+106106+// ____________________________________________________________________________
107107+108108+class CAAudioFileWriter : public CAPushBufferQueue, public CAAudioFileStreamer {
109109+public:
110110+ CAAudioFileWriter(int nBuffers, UInt32 bufferSizeFrames) :
111111+ CAPushBufferQueue(nBuffers, bufferSizeFrames) { }
112112+113113+ void SetFile(AudioFileID file);
114114+ void SetFile(const FSRef &parentDir, CFStringRef filename, AudioFileTypeID filetype, const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout);
115115+ virtual void Start();
116116+ virtual void Stop();
117117+118118+private:
119119+ virtual CABufferQueue::Buffer * CreateBuffer(const CAStreamBasicDescription &fmt, UInt32 nBytes) {
120120+ return new CABufferQueue::Buffer(this, fmt, nBytes);
121121+ }
122122+ virtual void ProcessBuffer(CABufferQueue::Buffer *b) {
123123+ WriteBuffer(b);
124124+ }
125125+ void WriteBuffer(CABufferQueue::Buffer *b);
126126+};
127127+128128+#endif // __CAAudioFileStreamer_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CABufferQueue.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CABufferQueue.h"
4444+4545+#if TARGET_OS_WIN32
4646+ #include "CAWindows.h"
4747+#endif
4848+4949+// ____________________________________________________________________________
5050+5151+CABufferQueue::WorkThread *CABufferQueue::sWorkThread = NULL;
5252+5353+CABufferQueue::WorkThread::WorkThread() :
5454+ CAPThread(ThreadEntry, this, CAPThread::kMaxThreadPriority, true),
5555+ mStopped(false),
5656+ mRunGuard("CABufferQueue::mRunGuard")
5757+{
5858+ // prime the container to have some elements so we're not calling malloc dynamically
5959+ Buffer *b = NULL;
6060+ for (int i = 0; i < 64; ++i)
6161+ mWorkQueue.push_back(b);
6262+ mWorkQueue.clear();
6363+ Start();
6464+}
6565+6666+void CABufferQueue::WorkThread::Run()
6767+{
6868+ while (!mStopped) {
6969+ CAGuard::Locker lock(mRunGuard);
7070+ mRunGuard.Wait();
7171+7272+ while (!mStopped) {
7373+ Buffer *b, *next;
7474+7575+ // add buffers from the other thread
7676+ TAtomicStack<Buffer> reversed;
7777+7878+ b = mBuffersToAdd.pop_all(); // these are in reverse order
7979+ while (b != NULL) {
8080+ next = b->get_next();
8181+ reversed.push_NA(b);
8282+ b = next;
8383+ }
8484+ while ((b = reversed.pop_NA()) != NULL)
8585+ mWorkQueue.push_back(b);
8686+8787+ if (mWorkQueue.empty())
8888+ break;
8989+ b = mWorkQueue.front();
9090+ mWorkQueue.pop_front();
9191+9292+ b->Queue()->ProcessBuffer(b);
9393+ b->SetInProgress(false);
9494+ }
9595+ }
9696+}
9797+9898+void CABufferQueue::WorkThread::Stop()
9999+{
100100+ mStopped = true;
101101+ mRunGuard.Notify();
102102+}
103103+104104+void CABufferQueue::WorkThread::AddBuffer(Buffer *b)
105105+{
106106+ b->SetInProgress(true);
107107+ mBuffersToAdd.push_atomic(b);
108108+ mRunGuard.Notify();
109109+}
110110+111111+void CABufferQueue::WorkThread::RemoveBuffers(CABufferQueue *owner)
112112+{
113113+ CAGuard::Locker lock(mRunGuard);
114114+ for (WorkQueue::iterator it = mWorkQueue.begin(); it != mWorkQueue.end(); ) {
115115+ if ((*it)->Queue() == owner) {
116116+ WorkQueue::iterator next = it; ++next;
117117+ mWorkQueue.erase(it);
118118+ it = next;
119119+ } else
120120+ ++it;
121121+ }
122122+}
123123+124124+// ____________________________________________________________________________
125125+126126+CABufferQueue::Buffer::Buffer(CABufferQueue *queue, const CAStreamBasicDescription &fmt, UInt32 nBytes) :
127127+ mQueue(queue)
128128+{
129129+ mMemory = CABufferList::New("", fmt);
130130+ mMemory->AllocateBuffers(nBytes);
131131+ mByteSize = nBytes;
132132+ mInProgress = false;
133133+ mStartFrame = mEndFrame = 0;
134134+ mEndOfStream = false;
135135+}
136136+137137+// return true if buffer emptied AND we're not at end-of-stream
138138+bool CABufferQueue::Buffer::CopyInto(AudioBufferList *destBufferList, int bytesPerFrame, UInt32 &framesProduced, UInt32 &framesRequired)
139139+{
140140+ UInt32 framesInBuffer = mEndFrame - mStartFrame;
141141+ UInt32 framesToCopy = std::min(framesInBuffer, framesRequired);
142142+ if (framesToCopy > 0) {
143143+ const CABufferList *bufMemory = mMemory;
144144+ const AudioBufferList &srcBufferList = bufMemory->GetBufferList();
145145+ const AudioBuffer *srcbuf = srcBufferList.mBuffers;
146146+ AudioBuffer *dstbuf = destBufferList->mBuffers;
147147+ for (int i = destBufferList->mNumberBuffers; --i >= 0; ++srcbuf, ++dstbuf) {
148148+ memcpy(
149149+ (Byte *)dstbuf->mData + framesProduced * bytesPerFrame,
150150+ (Byte *)srcbuf->mData + mStartFrame * bytesPerFrame,
151151+ framesToCopy * bytesPerFrame);
152152+ }
153153+ framesProduced += framesToCopy;
154154+ framesRequired -= framesToCopy;
155155+ mStartFrame += framesToCopy;
156156+ }
157157+ return (framesToCopy == framesInBuffer) && !mEndOfStream;
158158+}
159159+160160+// return true if buffer filled
161161+bool CABufferQueue::Buffer::CopyFrom(const AudioBufferList *srcBufferList, int bytesPerFrame, UInt32 &framesProduced, UInt32 &framesRequired)
162162+{
163163+ UInt32 framesInBuffer = mEndFrame - mStartFrame;
164164+ UInt32 freeFramesInBuffer = (mByteSize / bytesPerFrame) - framesInBuffer;
165165+ UInt32 framesToCopy = std::min(freeFramesInBuffer, framesRequired);
166166+ if (framesToCopy > 0) {
167167+ const AudioBuffer *srcbuf = srcBufferList->mBuffers;
168168+ const CABufferList *bufMemory = mMemory;
169169+ const AudioBufferList &destBufferList = bufMemory->GetBufferList();
170170+ const AudioBuffer *dstbuf = destBufferList.mBuffers;
171171+ for (int i = srcBufferList->mNumberBuffers; --i >= 0; ++srcbuf, ++dstbuf) {
172172+ memcpy(
173173+ (Byte *)dstbuf->mData + framesInBuffer * bytesPerFrame,
174174+ (Byte *)srcbuf->mData + framesProduced * bytesPerFrame,
175175+ framesToCopy * bytesPerFrame);
176176+ }
177177+ framesProduced += framesToCopy;
178178+ framesRequired -= framesToCopy;
179179+ mEndFrame += framesToCopy;
180180+ }
181181+ return (framesToCopy == freeFramesInBuffer);
182182+}
183183+184184+// ____________________________________________________________________________
185185+186186+CABufferQueue::CABufferQueue(int nBuffers, UInt32 bufferSizeFrames) :
187187+ mNumberBuffers(nBuffers),
188188+ mBuffers(NULL),
189189+ mBufferSizeFrames(bufferSizeFrames),
190190+ mBufferList(NULL)
191191+{
192192+ mCurrentBuffer = 0;
193193+ mErrorCount = 0;
194194+195195+ if (sWorkThread == NULL)
196196+ sWorkThread = new WorkThread();
197197+ mWorkThread = sWorkThread; // for now
198198+}
199199+200200+CABufferQueue::~CABufferQueue()
201201+{
202202+ CancelAndDisposeBuffers();
203203+}
204204+205205+void CABufferQueue::CancelBuffers()
206206+{
207207+ mWorkThread->RemoveBuffers(this);
208208+}
209209+210210+void CABufferQueue::CancelAndDisposeBuffers()
211211+{
212212+ CancelBuffers();
213213+ if (mBuffers) {
214214+ for (int i = 0; i < mNumberBuffers; ++i)
215215+ delete mBuffers[i];
216216+ delete[] mBuffers; mBuffers = NULL;
217217+ }
218218+ delete mBufferList; mBufferList = NULL;
219219+}
220220+221221+void CABufferQueue::SetFormat(const CAStreamBasicDescription &fmt)
222222+{
223223+ CancelAndDisposeBuffers();
224224+225225+ mBytesPerFrame = fmt.mBytesPerFrame;
226226+ mBuffers = new Buffer*[mNumberBuffers];
227227+ for (int i = 0; i < mNumberBuffers; ++i)
228228+ mBuffers[i] = CreateBuffer(fmt, mBufferSizeFrames * mBytesPerFrame);
229229+ mBufferList = CABufferList::New("", fmt);
230230+}
231231+232232+// ____________________________________________________________________________
233233+234234+void CAPushBufferQueue::PushBuffer(UInt32 inNumberFrames, const AudioBufferList *inBufferList)
235235+{
236236+ UInt32 framesRequired = inNumberFrames;
237237+ UInt32 framesProduced = 0;
238238+239239+ do {
240240+ Buffer *b = mBuffers[mCurrentBuffer];
241241+242242+ if (b->InProgress()) {
243243+ ++mErrorCount;
244244+ break;
245245+ }
246246+247247+ if (b->CopyFrom(inBufferList, mBytesPerFrame, framesProduced, framesRequired)) {
248248+ // buffer was filled, we're done with it
249249+ sWorkThread->AddBuffer(b);
250250+ if (++mCurrentBuffer == mNumberBuffers)
251251+ mCurrentBuffer = 0;
252252+ }
253253+ } while (framesRequired > 0);
254254+}
255255+256256+void CAPushBufferQueue::Flush()
257257+{
258258+ if (mBuffers != NULL) {
259259+ Buffer *b = mBuffers[mCurrentBuffer];
260260+ if (b->FrameCount() > 0 && !b->InProgress())
261261+ ProcessBuffer(b);
262262+ }
263263+}
264264+265265+// ____________________________________________________________________________
266266+267267+void CAPullBufferQueue::PullBuffer(UInt32 &ioFrames, AudioBufferList *outBufferList)
268268+{
269269+ if (mEndOfStream) {
270270+ ioFrames = 0;
271271+ return;
272272+ }
273273+ UInt32 framesRequired = ioFrames;
274274+ UInt32 framesProduced = 0;
275275+276276+ do {
277277+ Buffer *b = mBuffers[mCurrentBuffer];
278278+279279+ if (b->InProgress()) {
280280+ ++mErrorCount;
281281+ break;
282282+ }
283283+284284+ if (b->CopyInto(outBufferList, mBytesPerFrame, framesProduced, framesRequired)) {
285285+ // buffer emptied
286286+ sWorkThread->AddBuffer(b);
287287+288288+ if (++mCurrentBuffer == mNumberBuffers)
289289+ mCurrentBuffer = 0;
290290+ }
291291+ else if (b->ReachedEndOfStream()) {
292292+ mEndOfStream = true;
293293+ break;
294294+ }
295295+ } while (framesRequired > 0);
296296+ ioFrames = framesProduced;
297297+}
298298+299299+void CAPullBufferQueue::Prime()
300300+{
301301+ mEndOfStream = false;
302302+ for (int i = 0; i < mNumberBuffers; ++i) {
303303+ Buffer *b = mBuffers[i];
304304+ ProcessBuffer(b);
305305+ b->SetInProgress(false);
306306+ }
307307+ mCurrentBuffer = 0;
308308+}
309309+
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CABufferQueue.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CABufferQueue_h__
4444+#define __CABufferQueue_h__
4545+4646+#include "CAPThread.h"
4747+#include "CAGuard.h"
4848+#include "CAStreamBasicDescription.h"
4949+#include "CABufferList.h"
5050+#include <list>
5151+#include "CAAtomicStack.h"
5252+5353+// ____________________________________________________________________________
5454+5555+// Abstraction for moving audio buffers between threads.
5656+// Has abstract subclasses for push and pull.
5757+class CABufferQueue {
5858+ friend class CAPushBufferQueue;
5959+ friend class CAPullBufferQueue;
6060+public:
6161+ CABufferQueue(int nBuffers, UInt32 bufferSizeFrames);
6262+ virtual ~CABufferQueue();
6363+6464+ void SetFormat(const CAStreamBasicDescription &fmt);
6565+ UInt32 GetBufferSizeFrames() const { return mBufferSizeFrames; }
6666+ int ErrorCount() const { return mErrorCount; }
6767+6868+ // -----
6969+ class Buffer {
7070+ public:
7171+ Buffer(CABufferQueue *owner, const CAStreamBasicDescription &fmt, UInt32 nBytes);
7272+7373+ ~Buffer() { delete mMemory; }
7474+7575+ CABufferQueue * Queue() { return mQueue; }
7676+ CABufferList * GetBufferList() { return mMemory; }
7777+ UInt32 FrameCount() { return mEndFrame - mStartFrame; }
7878+ void SetEmpty() { mStartFrame = mEndFrame = 0; }
7979+8080+ void SetInProgress(bool b) { mInProgress = b; }
8181+ bool InProgress() const { return mInProgress; }
8282+ bool ReachedEndOfStream() const { return mEndOfStream; }
8383+8484+ bool CopyInto(AudioBufferList *destBufferList, int bytesPerFrame, UInt32 &framesProduced, UInt32 &framesRequired); // return true if buffer emptied
8585+8686+ bool CopyFrom(const AudioBufferList *srcBufferList, int bytesPerFrame, UInt32 &framesProduced, UInt32 &framesRequired); // return true if buffer filled and not end-of-stream
8787+8888+ Buffer * get_next() { return mNext; }
8989+ void set_next(Buffer *b) { mNext = b; }
9090+ Buffer *& next() { return mNext; }
9191+9292+#if DEBUG
9393+ void print() {
9494+ printf("Buffer %p:\n inProgress %d, endOfStream %d, frames %ld-%ld\n", this, mInProgress, mEndOfStream, mStartFrame, mEndFrame);
9595+ }
9696+#endif
9797+9898+ protected:
9999+ Buffer * mNext;
100100+ CABufferQueue * mQueue;
101101+ CABufferList * mMemory;
102102+ UInt32 mByteSize;
103103+104104+ bool mInProgress; // true if in the work queue
105105+ bool mEndOfStream; // true if the operation resulted in end-of-stream
106106+ UInt32 mStartFrame, mEndFrame; // produce/consume pointers within the buffer
107107+ };
108108+109109+#if DEBUG
110110+ void print() {
111111+ printf("BufferQueue %p\n mCurrentBuffer=%d\n", this, mCurrentBuffer);
112112+ if (mBuffers)
113113+ for (int i = 0; i < mNumberBuffers; ++i) {
114114+ Buffer *b = mBuffers[i];
115115+ printf(" buffer[%d]: ", i);
116116+ if (b)
117117+ b->print();
118118+ else printf("NULL\n");
119119+ }
120120+ }
121121+#endif
122122+123123+protected:
124124+ virtual Buffer * CreateBuffer(const CAStreamBasicDescription &fmt, UInt32 nBytes) = 0;
125125+ virtual void ProcessBuffer(Buffer *b) = 0;
126126+ void CancelBuffers();
127127+ void CancelAndDisposeBuffers();
128128+129129+ CABufferList * GetBufferList() { return mBufferList; }
130130+ const Buffer * GetCurrentBuffer() const { return mBuffers[mCurrentBuffer]; }
131131+ UInt32 GetBytesPerFrame() const { return mBytesPerFrame; }
132132+133133+private:
134134+135135+ // -----
136136+ class WorkThread : public CAPThread {
137137+ public:
138138+ WorkThread();
139139+140140+ static void * ThreadEntry(void *param)
141141+ {
142142+ static_cast<WorkThread *>(param)->Run();
143143+ return NULL;
144144+ }
145145+ void Run();
146146+ void Stop();
147147+148148+ void AddBuffer(Buffer *buffer);
149149+ void RemoveBuffers(CABufferQueue *owner);
150150+151151+ private:
152152+ typedef std::list<Buffer *> WorkQueue;
153153+154154+ bool mStopped;
155155+ WorkQueue mWorkQueue;
156156+ CAGuard mRunGuard;
157157+ TAtomicStack<Buffer> mBuffersToAdd;
158158+ };
159159+160160+ static WorkThread * sWorkThread;
161161+162162+ // -----
163163+private:
164164+ WorkThread * mWorkThread;
165165+166166+ int mCurrentBuffer;
167167+ int mNumberBuffers;
168168+ Buffer ** mBuffers; // array of pointers
169169+ UInt32 mBufferSizeFrames;
170170+ UInt32 mBytesPerFrame; // function of client format
171171+ CABufferList * mBufferList; // maintained in SetFormat
172172+protected:
173173+ int mErrorCount;
174174+};
175175+176176+// ____________________________________________________________________________
177177+178178+// Abstract class.
179179+// The client pushes buffers in; they are consumed (via ProcessBuffer) on the work thread.
180180+// (ex: file recorder)
181181+class CAPushBufferQueue : public CABufferQueue {
182182+public:
183183+ CAPushBufferQueue(int nBuffers, UInt32 bufferSizeFrames) :
184184+ CABufferQueue(nBuffers, bufferSizeFrames) { }
185185+186186+ void PushBuffer(UInt32 inNumberFrames, const AudioBufferList *inBufferList);
187187+ // push a buffer in
188188+ void Flush();
189189+ // emit a possibly incomplete final buffer
190190+};
191191+192192+// ____________________________________________________________________________
193193+194194+// Abstract class.
195195+// The client pulls buffers out; they are produced (via ProcessBuffer) on the work thread.
196196+// (ex: file player)
197197+class CAPullBufferQueue : public CABufferQueue {
198198+public:
199199+ CAPullBufferQueue(int nBuffers, UInt32 bufferSizeFrames) :
200200+ CABufferQueue(nBuffers, bufferSizeFrames),
201201+ mEndOfStream(false) { }
202202+203203+ void Prime();
204204+ // produce initial buffers
205205+ void PullBuffer(UInt32 &ioFrames, AudioBufferList *outBufferList);
206206+ // pull a buffer out
207207+ bool ReachedEndOfStream() const { return mEndOfStream; }
208208+209209+protected:
210210+ bool mEndOfStream;
211211+};
212212+213213+#endif // __CABufferQueue_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAChannelMapper.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAChannelMapper.h"
4444+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4545+ #include <AudioToolbox/AudioToolbox.h>
4646+#else
4747+ #include <AudioToolbox.h>
4848+#endif
4949+5050+static void DefaultChannelLayout(CAAudioChannelLayout &layout, UInt32 nchannels)
5151+{
5252+ // we really can't do a sensible downmix without valid source/destination channel layouts
5353+ if (nchannels == 1)
5454+ layout = CAAudioChannelLayout(kAudioChannelLayoutTag_Mono);
5555+ else if (nchannels == 2)
5656+ layout = CAAudioChannelLayout(kAudioChannelLayoutTag_Stereo);
5757+}
5858+5959+CAChannelMapper::CAChannelMapper( const CAStreamBasicDescription &srcFormat,
6060+ const CAStreamBasicDescription &destFormat,
6161+ const CAAudioChannelLayout * inSrcLayout,
6262+ const CAAudioChannelLayout * inDestLayout) :
6363+ mSrcNChannels(srcFormat.mChannelsPerFrame),
6464+ mDestNChannels(destFormat.mChannelsPerFrame)
6565+{
6666+ if (inSrcLayout && inSrcLayout->IsValid())
6767+ mSrcLayout = *inSrcLayout;
6868+ else
6969+ DefaultChannelLayout(mSrcLayout, srcFormat.mChannelsPerFrame);
7070+7171+ if (inDestLayout && inDestLayout->IsValid())
7272+ mDestLayout = *inDestLayout;
7373+ else
7474+ DefaultChannelLayout(mDestLayout, destFormat.mChannelsPerFrame);
7575+}
7676+7777+CAChannelMapper::~CAChannelMapper()
7878+{
7979+ if (mMatrixMixer)
8080+ CloseComponent(mMatrixMixer);
8181+}
8282+8383+OSStatus CAChannelMapper::OpenMixer(double sampleRate)
8484+{
8585+ CAComponent comp(kAudioUnitType_Mixer, kAudioUnitSubType_MatrixMixer, kAudioUnitManufacturer_Apple);
8686+ OSStatus err;
8787+8888+ err = CAAudioUnit::Open(comp, mMatrixMixer);
8989+ if (err) return err;
9090+9191+ CAStreamBasicDescription fmt;
9292+ fmt.mSampleRate = sampleRate;
9393+ UInt32 nbuses = 1;
9494+9595+ err = mMatrixMixer.SetProperty(kAudioUnitProperty_BusCount, kAudioUnitScope_Input, 0, &nbuses, sizeof(UInt32));
9696+ if (err) return err;
9797+ err = mMatrixMixer.SetProperty(kAudioUnitProperty_BusCount, kAudioUnitScope_Output, 0, &nbuses, sizeof(UInt32));
9898+ if (err) return err;
9999+100100+ fmt.SetCanonical(mSrcNChannels, false);
101101+ err = mMatrixMixer.SetFormat(kAudioUnitScope_Input, 0, fmt);
102102+ if (err) return err;
103103+104104+ fmt.SetCanonical(mDestNChannels, false);
105105+ err = mMatrixMixer.SetFormat(kAudioUnitScope_Output, 0, fmt);
106106+ if (err) return err;
107107+108108+ // set render callback
109109+ AURenderCallbackStruct input;
110110+ input.inputProc = MixerInputProc;
111111+ input.inputProcRefCon = this;
112112+ err = mMatrixMixer.SetProperty(
113113+ kAudioUnitProperty_SetRenderCallback,
114114+ kAudioUnitScope_Global,
115115+ 0,
116116+ &input,
117117+ sizeof(input));
118118+119119+ err = mMatrixMixer.Initialize();
120120+ if (err) return err;
121121+122122+ return ResetMixer();
123123+}
124124+125125+OSStatus CAChannelMapper::ResetMixer()
126126+{
127127+ int nin = mSrcNChannels, nout = mDestNChannels;
128128+ int i, j;
129129+130130+ // set global, input and output volumes
131131+ mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFFFFFF, 1.);
132132+ for (i = 0; i < nout; ++i) {
133133+ mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFF0000 | i, 1.);
134134+ }
135135+ for (i = 0; i < nin; ++i) {
136136+ mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global, (i<<16) | 0xFFFF, 1.);
137137+ }
138138+ // set crosspoint volumes
139139+ for (i = 0; i < nin; ++i) {
140140+ for (j = 0; j < nout; ++j) {
141141+ mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global, (i<<16) | j, 0.);
142142+ }
143143+ }
144144+ return noErr;
145145+}
146146+147147+OSStatus CAChannelMapper::ConfigureDownmix()
148148+{
149149+ OSStatus err = ResetMixer();
150150+ if (err)
151151+ return err;
152152+153153+ const AudioChannelLayout *layouts[] = { &mSrcLayout.Layout(), &mDestLayout.Layout() };
154154+ UInt32 propSize;
155155+ err = AudioFormatGetPropertyInfo(kAudioFormatProperty_MatrixMixMap, sizeof(layouts), layouts, &propSize);
156156+ if (err)
157157+ return err;
158158+159159+ void *mixmap = malloc(propSize);
160160+ err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(layouts), layouts, &propSize, mixmap);
161161+ if (!err) {
162162+ mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFFFFFF, 1.);
163163+ int nin = mSrcNChannels, nout = mDestNChannels;
164164+ int i, j;
165165+ // set the crosspoint volumes
166166+ Float32 *val = (Float32 *)mixmap;
167167+ for (i = 0; i < nin; ++i) {
168168+ for (j = 0; j < nout; ++j) {
169169+ mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global, (i<<16) | j, *val++);
170170+ }
171171+ }
172172+ }
173173+ free(mixmap);
174174+ return noErr;
175175+}
176176+177177+OSStatus CAChannelMapper::ConnectChannelToChannel(UInt32 inChannel, UInt32 outChannel)
178178+{
179179+ return mMatrixMixer.SetParameter(kMatrixMixerParam_Volume, kAudioUnitScope_Global,
180180+ (inChannel << 16) | outChannel, 1.);
181181+}
182182+183183+OSStatus CAChannelMapper::Mix(const AudioBufferList *src, AudioBufferList *dest, UInt32 nFrames)
184184+{
185185+ mMixInputBufferList = src;
186186+ AudioUnitRenderActionFlags flags = 0;
187187+ AudioTimeStamp ts;
188188+ ts.mFlags = 0;
189189+ return AudioUnitRender(mMatrixMixer.AU(), &flags, &ts, 0, nFrames, dest);
190190+}
191191+192192+OSStatus CAChannelMapper::MixerInputProc(
193193+ void * inRefCon,
194194+ AudioUnitRenderActionFlags *ioActionFlags,
195195+ const AudioTimeStamp * inTimeStamp,
196196+ UInt32 inBusNumber,
197197+ UInt32 inNumberFrames,
198198+ AudioBufferList * ioData)
199199+{
200200+ CAChannelMapper *This = static_cast<CAChannelMapper *>(inRefCon);
201201+ const AudioBufferList *mixInputBufferList = This->mMixInputBufferList;
202202+ UInt32 copySize = sizeof(UInt32) + (mixInputBufferList->mNumberBuffers * sizeof(AudioBuffer));
203203+ memcpy(ioData, mixInputBufferList, copySize);
204204+205205+ return noErr;
206206+}
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAChannelMapper.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAChannelMapper_h__
4444+#define __CAChannelMapper_h__
4545+4646+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4747+ #include <AudioUnit/AudioUnit.h>
4848+#else
4949+ #include <AudioUnit.h>
5050+#endif
5151+#include "CAAudioChannelLayout.h"
5252+#include "CAStreamBasicDescription.h"
5353+#include "CAAudioUnit.h"
5454+#include "MatrixMixerVolumes.h"
5555+5656+class CAChannelMapper {
5757+public:
5858+ CAChannelMapper(const CAStreamBasicDescription &srcFormat,
5959+ const CAStreamBasicDescription &destFormat,
6060+ const CAAudioChannelLayout * srcLayout = NULL,
6161+ const CAAudioChannelLayout * destLayout = NULL);
6262+ ~CAChannelMapper();
6363+6464+ UInt32 NumSourceChannels() { return mSrcNChannels; }
6565+ UInt32 NumDestChannels() { return mDestNChannels; }
6666+ const CAAudioChannelLayout &SourceLayout() { return mSrcLayout; }
6767+ const CAAudioChannelLayout &DestLayout() { return mDestLayout; }
6868+ AudioUnit GetMixer() { return mMatrixMixer.AU(); }
6969+7070+ bool CanDownmix() { return mSrcLayout.IsValid() && mDestLayout.IsValid(); }
7171+ OSStatus OpenMixer(double sampleRate);
7272+ OSStatus ResetMixer(); // enables all ins/outs, zeroes all crosspoints
7373+ OSStatus ConfigureDownmix();
7474+ OSStatus ConnectChannelToChannel(UInt32 inChannel, UInt32 outChannel);
7575+ OSStatus Mix(const AudioBufferList *src, AudioBufferList *dest, UInt32 nFrames);
7676+ void PrintMatrixMixerVolumes(FILE *f) { ::PrintMatrixMixerVolumes(f, mMatrixMixer.AU()); }
7777+7878+private:
7979+ static OSStatus MixerInputProc(
8080+ void * inRefCon,
8181+ AudioUnitRenderActionFlags *ioActionFlags,
8282+ const AudioTimeStamp * inTimeStamp,
8383+ UInt32 inBusNumber,
8484+ UInt32 inNumberFrames,
8585+ AudioBufferList * ioData);
8686+8787+ UInt32 mSrcNChannels, mDestNChannels;
8888+ CAAudioChannelLayout mSrcLayout, mDestLayout;
8989+ CAAudioUnit mMatrixMixer;
9090+ const AudioBufferList * mMixInputBufferList;
9191+};
9292+9393+#endif // __CAChannelMapper_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAChannelMappingPlayer.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAChannelMappingPlayer.h"
4444+#include "CAXException.h"
4545+4646+#if DEBUG
4747+ #define VERBOSE 1
4848+#endif
4949+5050+CAChannelMappingPlayer::CAChannelMappingPlayer(int nBuffers, UInt32 bufferSizeFrames) :
5151+ CAAudioFilePlayer(nBuffers, bufferSizeFrames),
5252+ mMapper(NULL)
5353+{
5454+}
5555+5656+CAChannelMappingPlayer::~CAChannelMappingPlayer()
5757+{
5858+ delete mMapper;
5959+}
6060+6161+void CAChannelMappingPlayer::SetupChannelMapping()
6262+{
6363+ delete mMapper;
6464+ mMapper = NULL;
6565+6666+ const CAStreamBasicDescription &fileFormat = GetFile().GetClientDataFormat();
6767+ CAStreamBasicDescription deviceFormat;
6868+ UInt32 propertySize = sizeof(AudioStreamBasicDescription);
6969+7070+ XThrowIfError(AudioUnitGetProperty(
7171+ GetOutputUnit(),
7272+ kAudioUnitProperty_StreamFormat,
7373+ kAudioUnitScope_Output,
7474+ 0,
7575+ (void *)&deviceFormat,
7676+ &propertySize), "get output device's format");
7777+7878+#if VERBOSE
7979+ printf("CAChannelMappingPlayer::SetupChannelMapping: %ld-ch file, %ld-ch device\n",
8080+ fileFormat.mChannelsPerFrame, deviceFormat.mChannelsPerFrame);
8181+#endif
8282+8383+ if (fileFormat.mChannelsPerFrame <= deviceFormat.mChannelsPerFrame) {
8484+ // no mapping needed, use output unit's default behavior
8585+ // (default stereo pair and speaker config from AMS)
8686+#if VERBOSE
8787+ printf(" using output unit's channel mapping\n");
8888+#endif
8989+ CAAudioFilePlayer::SetupChannelMapping();
9090+ } else {
9191+ // fewer device than file channels, mapping needed
9292+ CAAudioChannelLayout fileLayout, deviceLayout;
9393+9494+#if VERBOSE
9595+ printf(" using our own channel mapping\n");
9696+#endif
9797+ deviceFormat.mSampleRate = fileFormat.mSampleRate;
9898+ deviceFormat.SetCanonical(deviceFormat.mChannelsPerFrame, false); // force deinterleaved
9999+100100+ fileLayout = GetFile().GetFileChannelLayout();
101101+102102+ UInt32 layoutSize;
103103+ Boolean writable;
104104+ OSStatus err = AudioUnitGetPropertyInfo(
105105+ GetOutputUnit(),
106106+ kAudioUnitProperty_AudioChannelLayout,
107107+ kAudioUnitScope_Input,
108108+ 0,
109109+ &layoutSize,
110110+ &writable);
111111+ if (!err) {
112112+ char *buf = (char *)malloc(layoutSize);
113113+ err = AudioUnitGetProperty(
114114+ GetOutputUnit(),
115115+ kAudioUnitProperty_AudioChannelLayout,
116116+ kAudioUnitScope_Input,
117117+ 0,
118118+ buf,
119119+ &layoutSize);
120120+ deviceLayout = CAAudioChannelLayout(reinterpret_cast<AudioChannelLayout *>(buf));
121121+ free(buf);
122122+ }
123123+ mMapper = new CAChannelMapper(fileFormat, deviceFormat, &fileLayout, &deviceLayout);
124124+125125+ // give the output unit the same number of channels as in the device,
126126+ // since we'll be doing the mapping ourselves
127127+ XThrowIfError(AudioUnitSetProperty(
128128+ GetOutputUnit(),
129129+ kAudioUnitProperty_StreamFormat,
130130+ kAudioUnitScope_Input,
131131+ 0,
132132+ (void *)&deviceFormat,
133133+ sizeof(AudioStreamBasicDescription)), "set audio output format");
134134+135135+ XThrowIfError(mMapper->OpenMixer(fileFormat.mSampleRate), "open mixer");
136136+ XThrowIfError(mMapper->ConfigureDownmix(), "configure downmix");
137137+138138+ AudioUnitConnection conn;
139139+ conn.sourceAudioUnit = mMapper->GetMixer();
140140+ conn.sourceOutputNumber = 0;
141141+ conn.destInputNumber = 0;
142142+143143+ XThrowIfError(AudioUnitSetProperty(
144144+ GetOutputUnit(),
145145+ kAudioUnitProperty_MakeConnection,
146146+ kAudioUnitScope_Global,
147147+ 0,
148148+ (void *)&conn,
149149+ sizeof(AudioUnitConnection)), "connect mixer to output unit");
150150+151151+ AURenderCallbackStruct input;
152152+ input.inputProc = InputProc;
153153+ input.inputProcRefCon = this;
154154+ XThrowIfError(AudioUnitSetProperty(
155155+ conn.sourceAudioUnit,
156156+ kAudioUnitProperty_SetRenderCallback,
157157+ kAudioUnitScope_Global,
158158+ 0,
159159+ &input,
160160+ sizeof(input)), "connect input proc to mixer");
161161+ // provide NO channel layout
162162+// mReadBuf = CABufferList::New("", fileFormat);
163163+// mReadBuf->AllocateBuffers(
164164+ }
165165+}
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAChannelMappingPlayer.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAChannelMappingPlayer_h__
4444+#define __CAChannelMappingPlayer_h__
4545+4646+#include "CAAudioFilePlayer.h"
4747+#include "CAChannelMapper.h"
4848+4949+// Specialization of CAAudioFilePlayer to perform channel remapping or downmixing.
5050+class CAChannelMappingPlayer : public CAAudioFilePlayer {
5151+public:
5252+ CAChannelMappingPlayer(int nBuffers, UInt32 bufferSizeFrames);
5353+ ~CAChannelMappingPlayer();
5454+5555+ // CAAudioFilePlayer overrides:
5656+ virtual void SetupChannelMapping();
5757+5858+ CAChannelMapper * GetMapper() { return mMapper; }
5959+6060+private:
6161+ CAChannelMapper * mMapper;
6262+};
6363+6464+6565+#endif // __CAChannelMappingPlayer_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*==================================================================================================
3939+ CAGuard.cpp
4040+4141+==================================================================================================*/
4242+4343+//==================================================================================================
4444+// Includes
4545+//==================================================================================================
4646+4747+// Self Include
4848+#include "CAGuard.h"
4949+5050+#if TARGET_OS_MAC
5151+ #include <errno.h>
5252+#endif
5353+5454+// PublicUtility Inludes
5555+#include "CADebugMacros.h"
5656+#include "CAException.h"
5757+#include "CAHostTimeBase.h"
5858+5959+//==================================================================================================
6060+// Logging
6161+//==================================================================================================
6262+6363+#if CoreAudio_Debug
6464+// #define Log_Ownership 1
6565+// #define Log_WaitOwnership 1
6666+// #define Log_TimedWaits 1
6767+// #define Log_Latency 1
6868+// #define Log_Errors 1
6969+#endif
7070+7171+//#warning Need a try-based Locker too
7272+//==================================================================================================
7373+// CAGuard
7474+//==================================================================================================
7575+7676+CAGuard::CAGuard(const char* inName)
7777+:
7878+ CAMutex(inName)
7979+#if Log_Average_Latency
8080+ ,mAverageLatencyAccumulator(0.0),
8181+ mAverageLatencyCount(0)
8282+#endif
8383+{
8484+#if TARGET_OS_MAC
8585+ OSStatus theError = pthread_cond_init(&mCondVar, NULL);
8686+ ThrowIf(theError != 0, CAException(theError), "CAGuard::CAGuard: Could not init the cond var");
8787+#elif TARGET_OS_WIN32
8888+ mEvent = CreateEvent(NULL, true, false, NULL);
8989+ ThrowIfNULL(mEvent, CAException(GetLastError()), "CAGuard::CAGuard: Could not create the event");
9090+#endif
9191+}
9292+9393+CAGuard::~CAGuard()
9494+{
9595+#if TARGET_OS_MAC
9696+ pthread_cond_destroy(&mCondVar);
9797+#elif TARGET_OS_WIN32
9898+ if(mEvent != NULL)
9999+ {
100100+ CloseHandle(mEvent);
101101+ }
102102+#endif
103103+}
104104+105105+void CAGuard::Wait()
106106+{
107107+#if TARGET_OS_MAC
108108+ ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
109109+110110+ mOwner = 0;
111111+112112+ #if Log_WaitOwnership
113113+ DebugPrintfRtn(DebugPrintfFile, "%p %.4f: CAGuard::Wait: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
114114+ #endif
115115+116116+ OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex);
117117+ ThrowIf(theError != 0, CAException(theError), "CAGuard::Wait: Could not wait for a signal");
118118+ mOwner = pthread_self();
119119+120120+ #if Log_WaitOwnership
121121+ DebugPrintfRtn(DebugPrintfFile, "%p %.4f: CAGuard::Wait: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
122122+ #endif
123123+#elif TARGET_OS_WIN32
124124+ ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
125125+126126+ mOwner = 0;
127127+128128+ #if Log_WaitOwnership
129129+ DebugPrintfRtn(DebugPrintfFile, "%lu %.4f: CAGuard::Wait: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
130130+ #endif
131131+132132+ ReleaseMutex(mMutex);
133133+ HANDLE theHandles[] = { mMutex, mEvent };
134134+ OSStatus theError = WaitForMultipleObjects(2, theHandles, true, INFINITE);
135135+ ThrowIfError(theError, CAException(GetLastError()), "CAGuard::Wait: Could not wait for the signal");
136136+ mOwner = GetCurrentThreadId();
137137+ ResetEvent(mEvent);
138138+139139+ #if Log_WaitOwnership
140140+ DebugPrintfRtn(DebugPrintfFile, "%lu %.4f: CAGuard::Wait: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
141141+ #endif
142142+#endif
143143+}
144144+145145+bool CAGuard::WaitFor(UInt64 inNanos)
146146+{
147147+ bool theAnswer = false;
148148+149149+#if TARGET_OS_MAC
150150+ ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
151151+152152+ #if Log_TimedWaits
153153+ DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
154154+ #endif
155155+156156+ struct timespec theTimeSpec;
157157+ static const UInt64 kNanosPerSecond = 1000000000ULL;
158158+ if(inNanos > kNanosPerSecond)
159159+ {
160160+ theTimeSpec.tv_sec = inNanos / kNanosPerSecond;
161161+ theTimeSpec.tv_nsec = inNanos % kNanosPerSecond;
162162+ }
163163+ else
164164+ {
165165+ theTimeSpec.tv_sec = 0;
166166+ theTimeSpec.tv_nsec = inNanos;
167167+ }
168168+169169+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
170170+ UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
171171+ #endif
172172+173173+ mOwner = 0;
174174+175175+ #if Log_WaitOwnership
176176+ DebugPrintfRtn(DebugPrintfFile, "%p %.4f: CAGuard::WaitFor: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
177177+ #endif
178178+179179+ OSStatus theError = pthread_cond_timedwait_relative_np(&mCondVar, &mMutex, &theTimeSpec);
180180+ ThrowIf((theError != 0) && (theError != ETIMEDOUT), CAException(theError), "CAGuard::WaitFor: Wait got an error");
181181+ mOwner = pthread_self();
182182+183183+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
184184+ UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
185185+ #endif
186186+187187+ #if Log_TimedWaits
188188+ DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
189189+ #endif
190190+191191+ #if Log_Latency
192192+ DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
193193+ #endif
194194+195195+ #if Log_Average_Latency
196196+ ++mAverageLatencyCount;
197197+ mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
198198+ if(mAverageLatencyCount >= 50)
199199+ {
200200+ DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
201201+ mAverageLatencyCount = 0;
202202+ mAverageLatencyAccumulator = 0.0;
203203+ }
204204+ #endif
205205+206206+ #if Log_WaitOwnership
207207+ DebugPrintfRtn(DebugPrintfFile, "%p %.4f: CAGuard::WaitFor: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
208208+ #endif
209209+210210+ theAnswer = theError == ETIMEDOUT;
211211+#elif TARGET_OS_WIN32
212212+ ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
213213+214214+ #if Log_TimedWaits
215215+ DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
216216+ #endif
217217+218218+ // the time out is specified in milliseconds(!)
219219+ UInt32 theWaitTime = static_cast<UInt32>(inNanos / 1000000ULL);
220220+221221+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
222222+ UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
223223+ #endif
224224+225225+ mOwner = 0;
226226+227227+ #if Log_WaitOwnership
228228+ DebugPrintfRtn(DebugPrintfFile, "%lu %.4f: CAGuard::WaitFor: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
229229+ #endif
230230+231231+ ReleaseMutex(mMutex);
232232+ HANDLE theHandles[] = { mMutex, mEvent };
233233+ OSStatus theError = WaitForMultipleObjects(2, theHandles, true, theWaitTime);
234234+ ThrowIf((theError != WAIT_OBJECT_0) && (theError != WAIT_TIMEOUT), CAException(GetLastError()), "CAGuard::WaitFor: Wait got an error");
235235+ mOwner = GetCurrentThreadId();
236236+ ResetEvent(mEvent);
237237+238238+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
239239+ UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
240240+ #endif
241241+242242+ #if Log_TimedWaits
243243+ DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
244244+ #endif
245245+246246+ #if Log_Latency
247247+ DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
248248+ #endif
249249+250250+ #if Log_Average_Latency
251251+ ++mAverageLatencyCount;
252252+ mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
253253+ if(mAverageLatencyCount >= 50)
254254+ {
255255+ DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
256256+ mAverageLatencyCount = 0;
257257+ mAverageLatencyAccumulator = 0.0;
258258+ }
259259+ #endif
260260+261261+ #if Log_WaitOwnership
262262+ DebugPrintfRtn(DebugPrintfFile, "%lu %.4f: CAGuard::WaitFor: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
263263+ #endif
264264+265265+ theAnswer = theError == WAIT_TIMEOUT;
266266+#endif
267267+268268+ return theAnswer;
269269+}
270270+271271+bool CAGuard::WaitUntil(UInt64 inNanos)
272272+{
273273+ bool theAnswer = false;
274274+ UInt64 theCurrentNanos = CAHostTimeBase::GetCurrentTimeInNanos();
275275+276276+#if Log_TimedWaits
277277+ DebugMessageN2("CAGuard::WaitUntil: now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
278278+#endif
279279+280280+ if(inNanos > theCurrentNanos)
281281+ {
282282+#if Log_Errors
283283+ if((inNanos - theCurrentNanos) > 1000000000ULL)
284284+ {
285285+ DebugMessage("CAGuard::WaitUntil: about to wait for more than a second");
286286+ }
287287+#endif
288288+ theAnswer = WaitFor(inNanos - theCurrentNanos);
289289+ }
290290+#if Log_Errors
291291+ else
292292+ {
293293+ DebugMessageN2("CAGuard::WaitUntil: Time has expired before waiting, now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
294294+ }
295295+#endif
296296+297297+ return theAnswer;
298298+}
299299+300300+void CAGuard::Notify()
301301+{
302302+#if TARGET_OS_MAC
303303+ #if Log_WaitOwnership
304304+ DebugPrintfRtn(DebugPrintfFile, "%p %.4f: CAGuard::Notify: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
305305+ #endif
306306+307307+ OSStatus theError = pthread_cond_signal(&mCondVar);
308308+ ThrowIf(theError != 0, CAException(theError), "CAGuard::Notify: failed");
309309+#elif TARGET_OS_WIN32
310310+ #if Log_WaitOwnership
311311+ DebugPrintfRtn(DebugPrintfFile, "%lu %.4f: CAGuard::Notify: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
312312+ #endif
313313+314314+ SetEvent(mEvent);
315315+#endif
316316+}
317317+318318+void CAGuard::NotifyAll()
319319+{
320320+#if TARGET_OS_MAC
321321+ #if Log_WaitOwnership
322322+ DebugPrintfRtn(DebugPrintfFile, "%p %.4f: CAGuard::NotifyAll: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
323323+ #endif
324324+325325+ OSStatus theError = pthread_cond_broadcast(&mCondVar);
326326+ ThrowIf(theError != 0, CAException(theError), "CAGuard::NotifyAll: failed");
327327+#elif TARGET_OS_WIN32
328328+ #if Log_WaitOwnership
329329+ DebugPrintfRtn(DebugPrintfFile, "%lu %.4f: CAGuard::NotifyAll: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
330330+ #endif
331331+332332+ SetEvent(mEvent);
333333+#endif
334334+}
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*==================================================================================================
3939+ CAGuard.h
4040+4141+==================================================================================================*/
4242+#if !defined(__CAGuard_h__)
4343+#define __CAGuard_h__
4444+4545+//==================================================================================================
4646+// Includes
4747+//=============================================================================
4848+4949+// Super Class Includes
5050+#include "CAMutex.h"
5151+5252+#if CoreAudio_Debug
5353+// #define Log_Average_Latency 1
5454+#endif
5555+5656+//==================================================================================================
5757+// CAGuard
5858+//
5959+// This is your typical mutex with signalling implemented via pthreads.
6060+// Lock() will return true if and only if the guard is locked on that call.
6161+// A thread that already has the guard will receive 'false' if it locks it
6262+// again. Use of the stack-based CAGuard::Locker class is highly recommended
6363+// to properly manage the recursive nesting. The Wait calls with timeouts
6464+// will return true if and only if the timeout period expired. They will
6565+// return false if they receive notification any other way.
6666+//==================================================================================================
6767+6868+class CAGuard : public CAMutex
6969+{
7070+7171+// Construction/Destruction
7272+public:
7373+ CAGuard(const char* inName);
7474+ virtual ~CAGuard();
7575+7676+// Actions
7777+public:
7878+ virtual void Wait();
7979+ virtual bool WaitFor(UInt64 inNanos);
8080+ virtual bool WaitUntil(UInt64 inNanos);
8181+8282+ virtual void Notify();
8383+ virtual void NotifyAll();
8484+8585+// Implementation
8686+protected:
8787+#if TARGET_OS_MAC
8888+ pthread_cond_t mCondVar;
8989+#else
9090+ HANDLE mEvent;
9191+#endif
9292+#if Log_Average_Latency
9393+ Float64 mAverageLatencyAccumulator;
9494+ UInt32 mAverageLatencyCount;
9595+#endif
9696+9797+// Helper class to manage taking and releasing recursively
9898+public:
9999+ class Locker
100100+ {
101101+102102+ // Construction/Destruction
103103+ public:
104104+ Locker(CAGuard& inGuard) : mGuard(inGuard), mNeedsRelease(false) { mNeedsRelease = mGuard.Lock(); }
105105+ ~Locker() { if(mNeedsRelease) { mGuard.Unlock(); } }
106106+107107+ private:
108108+ Locker(const Locker&);
109109+ Locker& operator=(const Locker&);
110110+111111+ // Actions
112112+ public:
113113+ void Wait() { mGuard.Wait(); }
114114+ bool WaitFor(UInt64 inNanos) { return mGuard.WaitFor(inNanos); }
115115+ bool WaitUntil(UInt64 inNanos) { return mGuard.WaitUntil(inNanos); }
116116+117117+ void Notify() { mGuard.Notify(); }
118118+ void NotifyAll() { mGuard.NotifyAll(); }
119119+120120+ // Implementation
121121+ private:
122122+ CAGuard& mGuard;
123123+ bool mNeedsRelease;
124124+ };
125125+126126+};
127127+128128+#endif
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAPThread.cp
4040+4141+=============================================================================*/
4242+4343+//=============================================================================
4444+// Includes
4545+//=============================================================================
4646+4747+// Self Include
4848+#include "CAPThread.h"
4949+5050+// PublicUtility Includes
5151+#include "CADebugMacros.h"
5252+#include "CAException.h"
5353+5454+// System Includes
5555+#if TARGET_OS_MAC
5656+ #include <mach/mach.h>
5757+#endif
5858+5959+// Standard Library Includes
6060+#include <stdio.h>
6161+6262+//==================================================================================================
6363+// CAPThread
6464+//==================================================================================================
6565+6666+// returns the thread's priority as it was last set by the API
6767+#define CAPTHREAD_SET_PRIORITY 0
6868+// returns the thread's priority as it was last scheduled by the Kernel
6969+#define CAPTHREAD_SCHEDULED_PRIORITY 1
7070+7171+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority)
7272+:
7373+#if TARGET_OS_MAC
7474+ mPThread(0),
7575+ mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
7676+#elif TARGET_OS_WIN32
7777+ mThreadHandle(NULL),
7878+ mThreadID(0),
7979+#endif
8080+ mThreadRoutine(inThreadRoutine),
8181+ mThreadParameter(inParameter),
8282+ mPriority(inPriority),
8383+ mPeriod(0),
8484+ mComputation(0),
8585+ mConstraint(0),
8686+ mIsPreemptible(true),
8787+ mTimeConstraintSet(false),
8888+ mFixedPriority(inFixedPriority)
8989+{
9090+}
9191+9292+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible)
9393+:
9494+#if TARGET_OS_MAC
9595+ mPThread(0),
9696+ mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
9797+#elif TARGET_OS_WIN32
9898+ mThreadHandle(NULL),
9999+ mThreadID(0),
100100+#endif
101101+ mThreadRoutine(inThreadRoutine),
102102+ mThreadParameter(inParameter),
103103+ mPriority(kDefaultThreadPriority),
104104+ mPeriod(inPeriod),
105105+ mComputation(inComputation),
106106+ mConstraint(inConstraint),
107107+ mIsPreemptible(inIsPreemptible),
108108+ mTimeConstraintSet(true),
109109+ mFixedPriority(false)
110110+{
111111+}
112112+113113+CAPThread::~CAPThread()
114114+{
115115+}
116116+117117+UInt32 CAPThread::GetScheduledPriority()
118118+{
119119+#if TARGET_OS_MAC
120120+ return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY );
121121+#elif TARGET_OS_WIN32
122122+ UInt32 theAnswer = 0;
123123+ if(mThreadHandle != NULL)
124124+ {
125125+ theAnswer = GetThreadPriority(mThreadHandle);
126126+ }
127127+ return theAnswer;
128128+#endif
129129+}
130130+131131+void CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority)
132132+{
133133+ mPriority = inPriority;
134134+ mTimeConstraintSet = false;
135135+ mFixedPriority = inFixedPriority;
136136+#if TARGET_OS_MAC
137137+ if(mPThread != 0)
138138+ {
139139+140140+ if (mFixedPriority)
141141+ {
142142+ thread_extended_policy_data_t theFixedPolicy;
143143+ theFixedPolicy.timeshare = false; // set to true for a non-fixed thread
144144+ AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT), "CAPThread::SetPriority: failed to set the fixed-priority policy");
145145+ }
146146+ // We keep a reference to the spawning thread's priority around (initialized in the constructor),
147147+ // and set the importance of the child thread relative to the spawning thread's priority.
148148+ thread_precedence_policy_data_t thePrecedencePolicy;
149149+150150+ thePrecedencePolicy.importance = mPriority - mSpawningThreadPriority;
151151+ AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT), "CAPThread::SetPriority: failed to set the precedence policy");
152152+ }
153153+#elif TARGET_OS_WIN32
154154+ if(mThreadHandle != NULL)
155155+ {
156156+ SetThreadPriority(mThreadHandle, mPriority);
157157+ }
158158+#endif
159159+}
160160+161161+void CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible)
162162+{
163163+ mPeriod = inPeriod;
164164+ mComputation = inComputation;
165165+ mConstraint = inConstraint;
166166+ mIsPreemptible = inIsPreemptible;
167167+ mTimeConstraintSet = true;
168168+#if TARGET_OS_MAC
169169+ if(mPThread != 0)
170170+ {
171171+ thread_time_constraint_policy_data_t thePolicy;
172172+ thePolicy.period = mPeriod;
173173+ thePolicy.computation = mComputation;
174174+ thePolicy.constraint = mConstraint;
175175+ thePolicy.preemptible = mIsPreemptible;
176176+ AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&thePolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT), "CAPThread::SetTimeConstraints: thread_policy_set failed");
177177+ }
178178+#elif TARGET_OS_WIN32
179179+ if(mThreadHandle != NULL)
180180+ {
181181+ SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);
182182+ }
183183+#endif
184184+}
185185+186186+void CAPThread::Start()
187187+{
188188+#if TARGET_OS_MAC
189189+ if(mPThread == 0)
190190+ {
191191+ OSStatus theResult;
192192+ pthread_attr_t theThreadAttributes;
193193+194194+ theResult = pthread_attr_init(&theThreadAttributes);
195195+ ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: Thread attributes could not be created.");
196196+197197+ theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED);
198198+ ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: A thread could not be created in the detached state.");
199199+200200+ theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry, this);
201201+ ThrowIf(theResult != 0 || !mPThread, CAException(theResult), "CAPThread::Start: Could not create a thread.");
202202+203203+ pthread_attr_destroy(&theThreadAttributes);
204204+205205+ }
206206+#elif TARGET_OS_WIN32
207207+ if(mThreadID == 0)
208208+ {
209209+ // clean up the existing thread handle
210210+ if(mThreadHandle != NULL)
211211+ {
212212+ CloseHandle(mThreadHandle);
213213+ mThreadHandle = NULL;
214214+ }
215215+216216+ // create a new thread
217217+ mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry, this, 0, &mThreadID);
218218+ ThrowIf(mThreadHandle == NULL, CAException(GetLastError()), "CAPThread::Start: Could not create a thread.");
219219+ }
220220+#endif
221221+}
222222+223223+#if TARGET_OS_MAC
224224+225225+void* CAPThread::Entry(CAPThread* inCAPThread)
226226+{
227227+ void* theAnswer = NULL;
228228+229229+ try
230230+ {
231231+ if(inCAPThread->mTimeConstraintSet)
232232+ {
233233+ inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
234234+ }
235235+ else
236236+ {
237237+ inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
238238+ }
239239+240240+ if(inCAPThread->mThreadRoutine != NULL)
241241+ {
242242+ theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter);
243243+ }
244244+ }
245245+ catch (...)
246246+ {
247247+ // what should be done here?
248248+ }
249249+ inCAPThread->mPThread = 0;
250250+ return theAnswer;
251251+}
252252+253253+UInt32 CAPThread::getScheduledPriority(pthread_t inThread, int inPriorityKind)
254254+{
255255+ thread_basic_info_data_t threadInfo;
256256+ policy_info_data_t thePolicyInfo;
257257+ unsigned int count;
258258+259259+ if (inThread == NULL)
260260+ return 0;
261261+262262+ // get basic info
263263+ count = THREAD_BASIC_INFO_COUNT;
264264+ thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
265265+266266+ switch (threadInfo.policy) {
267267+ case POLICY_TIMESHARE:
268268+ count = POLICY_TIMESHARE_INFO_COUNT;
269269+ thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
270270+ if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) {
271271+ return thePolicyInfo.ts.cur_priority;
272272+ }
273273+ return thePolicyInfo.ts.base_priority;
274274+ break;
275275+276276+ case POLICY_FIFO:
277277+ count = POLICY_FIFO_INFO_COUNT;
278278+ thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
279279+ if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
280280+ return thePolicyInfo.fifo.depress_priority;
281281+ }
282282+ return thePolicyInfo.fifo.base_priority;
283283+ break;
284284+285285+ case POLICY_RR:
286286+ count = POLICY_RR_INFO_COUNT;
287287+ thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
288288+ if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
289289+ return thePolicyInfo.rr.depress_priority;
290290+ }
291291+ return thePolicyInfo.rr.base_priority;
292292+ break;
293293+ }
294294+295295+ return 0;
296296+}
297297+298298+#elif TARGET_OS_WIN32
299299+300300+UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread)
301301+{
302302+ UInt32 theAnswer = 0;
303303+304304+ try
305305+ {
306306+ if(inCAPThread->mTimeConstraintSet)
307307+ {
308308+ inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
309309+ }
310310+ else
311311+ {
312312+ inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
313313+ }
314314+315315+ if(inCAPThread->mThreadRoutine != NULL)
316316+ {
317317+ theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter));
318318+ }
319319+ inCAPThread->mThreadID = 0;
320320+ }
321321+ catch (...)
322322+ {
323323+ // what should be done here?
324324+ }
325325+ return theAnswer;
326326+}
327327+328328+// a definition of this function here for now
329329+extern "C"
330330+Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr)
331331+{
332332+ return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue;
333333+}
334334+335335+#endif
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*==================================================================================================
3939+ CAPThread.h
4040+4141+==================================================================================================*/
4242+#if !defined(__CAPThread_h__)
4343+#define __CAPThread_h__
4444+4545+//==================================================================================================
4646+// Includes
4747+//==================================================================================================
4848+4949+// System Includes
5050+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
5151+ #include <CoreAudio/CoreAudioTypes.h>
5252+#else
5353+ #include <CoreAudioTypes.h>
5454+#endif
5555+5656+#if TARGET_OS_MAC
5757+ #include <pthread.h>
5858+ #include <unistd.h>
5959+#elif TARGET_OS_WIN32
6060+ #include <windows.h>
6161+#else
6262+ #error Unsupported operating system
6363+#endif
6464+6565+//==================================================================================================
6666+// CAPThread
6767+//
6868+// This class wraps a pthread and a Win32 thread.
6969+// caution: long-running fixed priority threads can make the system unresponsive
7070+//==================================================================================================
7171+7272+class CAPThread
7373+{
7474+7575+// Types
7676+public:
7777+ typedef void* (*ThreadRoutine)(void* inParameter);
7878+7979+// Constants
8080+public:
8181+ enum
8282+ {
8383+#if TARGET_OS_MAC
8484+ kMinThreadPriority = 1,
8585+ kMaxThreadPriority = 63,
8686+ kDefaultThreadPriority = 31
8787+#elif TARGET_OS_WIN32
8888+ kMinThreadPriority = 1,
8989+ kMaxThreadPriority = 31,
9090+ kDefaultThreadPriority = THREAD_PRIORITY_NORMAL
9191+#endif
9292+ };
9393+9494+// Construction/Destruction
9595+public:
9696+ CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority = kDefaultThreadPriority, bool inFixedPriority=false);
9797+ CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible);
9898+ virtual ~CAPThread();
9999+100100+// Properties
101101+public:
102102+#if TARGET_OS_MAC
103103+ pthread_t GetPThread() const { return mPThread; }
104104+ bool IsCurrentThread() const { return (0 != mPThread) && (pthread_self() == mPThread); }
105105+ bool IsRunning() const { return 0 != mPThread; }
106106+#elif TARGET_OS_WIN32
107107+ HANDLE GetThreadHandle() const { return mThreadHandle; }
108108+ UInt32 GetThreadID() const { return mThreadID; }
109109+ bool IsCurrentThread() const { return (0 != mThreadID) && (GetCurrentThreadId() == mThreadID); }
110110+ bool IsRunning() const { return 0 != mThreadID; }
111111+#endif
112112+113113+ bool IsTimeShareThread() const { return !mTimeConstraintSet; }
114114+ bool IsTimeConstraintThread() const { return mTimeConstraintSet; }
115115+116116+ UInt32 GetPriority() const { return mPriority; }
117117+ UInt32 GetScheduledPriority();
118118+ void SetPriority(UInt32 inPriority, bool inFixedPriority=false);
119119+120120+ void GetTimeConstraints(UInt32& outPeriod, UInt32& outComputation, UInt32& outConstraint, bool& outIsPreemptible) const { outPeriod = mPeriod; outComputation = mComputation; outConstraint = mConstraint; outIsPreemptible = mIsPreemptible; }
121121+ void SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible);
122122+ void ClearTimeConstraints() { SetPriority(mPriority); }
123123+124124+// Actions
125125+public:
126126+ virtual void Start();
127127+128128+// Implementation
129129+protected:
130130+#if TARGET_OS_MAC
131131+ static void* Entry(CAPThread* inCAPThread);
132132+ static UInt32 getScheduledPriority(pthread_t inThread, int inPriorityKind);
133133+#elif TARGET_OS_WIN32
134134+ static UInt32 WINAPI Entry(CAPThread* inCAPThread);
135135+#endif
136136+137137+#if TARGET_OS_MAC
138138+ pthread_t mPThread;
139139+ UInt32 mSpawningThreadPriority;
140140+#elif TARGET_OS_WIN32
141141+ HANDLE mThreadHandle;
142142+ UInt32 mThreadID;
143143+#endif
144144+ ThreadRoutine mThreadRoutine;
145145+ void* mThreadParameter;
146146+ SInt32 mPriority;
147147+ UInt32 mPeriod;
148148+ UInt32 mComputation;
149149+ UInt32 mConstraint;
150150+ bool mIsPreemptible;
151151+ bool mTimeConstraintSet;
152152+ bool mFixedPriority;
153153+};
154154+155155+#endif
···11+{\rtf1\mac\ansicpg10000\cocoartf102
22+{\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fnil\fcharset77 Monaco;}
33+{\colortbl;\red255\green255\blue255;\red104\green56\blue33;}
44+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural
55+66+\f0\fs36 \cf0 AudioFile-new\
77+\
88+99+\fs24 This folder contains new classes for working with audio files, using the AudioToolbox AudioFile and AudioConverter API's. It is currently a work in progress. Some command-line tools using these classes are in the AudioFileTools sample project.\
1010+\
1111+CAAudioFile has been reworked to optionally use the new ExtendedAudioFile API in Tiger. The functionality is essentially the same but a number of method names have been changed. To use the provided Panther-compatible implementation instead of requiring ExtendedAudioFile, define
1212+\f1\fs18 \cf2 \CocoaLigature0 CAAF_USE_EXTAUDIOFILE
1313+\f0\fs24 \cf0 \CocoaLigature1 to 1.\
1414+\
1515+The main classes are:\
1616+\
1717+CAAudioFile - wraps an AudioFile in an AudioConverter. The client specifies a PCM format to be used when reading/writing from the file, and the class performs any necessary decoding/encoding transparently. Be aware that most methods of this class may throw exceptions.\
1818+\
1919+CAAudioFileStreamer / CAAudioFileReader / CAAudioFileWriter - perfom asynchronous streaming of CAAudioFiles on a separate work thread for file I/O and decoding.These classes don't actually connect to the audio hardware.\
2020+\
2121+CAAudioFilePlayer / CAAudioFileRecorder - Subclasses of CAAudioFileReader / CAAudioFileWriter which use audio "output" (now I/O) units to actually play and recorder the audio.\
2222+\
2323+CAChannelMapper - uses the matrix mixer audio unit for converting (downmixing if necessary) between audio channel layouts.\
2424+\
2525+The other classes are support classes for the above.\
2626+}
+45
src/CoreAudio/AudioFileTools/ReadMe.rtf
···11+{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf100
22+{\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fmodern\fcharset77 Courier;\f2\fswiss\fcharset77 Helvetica-Bold;
33+}
44+{\colortbl;\red255\green255\blue255;}
55+\vieww12420\viewh14680\viewkind0
66+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural
77+88+\f0\fs36 \cf0 AudioFileTools\
99+1010+\fs24 \
1111+This project contains a collection of sample command-line tools that demonstrate use of the AudioFile, AudioConverter, AudioFormat, and AudioUnit APIs. Most make heavy use of the CAAudioFile class (in PublicUtility/AudioFile-new).\
1212+\
1313+Note that CAAudioFile.h is conditionalized with
1414+\f1 \CocoaLigature0 CAAF_USE_EXTAUDIOFILE
1515+\f0 \CocoaLigature1 . If this symbol is defined and non-zero, the CAAudioFile implementation uses the ExtendedAudioFile API set introduced in Tiger. Otherwise, CAAudioFile carries its own similar implementation, which is deployable on Panther systems. If your build environment does not define this symbol, the header automatically defines it based on the Mac OS deployment build settings. The "-Tiger+" build styles in this project define the Mac OS deployment target to 10.4 and will thus use ExtendedAudioFile. The "-Panther" build styles do not define a Mac OS deployment target and thus do not use ExtendedAudioFile.\
1616+\
1717+The tools include:\
1818+\
1919+2020+\f2\b afconvert
2121+\f0\b0 - reads one audio file, writes it to another format. Good example of the power of CAAudioFile and use of the AudioConverter for codecs.\
2222+\
2323+2424+\f2\b afinterleave
2525+\f0\b0 - creates an interleaved file from 2 or more input files\
2626+\
2727+2828+\f2\b afplay
2929+\f0\b0 - plays an audio file (can be encoded)\
3030+\
3131+3232+\f2\b afrecord
3333+\f0\b0 - records an audio file (record format is hardcoded)\
3434+\
3535+3636+\f2\b audioformats
3737+\f0\b0 - demonstrates some uses of the AudioFormat and AudioFile APIs.\
3838+\
3939+4040+\f2\b qtaacdecode
4141+\f0\b0 - this has been removed. Please see the QT SDK's examples for using their AudioExtraction API\
4242+\
4343+4444+\f2\b auprocess
4545+\f0\b0 - processes an audio file with an Audio Unit and generates a new file. Illustrates the usage of the CAAUProcessor class, which presents a wrapper class around using any AU in either a real-time or offline context}
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ AFToolsCommon.cpp
4040+4141+=============================================================================*/
4242+4343+#include "AFToolsCommon.h"
4444+#include "CAAudioFileFormats.h"
4545+#include <ctype.h>
4646+#include <CoreServices/Endian.h>
4747+4848+4949+/*
5050+struct AudioStreamBasicDescription
5151+{
5252+ Float64 mSampleRate; // the native sample rate of the audio stream
5353+ UInt32 mFormatID; // the specific encoding type of audio stream
5454+ UInt32 mFormatFlags; // flags specific to each format
5555+ UInt32 mBytesPerPacket; // the number of bytes in a packet
5656+ UInt32 mFramesPerPacket; // the number of frames in each packet
5757+ UInt32 mBytesPerFrame; // the number of bytes in a frame
5858+ UInt32 mChannelsPerFrame; // the number of channels in each frame
5959+ UInt32 mBitsPerChannel; // the number of bits in each channel
6060+ UInt32 mReserved; // reserved, pads the structure out to force 8 byte alignment
6161+};
6262+*/
6363+bool ParseStreamDescription(const char *inTextDesc, CAStreamBasicDescription &fmt)
6464+{
6565+ const char *p = inTextDesc;
6666+ int bitdepth = 0;
6767+ CAAudioFileFormats *theFileFormats = CAAudioFileFormats::Instance();
6868+6969+ memset(&fmt, 0, sizeof(fmt));
7070+ OSType formatID;
7171+ int x;
7272+ if (strchr("-@/#", p[3])) {
7373+ // special-case for 3-char format ID's ending with a space
7474+ char fmtstr[4];
7575+ memcpy(fmtstr, p, 3);
7676+ fmtstr[3] = ' ';
7777+ formatID = EndianU32_BtoN(*(UInt32 *)fmtstr);
7878+ x = 3;
7979+ } else {
8080+ x = StrToOSType(p, formatID);
8181+ }
8282+ if (theFileFormats->IsKnownDataFormat(formatID)) {
8383+ p += x;
8484+ fmt.mFormatID = formatID;
8585+ if (*p == '-') {
8686+ ++p;
8787+ bitdepth = 0;
8888+ while (isdigit(*p))
8989+ bitdepth = 10 * bitdepth + *p++ - '0';
9090+ fmt.mBitsPerChannel = bitdepth;
9191+ }
9292+ }
9393+9494+ if (fmt.mFormatID == 0) {
9595+ // unknown format, assume LPCM
9696+ if (p[0] == '-') // previously we required a leading dash on PCM formats
9797+ // pcm
9898+ ++p;
9999+ fmt.mFormatID = kAudioFormatLinearPCM;
100100+ fmt.mFormatFlags = kAudioFormatFlagIsPacked;
101101+ fmt.mFramesPerPacket = 1;
102102+ fmt.mChannelsPerFrame = 1;
103103+ bool isUnsigned = false;
104104+105105+ if (p[0] == 'B' && p[1] == 'E') {
106106+ fmt.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
107107+ p += 2;
108108+ } else if (p[0] == 'L' && p[1] == 'E') {
109109+ p += 2;
110110+ } else {
111111+ // default is native-endian
112112+#if TARGET_RT_BIG_ENDIAN
113113+ fmt.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
114114+#endif
115115+ }
116116+ if (p[0] == 'F') {
117117+ fmt.mFormatFlags |= kAudioFormatFlagIsFloat;
118118+ ++p;
119119+ } else {
120120+ if (p[0] == 'U') {
121121+ isUnsigned = true;
122122+ ++p;
123123+ }
124124+ if (p[0] == 'I')
125125+ ++p;
126126+ else {
127127+ fprintf(stderr, "The format '%s' is unknown or an unparseable PCM format specifier\n", inTextDesc);
128128+ goto Bail;
129129+ }
130130+ }
131131+132132+ while (isdigit(*p))
133133+ bitdepth = 10 * bitdepth + *p++ - '0';
134134+ if (fmt.mFormatFlags & kAudioFormatFlagIsFloat) {
135135+ if (bitdepth != 32 && bitdepth != 64) {
136136+ fprintf(stderr, "Valid float bitdepths are 32 and 64\n");
137137+ goto Bail;
138138+ }
139139+ } else {
140140+ if (bitdepth != 8 && bitdepth != 16 && bitdepth != 24 && bitdepth != 32) {
141141+ fprintf(stderr, "Valid integer bitdepths are 8, 16, 24, and 32\n");
142142+ goto Bail;
143143+ }
144144+ if (!isUnsigned)
145145+ fmt.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
146146+ }
147147+ fmt.mBitsPerChannel = bitdepth;
148148+ fmt.mBytesPerPacket = fmt.mBytesPerFrame = bitdepth / 8;
149149+ }
150150+ if (*p == '@') {
151151+ ++p;
152152+ while (isdigit(*p))
153153+ fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0');
154154+ }
155155+ if (*p == '/') {
156156+ UInt32 flags = 0;
157157+ while (true) {
158158+ char c = *++p;
159159+ if (c >= '0' && c <= '9')
160160+ flags = (flags << 4) | (c - '0');
161161+ else if (c >= 'A' && c <= 'F')
162162+ flags = (flags << 4) | (c - 'A' + 10);
163163+ else if (c >= 'a' && c <= 'f')
164164+ flags = (flags << 4) | (c - 'a' + 10);
165165+ else break;
166166+ }
167167+ fmt.mFormatFlags = flags;
168168+ }
169169+ if (*p == '#') {
170170+ ++p;
171171+ while (isdigit(*p))
172172+ fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + (*p++ - '0');
173173+ }
174174+ if (*p != '\0')
175175+ goto Bail;
176176+ return true;
177177+178178+Bail:
179179+ fprintf(stderr, "Invalid format string: %s\n", inTextDesc);
180180+ fprintf(stderr, "Syntax of format strings is: [-][BE|LE]{F|I|UI}{8|16|24|32|64}[@sample_rate_hz][/format_flags]\n");
181181+ return false;
182182+}
183183+184184+void PrintAudioFileTypesAndFormats(FILE *outfile)
185185+{
186186+ CAAudioFileFormats *theFileFormats = CAAudioFileFormats::Instance();
187187+188188+ for (int i = 0; i < theFileFormats->mNumFileFormats; ++i) {
189189+ CAAudioFileFormats::FileFormatInfo *ffi = &theFileFormats->mFileFormats[i];
190190+191191+ int j;
192192+ char buf[20];
193193+ char fmtName[256] = { 0 };
194194+ if (ffi->mFileTypeName)
195195+ CFStringGetCString(ffi->mFileTypeName, fmtName, sizeof(fmtName), kCFStringEncodingUTF8);
196196+ fprintf(outfile, " '%s' = %s", OSTypeToStr(buf, sizeof(buf), ffi->mFileTypeID), fmtName);
197197+198198+ int next = ffi->NumberOfExtensions();
199199+ if (next > 0) {
200200+ fprintf(outfile, " (");
201201+ for (j = 0; j < next; ++j) {
202202+ if (j > 0) fprintf(outfile, ", ");
203203+ fprintf(outfile, ".%s", ffi->GetExtension(j, buf, sizeof(buf)));
204204+ }
205205+ fprintf(outfile, ")");
206206+ }
207207+208208+ fprintf(outfile, "\n data_formats: ");
209209+ int count = 0;
210210+ for (j = 0; j < ffi->mNumDataFormats; ++j) {
211211+ CAAudioFileFormats::DataFormatInfo *dfi = &ffi->mDataFormats[j];
212212+ if (dfi->mFormatID == kAudioFormatLinearPCM) {
213213+ for (int k = 0; k < dfi->mNumVariants; ++k) {
214214+ if (++count == 6) {
215215+ fprintf(outfile, "\n ");
216216+ count = 0;
217217+ }
218218+ AudioStreamBasicDescription *asbd = &dfi->mVariants[k];
219219+ if (asbd->mFormatFlags & ~(kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsFloat))
220220+ fprintf(outfile, "(%08lx/%ld) ", asbd->mFormatFlags, asbd->mBitsPerChannel);
221221+ else {
222222+ fprintf(outfile, "%s",
223223+ (asbd->mFormatFlags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE");
224224+ if (asbd->mFormatFlags & kAudioFormatFlagIsFloat)
225225+ fprintf(outfile, "F");
226226+ else
227227+ fprintf(outfile, "%sI",
228228+ (asbd->mFormatFlags & kAudioFormatFlagIsSignedInteger) ? "" : "U");
229229+ fprintf(outfile, "%ld ", asbd->mBitsPerChannel);
230230+ }
231231+ }
232232+ } else {
233233+ if (++count == 6) {
234234+ fprintf(outfile, "\n ");
235235+ count = 0;
236236+ }
237237+ fprintf(outfile, "'%s' ", OSTypeToStr(buf, sizeof(buf), dfi->mFormatID));
238238+ }
239239+ }
240240+ fprintf(outfile, "\n");
241241+ }
242242+}
243243+244244+#if 0
245245+char *OSTypeToStr(char *buf, OSType t)
246246+{
247247+ char *p = buf;
248248+ char str[4], *q = str;
249249+ *(UInt32 *)str = EndianU32_NtoB(t);
250250+ for (int i = 0; i < 4; ++i) {
251251+ if (isprint(*q) && *q != '\\')
252252+ *p++ = *q++;
253253+ else {
254254+ sprintf(p, "\\x%02x", *q++);
255255+ p += 4;
256256+ }
257257+ }
258258+ *p = '\0';
259259+ return buf;
260260+}
261261+262262+int StrToOSType(const char *str, OSType &t)
263263+{
264264+ char buf[4];
265265+ const char *p = str;
266266+ int x;
267267+ for (int i = 0; i < 4; ++i) {
268268+ if (*p != '\\') {
269269+ if ((buf[i] = *p++) == '\0')
270270+ goto fail;
271271+ } else {
272272+ if (*++p != 'x') goto fail;
273273+ if (sscanf(++p, "%02X", &x) != 1) goto fail;
274274+ buf[i] = x;
275275+ p += 2;
276276+ }
277277+ }
278278+ t = EndianU32_BtoN(*(UInt32 *)buf);
279279+ return p - str;
280280+fail:
281281+ return 0;
282282+}
283283+#endif
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ AFToolsCommon.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __AFToolsCommon_h__
4444+#define __AFToolsCommon_h__
4545+4646+// Various utility functions appropriate for reuse in Core Audio command-line tools
4747+4848+#include <stdio.h>
4949+#include "CAStreamBasicDescription.h"
5050+5151+bool ParseStreamDescription(const char *inTextDesc, CAStreamBasicDescription &fmt);
5252+ // parse a textual representation of an AudioStreamBasicDescription
5353+void PrintAudioFileTypesAndFormats(FILE *outfile);
5454+5555+// utilities to convert OSType's to and from printable strings
5656+// buffer should be at least 17 bytes
5757+5858+5959+#endif // __AFToolsCommon_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAAudioFileConverter.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAAudioFileConverter_h__
4444+#define __CAAudioFileConverter_h__
4545+4646+/*
4747+ Compile options:
4848+ CAAUDIOFILE_PROFILE
4949+*/
5050+5151+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
5252+ #include <AudioToolbox/AudioToolbox.h>
5353+#else
5454+ #include <AudioToolbox.h>
5555+#endif
5656+#include "CAStreamBasicDescription.h"
5757+#include "CABufferList.h"
5858+#include "CAHostTimeBase.h"
5959+#include "CAAudioChannelLayout.h"
6060+#include "CAAudioFile.h"
6161+6262+class CAAudioFileConverter {
6363+public:
6464+ // options for ConversionParameters.flags
6565+ enum {
6666+ kOpt_OverwriteOutputFile = 1,
6767+ kOpt_Verbose = 2,
6868+ kOpt_CAFTag = 4, // tags encoded CAF files with info about the source file
6969+ // or restores based on it when decoding
7070+ kOpt_NoSanitizeOutputFormat = 8 // used internally
7171+ };
7272+7373+ struct ConversionParameters {
7474+ ConversionParameters();
7575+7676+ UInt32 flags;
7777+7878+ struct {
7979+ const char * filePath; // POSIX path, UTF-8
8080+ AudioFileID audioFileID; // or set this to non-zero
8181+ AudioChannelLayoutTag channelLayoutTag; // 0 to use the one in the file, or default
8282+ } input;
8383+8484+ struct {
8585+ const char * filePath; // POSIX path; if null, file is written to same
8686+ // directory as input file, name generated from
8787+ // its name with the appropriate filename extension
8888+ // (fails if file already exists)
8989+ AudioFileTypeID fileType;
9090+ CAStreamBasicDescription dataFormat;
9191+ int channels; // -1 for same number of channels as input
9292+ SInt32 bitRate; // -1 for default
9393+ SInt32 codecQuality; // 0-127, -1 for default
9494+ SInt32 srcQuality; // 0-127, -1 for default
9595+ SInt32 strategy; // 0-2, -1 for default
9696+ SInt32 primeMethod; // 0-2, -1 for default
9797+ AudioChannelLayoutTag channelLayoutTag; // 0 for default
9898+ } output;
9999+100100+ //UInt32 bufferSize; // [UNIMPLEMENTED]
101101+ };
102102+103103+ CAAudioFileConverter();
104104+105105+ virtual ~CAAudioFileConverter();
106106+107107+ void ConvertFile(const ConversionParameters ¶ms);
108108+ virtual bool Progress(SInt64 packetsConverted, SInt64 packetsTotal) { return false; }
109109+ virtual void GenerateOutputFileName(const char *inputFilePath,
110110+ const CAStreamBasicDescription &inputFormat,
111111+ const CAStreamBasicDescription &outputFormat,
112112+ OSType outputFileType, char *outName);
113113+114114+ const char * GetOutputFileName() { return mOutName; }
115115+ const CAAudioFile & InputFile() { return mSrcFile; }
116116+ const CAAudioFile & OutputFile() { return mDestFile; }
117117+118118+ // customization
119119+ virtual void PrepareConversion() { }
120120+ virtual void OpenInputFile();
121121+ virtual void OpenOutputFile(const CAStreamBasicDescription &srcFormat, const CAStreamBasicDescription &destFormat, FSRef &destFSRef, CAAudioChannelLayout &destFileLayout);
122122+ virtual void ComputeReadSize(const CAStreamBasicDescription &srcFormat, const CAStreamBasicDescription &destFormat, UInt32 &bytesToRead, UInt32 &framesToRead) { }
123123+ virtual void BeginConversion() { }
124124+ virtual void EndConversion() { }
125125+ virtual bool ShouldTerminateConversion() { return false; }
126126+127127+ bool TaggedEncodingToCAF() const {
128128+ return (mParams.flags & kOpt_CAFTag) && mDestFormat.mFormatID != kAudioFormatLinearPCM && mParams.output.fileType == kAudioFileCAFType;
129129+ }
130130+ bool TaggedDecodingFromCAF() const {
131131+ return (mParams.flags & kOpt_CAFTag) && mSrcFormat.mFormatID != kAudioFormatLinearPCM;
132132+ // don't know for sure that the source file is CAF...
133133+ }
134134+135135+ void WriteCAFInfo();
136136+ void ReadCAFInfo();
137137+138138+protected:
139139+ void PrintFormats(const CAAudioChannelLayout *origSrcFileLayout);
140140+141141+ ConversionParameters mParams;
142142+ CAAudioFile mSrcFile;
143143+ CAAudioFile mDestFile;
144144+ CAStreamBasicDescription mSrcFormat; // valid after OpenInputFile
145145+ CAStreamBasicDescription mDestFormat; // valid after OpenOutputFile
146146+147147+private:
148148+ CABufferList * mReadBuffer;
149149+ CABufferList * mReadPtrs;
150150+151151+protected:
152152+ char mOutName[PATH_MAX];
153153+};
154154+155155+#endif // __CAAudioFileConverter_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAChannelLayouts.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAChannelLayouts.h"
4444+#include <string.h>
4545+#include <stdio.h>
4646+4747+struct LayoutTag {
4848+ UInt32 constant;
4949+ const char *name;
5050+};
5151+5252+#define TAG(x) { x, #x },
5353+5454+static LayoutTag gLayoutTags[] = {
5555+ TAG(kAudioChannelLayoutTag_Mono)
5656+ TAG(kAudioChannelLayoutTag_Stereo)
5757+ TAG(kAudioChannelLayoutTag_StereoHeadphones)
5858+ TAG(kAudioChannelLayoutTag_MatrixStereo)
5959+ TAG(kAudioChannelLayoutTag_MidSide)
6060+ TAG(kAudioChannelLayoutTag_XY)
6161+ TAG(kAudioChannelLayoutTag_Binaural)
6262+ TAG(kAudioChannelLayoutTag_Ambisonic_B_Format)
6363+ TAG(kAudioChannelLayoutTag_Quadraphonic)
6464+ TAG(kAudioChannelLayoutTag_Pentagonal)
6565+ TAG(kAudioChannelLayoutTag_Hexagonal)
6666+ TAG(kAudioChannelLayoutTag_Octagonal)
6767+ TAG(kAudioChannelLayoutTag_Cube)
6868+ TAG(kAudioChannelLayoutTag_MPEG_1_0)
6969+ TAG(kAudioChannelLayoutTag_MPEG_2_0)
7070+ TAG(kAudioChannelLayoutTag_MPEG_3_0_A)
7171+ TAG(kAudioChannelLayoutTag_MPEG_3_0_B)
7272+ TAG(kAudioChannelLayoutTag_MPEG_4_0_A)
7373+ TAG(kAudioChannelLayoutTag_MPEG_4_0_B)
7474+ TAG(kAudioChannelLayoutTag_MPEG_5_0_A)
7575+ TAG(kAudioChannelLayoutTag_MPEG_5_0_B)
7676+ TAG(kAudioChannelLayoutTag_MPEG_5_0_C)
7777+ TAG(kAudioChannelLayoutTag_MPEG_5_0_D)
7878+ TAG(kAudioChannelLayoutTag_MPEG_5_1_A)
7979+ TAG(kAudioChannelLayoutTag_MPEG_5_1_B)
8080+ TAG(kAudioChannelLayoutTag_MPEG_5_1_C)
8181+ TAG(kAudioChannelLayoutTag_MPEG_5_1_D)
8282+ TAG(kAudioChannelLayoutTag_MPEG_6_1_A)
8383+ TAG(kAudioChannelLayoutTag_MPEG_7_1_A)
8484+ TAG(kAudioChannelLayoutTag_MPEG_7_1_B)
8585+ TAG(kAudioChannelLayoutTag_MPEG_7_1_C)
8686+ TAG(kAudioChannelLayoutTag_Emagic_Default_7_1)
8787+ TAG(kAudioChannelLayoutTag_SMPTE_DTV)
8888+ TAG(kAudioChannelLayoutTag_ITU_1_0)
8989+ TAG(kAudioChannelLayoutTag_ITU_2_0)
9090+ TAG(kAudioChannelLayoutTag_ITU_2_1)
9191+ TAG(kAudioChannelLayoutTag_ITU_2_2)
9292+ TAG(kAudioChannelLayoutTag_ITU_3_0)
9393+ TAG(kAudioChannelLayoutTag_ITU_3_1)
9494+ TAG(kAudioChannelLayoutTag_ITU_3_2)
9595+ TAG(kAudioChannelLayoutTag_ITU_3_2_1)
9696+ TAG(kAudioChannelLayoutTag_ITU_3_4_1)
9797+ TAG(kAudioChannelLayoutTag_DVD_0)
9898+ TAG(kAudioChannelLayoutTag_DVD_1)
9999+ TAG(kAudioChannelLayoutTag_DVD_2)
100100+ TAG(kAudioChannelLayoutTag_DVD_3)
101101+ TAG(kAudioChannelLayoutTag_DVD_4)
102102+ TAG(kAudioChannelLayoutTag_DVD_5)
103103+ TAG(kAudioChannelLayoutTag_DVD_6)
104104+ TAG(kAudioChannelLayoutTag_DVD_7)
105105+ TAG(kAudioChannelLayoutTag_DVD_8)
106106+ TAG(kAudioChannelLayoutTag_DVD_9)
107107+ TAG(kAudioChannelLayoutTag_DVD_10)
108108+ TAG(kAudioChannelLayoutTag_DVD_11)
109109+ TAG(kAudioChannelLayoutTag_DVD_12)
110110+ TAG(kAudioChannelLayoutTag_DVD_13)
111111+ TAG(kAudioChannelLayoutTag_DVD_14)
112112+ TAG(kAudioChannelLayoutTag_DVD_15)
113113+ TAG(kAudioChannelLayoutTag_DVD_16)
114114+ TAG(kAudioChannelLayoutTag_DVD_17)
115115+ TAG(kAudioChannelLayoutTag_DVD_18)
116116+ TAG(kAudioChannelLayoutTag_DVD_19)
117117+ TAG(kAudioChannelLayoutTag_DVD_20)
118118+ TAG(kAudioChannelLayoutTag_AudioUnit_4)
119119+ TAG(kAudioChannelLayoutTag_AudioUnit_5)
120120+ TAG(kAudioChannelLayoutTag_AudioUnit_6)
121121+ TAG(kAudioChannelLayoutTag_AudioUnit_8)
122122+ TAG(kAudioChannelLayoutTag_AudioUnit_5_0)
123123+ TAG(kAudioChannelLayoutTag_AudioUnit_6_0)
124124+ TAG(kAudioChannelLayoutTag_AudioUnit_7_0)
125125+ TAG(kAudioChannelLayoutTag_AudioUnit_5_1)
126126+ TAG(kAudioChannelLayoutTag_AudioUnit_6_1)
127127+ TAG(kAudioChannelLayoutTag_AudioUnit_7_1)
128128+ TAG(kAudioChannelLayoutTag_AAC_Quadraphonic)
129129+ TAG(kAudioChannelLayoutTag_AAC_4_0)
130130+ TAG(kAudioChannelLayoutTag_AAC_5_0)
131131+ TAG(kAudioChannelLayoutTag_AAC_5_1)
132132+ TAG(kAudioChannelLayoutTag_AAC_6_0)
133133+ TAG(kAudioChannelLayoutTag_AAC_6_1)
134134+ TAG(kAudioChannelLayoutTag_AAC_7_0)
135135+ TAG(kAudioChannelLayoutTag_AAC_7_1)
136136+ TAG(kAudioChannelLayoutTag_AAC_Octagonal)
137137+138138+ TAG(kAudioChannelLayoutTag_TMH_10_2_std)
139139+ TAG(kAudioChannelLayoutTag_TMH_10_2_full)
140140+ { 0, NULL } // sentinel
141141+};
142142+143143+static const char *prefix = "kAudioChannelLayoutTag_";
144144+145145+UInt32 CAChannelLayouts::StringToConstant(const char *s)
146146+{
147147+ int prefixlen = strlen(prefix);
148148+ for (LayoutTag *t = gLayoutTags; t->name != NULL; ++t) {
149149+ if (!strcmp(t->name, s) || !strcmp(t->name + prefixlen, s))
150150+ return t->constant;
151151+ }
152152+ return kInvalidTag;
153153+}
154154+155155+const char * CAChannelLayouts::ConstantToString(UInt32 layoutTag)
156156+{
157157+ static char buffer[256];
158158+ for (LayoutTag *t = gLayoutTags; t->name != NULL; ++t) {
159159+ if (layoutTag == t->constant)
160160+ return t->name + strlen(prefix);
161161+ }
162162+ sprintf(buffer, "unknown (0x%lx)", layoutTag);
163163+ return buffer;
164164+}
165165+
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAChannelLayouts.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAChannelLayouts_h__
4444+#define __CAChannelLayouts_h__
4545+4646+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4747+ #include <CoreAudio/CoreAudioTypes.h>
4848+#else
4949+ #include <CoreAudioTypes.h>
5050+#endif
5151+5252+// convert between channel layout tag constant and its name
5353+class CAChannelLayouts {
5454+public:
5555+ static const AudioChannelLayoutTag kInvalidTag = 0xFFFF0000;
5656+5757+ static AudioChannelLayoutTag StringToConstant(const char *s);
5858+ static const char * ConstantToString(AudioChannelLayoutTag layoutTag);
5959+};
6060+6161+6262+#endif // __CAChannelLayouts_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAFilePathUtils.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAFilePathUtils.h"
4444+#include <string.h>
4545+4646+OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName)
4747+{
4848+ // convert C string to CFString
4949+#if !TARGET_OS_WIN32
5050+ CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
5151+#else
5252+ CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingWindowsLatin1);
5353+#endif
5454+ // convert CF string to URL
5555+ CFURLRef fullurl = CFURLCreateWithFileSystemPath(NULL, cfFullPath, TARGET_OS_WIN32 ? kCFURLWindowsPathStyle : kCFURLPOSIXPathStyle, false);
5656+ CFRelease(cfFullPath);
5757+ // get the directory portion of the URL
5858+ CFURLRef dirurl = CFURLCreateCopyDeletingLastPathComponent(NULL, fullurl);
5959+ // get the directory's FSSpec
6060+ OSStatus err = CFURLGetFSRef(dirurl, &outParentDir) ? OSStatus(noErr) : OSStatus(fnfErr);
6161+ CFRelease(dirurl);
6262+6363+ CFStringRef lastPathComponent = CFURLCopyLastPathComponent(fullurl);
6464+ CFRelease(fullurl);
6565+ CFMutableStringRef filename = CFStringCreateMutableCopy(NULL, 0, lastPathComponent);
6666+ CFRelease(lastPathComponent);
6767+ // convert colons (legal in POSIX paths, illegal in File Manager) to slashes
6868+ CFStringFindAndReplace(filename, CFSTR(":"), CFSTR("/"), CFRangeMake(0, CFStringGetLength(filename)), 0);
6969+7070+ outFileName = filename;
7171+7272+ return err;
7373+}
7474+7575+7676+#if TARGET_OS_WIN32
7777+7878+char* dirname(const char* inPath)
7979+{
8080+ static char sAnswer[1024];
8181+8282+ char* theAnswer = NULL;
8383+ SInt32 thePathLength = strlen(inPath);
8484+ if(thePathLength < 1023)
8585+ {
8686+ // make a working copy
8787+ strcpy(sAnswer, inPath);
8888+8989+ // start at the end of the string
9090+ SInt32 theIndex = thePathLength - 1;
9191+9292+ // walk back over the '\' characters
9393+ while((theIndex > 0) && (sAnswer[theIndex] == '\\'))
9494+ {
9595+ --theIndex;
9696+ }
9797+9898+ // now keep walking back until we get to a '\'
9999+ while((theIndex > 0) && (sAnswer[theIndex] != '\\'))
100100+ {
101101+ --theIndex;
102102+ }
103103+104104+ // where we are now is either the first character of the path or the '\' that marks the end of the directory name
105105+ if(theIndex > 0)
106106+ {
107107+ // we have a name so put a '\0' in place of the '\'
108108+ sAnswer[theIndex] = 0;
109109+ }
110110+ else
111111+ {
112112+ // no name, so the answer is "."
113113+ sAnswer[0] = '.';
114114+ sAnswer[1] = 0;
115115+ }
116116+117117+ // set the return value
118118+ theAnswer = sAnswer;
119119+ }
120120+121121+ return theAnswer;
122122+}
123123+124124+char* basename(const char* inPath)
125125+{
126126+ static char sAnswer[1024];
127127+128128+ char* theAnswer = NULL;
129129+ SInt32 thePathLength = strlen(inPath);
130130+ if(thePathLength < 1023)
131131+ {
132132+ // make a working copy
133133+ strcpy(sAnswer, inPath);
134134+135135+ // start at the end of the string
136136+ SInt32 theLastIndex = thePathLength - 1;
137137+138138+ // walk back over the '\' characters
139139+ while((theLastIndex > 0) && (sAnswer[theLastIndex] == '\\'))
140140+ {
141141+ --theLastIndex;
142142+ }
143143+144144+ // check to see if we're at the beginning now
145145+ if(theLastIndex > 0)
146146+ {
147147+ // there's a name in there now, so start where we are and go back to the next '\'
148148+ UInt32 theFirstIndex = theLastIndex;
149149+ while((theFirstIndex > 0) && (sAnswer[theFirstIndex] != '\\'))
150150+ {
151151+ --theFirstIndex;
152152+ }
153153+154154+ // we now have a string, so put a '\0' after the last character
155155+ sAnswer[theLastIndex + 1] = 0;
156156+157157+ // and set the return value
158158+ theAnswer = &sAnswer[theFirstIndex];
159159+ }
160160+ else
161161+ {
162162+ // the path was entirely '\' characters, so the return value is "\"
163163+ sAnswer[0] = '\\';
164164+ sAnswer[1] = 0;
165165+166166+ // set the return value
167167+ theAnswer = sAnswer;
168168+ }
169169+ }
170170+171171+ return theAnswer;
172172+}
173173+174174+#endif
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ CAFilePathUtils.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __CAFilePathUtils_h__
4444+#define __CAFilePathUtils_h__
4545+4646+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4747+ #include <CoreServices/CoreServices.h>
4848+ #include <CoreFoundation/CoreFoundation.h>
4949+#else
5050+ #include <TargetConditionals.h>
5151+ #include <CoreServices.h>
5252+ #include <CoreFoundation.h>
5353+#endif
5454+5555+OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName);
5656+#if !TARGET_OS_WIN32
5757+ #include <libgen.h>
5858+#else
5959+ char* dirname(const char* inPath);
6060+ char* basename(const char* inPath);
6161+#endif
6262+6363+#endif // __CAFilePathUtils_h__
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ QTAACFile.cpp
4040+4141+=============================================================================*/
4242+4343+#include "QTAACFile.h"
4444+#include "CAXException.h"
4545+#include "CAStreamBasicDescription.h"
4646+4747+4848+// _______________________________________________________________________________________
4949+//
5050+QTAACFile::QTAACFile() :
5151+ mMovieResFile(-1),
5252+ mMovie(NULL),
5353+ mPacketHandle(NULL),
5454+ mMagicCookie(NULL),
5555+ mConverter(NULL),
5656+ mFileMaxPacketSize(0)
5757+{
5858+}
5959+6060+// _______________________________________________________________________________________
6161+//
6262+QTAACFile::~QTAACFile()
6363+{
6464+ Close();
6565+ CloseConverter();
6666+ if (mPacketHandle)
6767+ DisposeHandle(mPacketHandle);
6868+}
6969+7070+// _______________________________________________________________________________________
7171+//
7272+void QTAACFile::Close()
7373+{
7474+ if (mMovieResFile != -1) {
7575+ CloseMovieFile(mMovieResFile);
7676+ mMovieResFile = -1;
7777+ }
7878+ if (mMovie) {
7979+ DisposeMovie(mMovie);
8080+ mMovie = NULL;
8181+ }
8282+ if (mMagicCookie) {
8383+ free(mMagicCookie);
8484+ mMagicCookie = NULL;
8585+ }
8686+}
8787+8888+// _______________________________________________________________________________________
8989+//
9090+void QTAACFile::CloseConverter()
9191+{
9292+ if (mConverter) {
9393+ AudioConverterDispose(mConverter);
9494+ mConverter = NULL;
9595+ }
9696+}
9797+9898+// _______________________________________________________________________________________
9999+/*
100100+ GetMP4DecoderConfig
101101+102102+ NOTE: This is designed to work only for a very specific case -- an MPEG-4/QuickTime movie
103103+ containing AAC-encoded audio. It is adapted from the "SoundPlayer"QuickTime sample code,
104104+ but with much generality removed.
105105+106106+ If the audio is not MPEG-4, then we'll fail immediately with an exception.
107107+108108+ If the audio is MPEG-4, but not AAC-encoded, then we will fail somewhere beyond this function, when passing the magic cookie (ESDS) to the AudioConverter.
109109+*/
110110+static void GetMP4DecoderConfig(Media inMedia, AudioStreamBasicDescription &outStreamFormat, char **outEsds, UInt32 *outEsdsSize)
111111+{
112112+ OSStatus err = noErr;
113113+ Size size;
114114+ Handle extension = NULL;
115115+ SoundDescriptionHandle hSoundDescription = (SoundDescriptionHandle)NewHandle(0);
116116+ struct MyMP4AudioAtom {
117117+ UInt32 size;
118118+ OSType atomType;
119119+ UInt32 version;
120120+ };
121121+122122+ try {
123123+ // get the description of the sample data
124124+ GetMediaSampleDescription(inMedia, 1, (SampleDescriptionHandle)hSoundDescription);
125125+ XThrowIfError(GetMoviesError(), "couldn't get media sample description");
126126+127127+ // other formats: exercise for the reader!
128128+ OSType fmt = (*hSoundDescription)->dataFormat;
129129+ XThrowIf(fmt != 'mp4a', -1, "can only decode MPEG-4/AAC");
130130+131131+ extension = NewHandle(0);
132132+133133+ // get the "magic" decompression atom
134134+ // This extension to the SoundDescription information stores data specific to a given audio decompressor.
135135+ // Some audio decompression algorithms require a set of out-of-stream values to configure the decompressor
136136+ // which are stored in a siDecompressionParams atom. The contents of the siDecompressionParams atom are dependent
137137+ // on the audio decompressor.
138138+139139+ err = GetSoundDescriptionExtension(hSoundDescription, &extension, siDecompressionParams);
140140+141141+ // if it doesn't have an atom, that's ok for some formats, but not for AAC
142142+ XThrowIfError(err, "couldn't get sound description extension");
143143+144144+ size = GetHandleSize(extension);
145145+ HLock(extension);
146146+ UserDataAtom *atom = (UserDataAtom *)*extension;
147147+ bool moreAtoms = true;
148148+ do {
149149+ long atomSize = EndianS32_BtoN(atom->size);
150150+151151+ XThrowIf(atomSize < 8, -1, "invalid sound description atom");
152152+ switch (EndianU32_BtoN(atom->atomType)) {
153153+ case 'esds':
154154+ *outEsdsSize = atomSize - sizeof(MyMP4AudioAtom);
155155+ *outEsds = (char *)malloc(*outEsdsSize);
156156+ memcpy(*outEsds, (char *)atom + sizeof(MyMP4AudioAtom), *outEsdsSize);
157157+ break;
158158+ case kAudioTerminatorAtomType:
159159+ moreAtoms = false;
160160+ break;
161161+ }
162162+ atom = (UserDataAtom *)((char *)atom + atomSize);
163163+ } while (moreAtoms);
164164+165165+ HUnlock(extension);
166166+167167+ // set up our stream description
168168+ memset(&outStreamFormat, 0, sizeof(AudioStreamBasicDescription));
169169+ outStreamFormat.mFormatID = kAudioFormatMPEG4AAC;
170170+ }
171171+ catch (...) {
172172+ if (extension) DisposeHandle(extension);
173173+ if (hSoundDescription) DisposeHandle((Handle)hSoundDescription);
174174+ throw;
175175+ }
176176+ if (extension) DisposeHandle(extension);
177177+ if (hSoundDescription) DisposeHandle((Handle)hSoundDescription);
178178+}
179179+180180+// _______________________________________________________________________________________
181181+//
182182+void QTAACFile::Open(const char *filename)
183183+{
184184+ FSRef theFSRef;
185185+ Track theAudioTrack;
186186+ FSSpec theFSSpec;
187187+188188+ // convert from POSIX full path to FSSpec
189189+ XThrowIfError(FSPathMakeRef((UInt8 *)filename, &theFSRef, NULL), "locate file");
190190+ XThrowIfError(FSGetCatalogInfo(&theFSRef, 0, NULL, NULL, &theFSSpec, NULL), "get FSSpec");
191191+192192+ // make a QuickTime movie (will open MP4 transparently)
193193+ XThrowIfError(OpenMovieFile(&theFSSpec, &mMovieResFile, fsRdPerm), "OpenMovieFile failed");
194194+ SInt16 nResID = 0;
195195+ Str255 strName;
196196+ Boolean bWasChanged;
197197+ XThrowIfError(NewMovieFromFile(&mMovie, mMovieResFile, &nResID, strName, newMovieActive, &bWasChanged), "NewMovieFromFile failed");
198198+199199+ // NOTE: we're assuming the data we want is in the movie's first enabled audio track
200200+ theAudioTrack = GetMovieIndTrackType(mMovie, 1, SoundMediaType, movieTrackMediaType | movieTrackEnabledOnly);
201201+ XThrowIf(theAudioTrack == NULL, -1, "movie contains no audio track");
202202+203203+ // find the track's media, and interrogate it for the audio format and magic cookie (decoder config)
204204+ mMedia = GetTrackMedia(theAudioTrack);
205205+ XThrowIf(mMedia == NULL, -1, "track contains no media");
206206+ GetMP4DecoderConfig(mMedia, mFileDataFormat, &mMagicCookie, &mMagicCookieSize);
207207+208208+ // Fill out the remaining fields of the ASBD by evaluating the magic cookie
209209+ UInt32 size = sizeof(mFileDataFormat);
210210+ XThrowIfError(AudioFormatGetProperty(kAudioFormatProperty_ASBDFromESDS, mMagicCookieSize, mMagicCookie, &size, &mFileDataFormat),
211211+ "couldn't get ASBD from the Magic Cookie");
212212+213213+ // build a vector of times at which packets begin
214214+ // so later we can randomly access the file by packet number
215215+ TimeValue currentTime = 0;
216216+ static const Fixed oneFixed = 0x10000;
217217+ while (true) {
218218+ TimeValue interestingTime, interestingDuration;
219219+ GetMediaNextInterestingTime(mMedia, nextTimeMediaSample | nextTimeEdgeOK, currentTime, oneFixed, &interestingTime, &interestingDuration);
220220+ if (interestingTime < 0)
221221+ break;
222222+ mPacketTimes.push_back(interestingTime);
223223+ currentTime = interestingTime + 1;
224224+ }
225225+ mNumberPackets = mPacketTimes.size();
226226+ mPacketMark = 0;
227227+ mPacketHandle = NewHandle(1024); // memory into which packets will be read
228228+}
229229+230230+// _______________________________________________________________________________________
231231+//
232232+void QTAACFile::SetClientFormat(const CAStreamBasicDescription &dataFormat)
233233+{
234234+ CloseConverter();
235235+236236+ XThrowIf(!dataFormat.IsPCM(), -1, "non-PCM client format on audio file");
237237+ mClientDataFormat = dataFormat;
238238+239239+ if (mClientDataFormat != mFileDataFormat) {
240240+ // We need an AudioConverter.
241241+ // file -> client
242242+ XThrowIfError(AudioConverterNew(&mFileDataFormat, &mClientDataFormat, &mConverter),
243243+ "create audio converter");
244244+245245+ // set the magic cookie, if any (for decode)
246246+ if (mMagicCookie)
247247+ SetConverterProperty(kAudioConverterDecompressionMagicCookie,
248248+ mMagicCookieSize, mMagicCookie, true);
249249+ }
250250+ UpdateClientMaxPacketSize();
251251+}
252252+253253+// _______________________________________________________________________________________
254254+//
255255+OSStatus QTAACFile::SetConverterProperty(AudioConverterPropertyID inPropertyID,
256256+ UInt32 inPropertyDataSize,
257257+ const void* inPropertyData,
258258+ bool inCanFail)
259259+{
260260+ OSStatus err = AudioConverterSetProperty(mConverter, inPropertyID, inPropertyDataSize, inPropertyData);
261261+ if (!inCanFail) {
262262+ XThrowIfError(err, "set audio converter property");
263263+ }
264264+ UpdateClientMaxPacketSize();
265265+ return err;
266266+}
267267+268268+// _______________________________________________________________________________________
269269+//
270270+void QTAACFile::UpdateClientMaxPacketSize()
271271+{
272272+ if (mConverter != NULL) {
273273+ AudioConverterPropertyID property =
274274+ kAudioConverterPropertyMaximumOutputPacketSize;
275275+276276+ UInt32 propertySize = sizeof(UInt32);
277277+ XThrowIfError(AudioConverterGetProperty(mConverter, property, &propertySize, &mClientMaxPacketSize),
278278+ "get audio converter's maximum packet size");
279279+ } else
280280+ mClientMaxPacketSize = mFileMaxPacketSize;
281281+ XThrowIf(mClientMaxPacketSize == 0, -1, "client maximum packet size is 0");
282282+}
283283+284284+// _______________________________________________________________________________________
285285+//
286286+// This function reads the next packet from the movie. It always reads only 1 packet,
287287+// regardless of how many were asked for -- whether it's called either as a callback from
288288+// AudioConverterFillComplexBuffer, or directly from ReadPackets (below), the caller
289289+// will just call again if it wants more.
290290+OSStatus QTAACFile::ReadInputProc( AudioConverterRef inAudioConverter,
291291+ UInt32* ioNumberDataPackets,
292292+ AudioBufferList* ioData,
293293+ AudioStreamPacketDescription** outDataPacketDescription,
294294+ void* inUserData)
295295+{
296296+ QTAACFile *This = static_cast<QTAACFile *>(inUserData);
297297+298298+ UInt32 remainingPacketsInFile = This->mNumberPackets - This->mPacketMark;
299299+ if (remainingPacketsInFile == 0) {
300300+ // end of file
301301+ *ioNumberDataPackets = 0;
302302+ ioData->mBuffers[0].mDataByteSize = 0;
303303+ return noErr; // EOF is signified by 0 packets/0 bytes/noErr
304304+ }
305305+306306+ UInt32 ioPackets = 1;
307307+308308+ // don't try to read past EOF
309309+ if (ioPackets > remainingPacketsInFile)
310310+ ioPackets = remainingPacketsInFile;
311311+312312+ long bytesRead;
313313+ OSStatus err;
314314+315315+ HUnlock(This->mPacketHandle);
316316+ err = GetMediaSample(This->mMedia, // specifies the media for this operation
317317+ This->mPacketHandle, // function returns the sample data into this handle
318318+ 0, // maximum number of bytes of sample data to be returned
319319+ &bytesRead, // the number of bytes of sample data returned
320320+ This->mPacketTimes[This->mPacketMark],
321321+ // starting time of the sample to be retrieved (must be in Media's TimeScale)
322322+ NULL, // indicates the actual time of the returned sample data
323323+ NULL, // duration of each sample in the media
324324+ NULL, // sample description corresponding to the returned sample data (NULL to ignore)
325325+ NULL, // index value to the sample description that corresponds to the returned sample data (NULL to ignore)
326326+ 0, // maximum number of samples to be returned (0 to use a value that is appropriate for the media)
327327+ NULL, // number of samples it actually returned
328328+ NULL); // flags that describe the sample (NULL to ignore)
329329+330330+ if (err)
331331+ return err;
332332+333333+ if (outDataPacketDescription) {
334334+ This->mPacketDescription.mStartOffset = 0;
335335+ This->mPacketDescription.mVariableFramesInPacket = 0;
336336+ This->mPacketDescription.mDataByteSize = bytesRead;
337337+ *outDataPacketDescription = &This->mPacketDescription;
338338+ }
339339+340340+ HLock(This->mPacketHandle);
341341+ ioData->mBuffers[0].mDataByteSize = bytesRead;
342342+ ioData->mBuffers[0].mData = *This->mPacketHandle;
343343+ This->mPacketMark += ioPackets;
344344+ *ioNumberDataPackets = ioPackets;
345345+ return noErr;
346346+}
347347+348348+// _______________________________________________________________________________________
349349+//
350350+void QTAACFile::ReadPackets(UInt32 &ioNumPackets, AudioBufferList *ioData)
351351+{
352352+ // older versions of AudioConverterFillComplexBuffer don't do this, so do our own sanity check
353353+ UInt32 maxNumPackets = ioData->mBuffers[0].mDataByteSize / mClientMaxPacketSize;
354354+ if (ioNumPackets > maxNumPackets)
355355+ ioNumPackets = maxNumPackets;
356356+357357+ if (mConverter == NULL)
358358+ XThrowIfError(ReadInputProc(NULL, &ioNumPackets, ioData, NULL, this), "read audio file");
359359+ else {
360360+ XThrowIfError(AudioConverterFillComplexBuffer(mConverter, ReadInputProc, this, &ioNumPackets, ioData, NULL),
361361+ "qt convert audio packets");
362362+ }
363363+}
+109
src/CoreAudio/AudioFileTools/Utility/QTAACFile.h
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ QTAACFile.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __QTAACFile_h__
4444+#define __QTAACFile_h__
4545+4646+#include <QuickTime/QuickTime.h>
4747+#include <AudioToolbox/AudioConverter.h>
4848+#include <AudioToolbox/AudioFormat.h>
4949+#include <vector>
5050+#include "CAStreamBasicDescription.h"
5151+#include "CAAudioChannelLayout.h"
5252+5353+/*
5454+ This class is a stripped-down analogue to CAAudioFile, designed solely for reading AAC audio
5555+ tracks from QuickTime/MP4 files.
5656+5757+ Throws CAXException's on errors.
5858+*/
5959+class QTAACFile {
6060+public:
6161+ QTAACFile();
6262+ ~QTAACFile();
6363+6464+ void Open(const char *filePath);
6565+ void Close();
6666+6767+ void SetClientFormat(const CAStreamBasicDescription &dataFormat);
6868+ // set the PCM format to which the movie's audio will be decoded
6969+7070+ OSStatus SetConverterProperty( AudioConverterPropertyID inPropertyID,
7171+ UInt32 inPropertyDataSize,
7272+ const void* inPropertyData,
7373+ bool inCanFail);
7474+7575+ void ReadPackets(UInt32 &ioNumPackets, AudioBufferList *ioData);
7676+ // read packets from the audio file in the client format
7777+7878+private:
7979+ void CloseConverter();
8080+ void UpdateClientMaxPacketSize();
8181+8282+ static OSStatus ReadInputProc( AudioConverterRef inAudioConverter,
8383+ UInt32* ioNumberDataPackets,
8484+ AudioBufferList* ioData,
8585+ AudioStreamPacketDescription** outDataPacketDescription,
8686+ void* inUserData);
8787+8888+private:
8989+ typedef std::vector<TimeValue> TimeValueList;
9090+9191+ SInt16 mMovieResFile;
9292+ Movie mMovie;
9393+ Media mMedia;
9494+ Handle mPacketHandle;
9595+ UInt32 mMagicCookieSize;
9696+ char * mMagicCookie;
9797+ TimeValueList mPacketTimes;
9898+ UInt32 mNumberPackets; // in file's format
9999+ UInt32 mPacketMark; // location in file, in file's format
100100+101101+ CAStreamBasicDescription mFileDataFormat;
102102+ CAStreamBasicDescription mClientDataFormat;
103103+ AudioConverterRef mConverter;
104104+ UInt32 mFileMaxPacketSize;
105105+ UInt32 mClientMaxPacketSize;
106106+ AudioStreamPacketDescription mPacketDescription;
107107+};
108108+109109+#endif // __QTAACFile_h__
+251
src/CoreAudio/AudioFileTools/afconvert.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ afconvert.cpp
4040+4141+=============================================================================*/
4242+4343+/*
4444+ afconvert
4545+4646+ command-line tool to convert an audio file to another format
4747+*/
4848+4949+#include "afconvert.h"
5050+#include <stdio.h>
5151+#include <vector>
5252+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
5353+ #include <CoreServices/CoreServices.h>
5454+ #include <AudioToolbox/AudioToolbox.h>
5555+#else
5656+ #include <CoreServices.h>
5757+ #include <AudioToolbox.h>
5858+#endif
5959+#include "CAChannelLayouts.h"
6060+6161+#include "CAAudioFileConverter.h"
6262+#include "CAXException.h"
6363+#include "CAAudioFileFormats.h"
6464+#include "AFToolsCommon.h"
6565+#if !TARGET_OS_MAC
6666+ #include <QTML.h>
6767+ #include "CAWindows.h"
6868+#endif
6969+7070+7171+void AFConvertTool::usage()
7272+{
7373+ fprintf(stderr,
7474+ "Usage:\n"
7575+ "%s [option...] input_file [output_file]\n\n"
7676+ "Options: (may appear before or after arguments)\n"
7777+ " { -f | --file } file_format:\n",
7878+#if !TARGET_OS_WIN32
7979+ getprogname());
8080+#else
8181+ "afconvert");
8282+#endif
8383+ PrintAudioFileTypesAndFormats(stderr);
8484+ fprintf(stderr,
8585+ " { -d | --data } data_format[@sample_rate_hz][/format_flags][#frames_per_packet] :\n"
8686+ " [-][BE|LE]{F|[U]I}{8|16|24|32|64} (PCM)\n"
8787+ " e.g. BEI16 F32@44100\n"
8888+ " or a data format appropriate to file format, as above\n"
8989+ " format_flags: hex digits, e.g. '80'\n"
9090+ " bitdepth on non-PCM formats can be specified, e.g.: alac-24\n"
9191+ " Frames per packet can be specified for some encoders, e.g.: samr#12\n"
9292+ " { -c | --channels } number_of_channels\n"
9393+ " add/remove channels without regard to order\n"
9494+ " { -l | --channellayout } layout_tag\n"
9595+ " layout_tag: name of a constant from CoreAudioTypes.h\n"
9696+ " (prefix \"kAudioChannelLayoutTag_\" may be omitted)\n"
9797+ " if specified once, applies to output file; if twice, the first\n"
9898+ " applies to the input file, the second to the output file\n"
9999+ " { -b | --bitrate } bit_rate_bps\n"
100100+ " e.g. 128000\n"
101101+ " { -q | --quality } codec_quality\n"
102102+ " codec_quality: 0-127\n"
103103+ " { -r | --src-quality } src_quality\n"
104104+ " src_quality (sample rate converter quality): 0-127\n"
105105+ " { -v | --verbose }\n"
106106+ " print progress verbosely\n"
107107+ " { -s | --strategy } strategy\n"
108108+ " bitrate strategy for encoded file\n"
109109+ " 0 for CBR, 1 for ABR, 2 for VBR\n"
110110+ " { -t | --tag }\n"
111111+ " If encoding to CAF, store the source file's format and name in a user chunk.\n"
112112+ " If decoding from CAF, use the destination format and filename found in a user chunk.\n"
113113+ " --prime-method method\n"
114114+ " decode priming method (see AudioConverter.h)\n"
115115+ );
116116+ ExtraUsageOptions();
117117+ exit(1);
118118+}
119119+120120+void Warning(const char *s, OSStatus error)
121121+{
122122+ char buf[256];
123123+ fprintf(stderr, "*** warning: %s (%s)\n", s, CAXException::FormatError(buf, sizeof(buf), error));
124124+}
125125+126126+OSType AFConvertTool::Parse4CharCode(const char *arg, const char *name)
127127+{
128128+ OSType t;
129129+ StrToOSType(arg, t);
130130+ if (t == 0) {
131131+ fprintf(stderr, "invalid 4-char-code argument for %s: '%s'\n\n", name, arg);
132132+ usage();
133133+ }
134134+ return t;
135135+}
136136+137137+138138+int AFConvertTool::main(int argc, const char * argv[])
139139+{
140140+ Init();
141141+142142+ CAAudioFileConverter::ConversionParameters ¶ms = *mParams;
143143+ bool gotOutDataFormat = false;
144144+145145+ CAXException::SetWarningHandler(Warning);
146146+147147+ if (argc < 2)
148148+ usage();
149149+150150+ params.flags = CAAudioFileConverter::kOpt_OverwriteOutputFile;
151151+152152+ for (int i = 1; i < argc; ++i) {
153153+ const char *arg = argv[i];
154154+ if (arg[0] != '-') {
155155+ if (params.input.filePath == NULL) params.input.filePath = arg;
156156+ else if (params.output.filePath == NULL) params.output.filePath = arg;
157157+ else usage();
158158+ } else {
159159+ arg += 1;
160160+ if (arg[0] == 'f' || !strcmp(arg, "-file")) {
161161+ if (++i == argc) MissingArgument();
162162+ params.output.fileType = Parse4CharCode(argv[i], "-f | --file");
163163+ } else if (arg[0] == 'd' || !strcmp(arg, "-data")) {
164164+ if (++i == argc) MissingArgument();
165165+ if (!ParseStreamDescription(argv[i], params.output.dataFormat))
166166+ usage();
167167+ gotOutDataFormat = true;
168168+ } else if (arg[0] == 'b' || !strcmp(arg, "-bitrate")) {
169169+ if (++i == argc) MissingArgument();
170170+ params.output.bitRate = ParseInt(argv[i], "-b | --bitrate");
171171+ } else if (arg[0] == 'q' || !strcmp(arg, "-quality")) {
172172+ if (++i == argc) MissingArgument();
173173+ params.output.codecQuality = ParseInt(argv[i], "-q | --quality");
174174+ } else if (arg[0] == 'r' || !strcmp(arg, "-src-quality")) {
175175+ if (++i == argc) MissingArgument();
176176+ params.output.srcQuality = ParseInt(argv[i], "-r | --src-quality");
177177+ } else if (arg[0] == 'l' || !strcmp(arg, "-channellayout")) {
178178+ if (++i == argc) MissingArgument();
179179+ UInt32 tag = CAChannelLayouts::StringToConstant(argv[i]);
180180+ if (tag == CAChannelLayouts::kInvalidTag) {
181181+ fprintf(stderr, "unknown channel layout tag: %s\n\n", argv[i]);
182182+ usage();
183183+ }
184184+ if (params.output.channelLayoutTag == 0)
185185+ params.output.channelLayoutTag = tag;
186186+ else if (params.input.channelLayoutTag == 0) {
187187+ params.input.channelLayoutTag = params.output.channelLayoutTag;
188188+ params.output.channelLayoutTag = tag;
189189+ } else {
190190+ fprintf(stderr, "too many channel layout tags!\n\n");
191191+ usage();
192192+ }
193193+ } else if (arg[0] == 'c' || !strcmp(arg, "-channels")) {
194194+ if (++i == argc) MissingArgument();
195195+ params.output.channels = ParseInt(argv[i], "-c | --channels");
196196+ } else if (arg[0] == 'v' || !strcmp(arg, "-verbose")) {
197197+ params.flags |= CAAudioFileConverter::kOpt_Verbose;
198198+ } else if (arg[0] == 's' || !strcmp(arg, "-strategy")) {
199199+ if (++i == argc) MissingArgument();
200200+ params.output.strategy = ParseInt(argv[i], "-s | --strategy");
201201+ } else if (arg[0] == 't' || !strcmp(arg, "-tag")) {
202202+ params.flags |= CAAudioFileConverter::kOpt_CAFTag;
203203+ } else if (!strcmp(arg, "-prime-method")) {
204204+ if (++i == argc) MissingArgument();
205205+ params.output.primeMethod = ParseInt(argv[i], "-p | --prime-method");
206206+ } else if (!ParseOtherOption(argv, i)) {
207207+ fprintf(stderr, "unknown argument: %s\n\n", arg - 1);
208208+ usage();
209209+ }
210210+ }
211211+ }
212212+ if (params.input.filePath == NULL) {
213213+ fprintf(stderr, "no input file specified\n\n");
214214+ usage();
215215+ }
216216+217217+ if (!(params.flags & CAAudioFileConverter::kOpt_CAFTag)) {
218218+ if (!gotOutDataFormat) {
219219+ if (params.output.fileType == 0) {
220220+ fprintf(stderr, "no output file or data format specified\n\n");
221221+ usage();
222222+ }
223223+ if (!CAAudioFileFormats::Instance()->InferDataFormatFromFileFormat(params.output.fileType, params.output.dataFormat)) {
224224+ fprintf(stderr, "Couldn't infer data format from file format\n\n");
225225+ usage();
226226+ }
227227+ } else if (params.output.fileType == 0) {
228228+ CAAudioFileFormats *formats = CAAudioFileFormats::Instance();
229229+ if (!formats->InferFileFormatFromFilename(params.output.filePath, params.output.fileType) && !formats->InferFileFormatFromDataFormat(params.output.dataFormat, params.output.fileType)) {
230230+ params.output.dataFormat.PrintFormat(stderr, "", "Couldn't infer file format from data format");
231231+ usage();
232232+ }
233233+ }
234234+ }
235235+236236+ try {
237237+ mAFConverter->ConvertFile(params);
238238+ Success();
239239+ }
240240+ catch (CAXException &e) {
241241+ char buf[256];
242242+ fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf, sizeof(buf)));
243243+ return 1;
244244+ }
245245+ catch (...) {
246246+ fprintf(stderr, "An unknown error occurred\n");
247247+ return 1;
248248+ }
249249+250250+ return 0;
251251+}
+94
src/CoreAudio/AudioFileTools/afconvert.h
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ afconvert.h
4040+4141+=============================================================================*/
4242+4343+#ifndef __afconvert_h__
4444+#define __afconvert_h__
4545+4646+#include "CAAudioFileConverter.h"
4747+4848+class AFConvertTool {
4949+public:
5050+ AFConvertTool() :
5151+ mAFConverter(NULL),
5252+ mParams(NULL)
5353+ { }
5454+5555+ virtual ~AFConvertTool() {
5656+ delete mAFConverter;
5757+ delete mParams;
5858+ }
5959+6060+6161+ int main(int argc, const char *argv[]);
6262+ virtual void Init() { // called on entry to main
6363+ mParams = new CAAudioFileConverter::ConversionParameters;
6464+ mAFConverter = new CAAudioFileConverter;
6565+ }
6666+6767+ virtual bool ParseOtherOption(const char *argv[], int &argIndex) { return false; }
6868+ virtual void Success() { } // called after successful conversion
6969+7070+ void usage();
7171+ virtual void ExtraUsageOptions() { }
7272+ void MissingArgument() {
7373+ fprintf(stderr, "missing argument\n\n");
7474+ usage();
7575+ }
7676+ OSType Parse4CharCode(const char *arg, const char *name);
7777+7878+ int ParseInt(const char *arg, const char *name)
7979+ {
8080+ int x;
8181+ if (sscanf(arg, "%d", &x) != 1) {
8282+ fprintf(stderr, "invalid integer argument for %s: '%s'\n\n", name, arg);
8383+ usage();
8484+ }
8585+ return x;
8686+ }
8787+8888+8989+9090+ CAAudioFileConverter * mAFConverter;
9191+ CAAudioFileConverter::ConversionParameters *mParams;
9292+};
9393+9494+#endif // __afconvert_h__
+56
src/CoreAudio/AudioFileTools/afconvert_main.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ afconvert_main.cpp
4040+4141+=============================================================================*/
4242+4343+#include "afconvert.h"
4444+#if !TARGET_OS_MAC
4545+ #include <QTML.h>
4646+#endif
4747+4848+int main(int argc, const char * argv[])
4949+{
5050+ AFConvertTool t;
5151+5252+ int theAnswer = t.main(argc, argv);
5353+5454+ return theAnswer;
5555+}
5656+
+217
src/CoreAudio/AudioFileTools/afinfo.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ afinfo.cpp
4040+4141+=============================================================================*/
4242+4343+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
4444+ #include <AudioToolbox/AudioToolbox.h>
4545+#else
4646+ #include <AudioToolbox.h>
4747+#endif
4848+4949+#if TARGET_OS_WIN32
5050+ #include <QTML.h>
5151+#endif
5252+5353+#include <stdio.h>
5454+#include "CAStreamBasicDescription.h"
5555+#include <stdlib.h>
5656+#include <CoreServices/Endian.h>
5757+5858+//using namespace std;
5959+6060+int main (int argc, const char * argv[])
6161+{
6262+#if TARGET_OS_WIN32
6363+ InitializeQTML(0L);
6464+#endif
6565+ int enc = kCFStringEncodingUTF8;
6666+6767+ for (int i=1; i<argc; ++i)
6868+ {
6969+ OSStatus err;
7070+ CAStreamBasicDescription asbd;
7171+ AudioChannelLayout *acl = 0;
7272+ UInt32 propertySize;
7373+ UInt32 specifierSize;
7474+ AudioFileID afid;
7575+ Boolean res;
7676+ FSRef fsRef;
7777+ AudioFileTypeID filetype;
7878+ CFStringRef filename = CFStringCreateWithCString(NULL, argv[i], enc);
7979+ if (!filename) continue;
8080+8181+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, filename, kCFURLPOSIXPathStyle, true);
8282+ if (!url) {
8383+ fprintf(stderr, "Can't create CFURL for '%s'\n", argv[i]);
8484+ goto Bail3;
8585+ }
8686+8787+ res = CFURLGetFSRef(url, &fsRef);
8888+ if (!res) {
8989+ fprintf(stderr, "Can't get FSRef for '%s'\n", argv[i]);
9090+ goto Bail2;
9191+ }
9292+9393+ err = AudioFileOpen(&fsRef, fsRdPerm, 0, &afid);
9494+ if (err) {
9595+ fprintf(stderr, "AudioFileOpen failed for '%s'\n", argv[i]);
9696+ goto Bail2;
9797+ }
9898+9999+ propertySize = sizeof(AudioFileTypeID);
100100+ err = AudioFileGetProperty(afid, kAudioFilePropertyFileFormat, &propertySize, &filetype);
101101+ if (err) {
102102+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyFileFormat failed for '%s'\n", argv[i]);
103103+ goto Bail1;
104104+ }
105105+ filetype = EndianU32_NtoB(filetype); // for display purposes
106106+107107+ propertySize = sizeof(asbd);
108108+ err = AudioFileGetProperty(afid, kAudioFilePropertyDataFormat, &propertySize, &asbd);
109109+ if (err) {
110110+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyDataFormat failed for '%s'\n", argv[i]);
111111+ goto Bail1;
112112+ }
113113+114114+ printf("File: %s\n", argv[i]);
115115+ printf("File type ID: %-4.4s\n", (char *)&filetype);
116116+ asbd.PrintFormat(stdout, "", "Data format: ");
117117+118118+ UInt32 writable;
119119+ err = AudioFileGetPropertyInfo(afid, kAudioFilePropertyChannelLayout, &propertySize, &writable);
120120+ if (err) {
121121+ //fprintf(stderr, "AudioFileGetPropertyInfo kAudioFilePropertyChannelLayout failed for '%s'\n", argv[i]);
122122+ printf(" no channel layout.\n");
123123+ } else {
124124+125125+ acl = (AudioChannelLayout*)calloc(1, propertySize);
126126+ err = AudioFileGetProperty(afid, kAudioFilePropertyChannelLayout, &propertySize, acl);
127127+ if (err) {
128128+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyChannelLayout failed for '%s'\n", argv[i]);
129129+ goto Bail1;
130130+ }
131131+132132+ CFStringRef aclname;
133133+ char aclstr[512];
134134+ specifierSize = propertySize;
135135+ propertySize = sizeof(aclname);
136136+ AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName, specifierSize, acl, &propertySize, &aclname);
137137+ if (err) {
138138+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyChannelLayout failed for '%s'\n", argv[i]);
139139+ goto Bail1;
140140+ }
141141+ CFStringGetCString(aclname, aclstr, 512, kCFStringEncodingUTF8);
142142+143143+ printf("Channel layout: %s\n", aclstr);
144144+ }
145145+146146+ UInt64 dataByteCount;
147147+ propertySize = sizeof(dataByteCount);
148148+ err = AudioFileGetProperty(afid, kAudioFilePropertyAudioDataByteCount, &propertySize, &dataByteCount);
149149+ if (err) {
150150+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyAudioDataByteCount failed for '%s'\n", argv[i]);
151151+ } else {
152152+ printf("audio bytes: %llu\n", dataByteCount);
153153+ }
154154+155155+ UInt64 dataPacketCount;
156156+ UInt64 totalFrames;
157157+ totalFrames = 0;
158158+ propertySize = sizeof(dataPacketCount);
159159+ err = AudioFileGetProperty(afid, kAudioFilePropertyAudioDataPacketCount, &propertySize, &dataPacketCount);
160160+ if (err) {
161161+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyAudioDataPacketCount failed for '%s'\n", argv[i]);
162162+ } else {
163163+ printf("audio packets: %llu\n", dataPacketCount);
164164+ if (asbd.mFramesPerPacket)
165165+ totalFrames = asbd.mFramesPerPacket * dataPacketCount;
166166+ }
167167+168168+ AudioFilePacketTableInfo pti;
169169+ propertySize = sizeof(pti);
170170+ err = AudioFileGetProperty(afid, kAudioFilePropertyPacketTableInfo, &propertySize, &pti);
171171+ if (err == noErr) {
172172+ totalFrames = pti.mNumberValidFrames;
173173+ printf("audio %qd valid frames + %ld priming + %ld remainder = %qd\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames, pti.mNumberValidFrames + pti.mPrimingFrames + pti.mRemainderFrames);
174174+ }
175175+176176+ if (totalFrames != 0)
177177+ printf("duration: %.4f seconds\n", (double)totalFrames / (double)asbd.mSampleRate );
178178+179179+ UInt32 maxPacketSize;
180180+ propertySize = sizeof(maxPacketSize);
181181+ err = AudioFileGetProperty(afid, kAudioFilePropertyMaximumPacketSize, &propertySize, &maxPacketSize);
182182+ if (err) {
183183+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyMaximumPacketSize failed for '%s'\n", argv[i]);
184184+ } else {
185185+ printf("maximum packet size: %lu\n", maxPacketSize);
186186+ }
187187+188188+ UInt64 dataOffset;
189189+ propertySize = sizeof(dataOffset);
190190+ err = AudioFileGetProperty(afid, kAudioFilePropertyDataOffset, &propertySize, &dataOffset);
191191+ if (err) {
192192+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyDataOffset failed for '%s'\n", argv[i]);
193193+ } else {
194194+ printf("audio data file offset: %llu\n", dataOffset);
195195+ }
196196+197197+ UInt32 isOptimized;
198198+ propertySize = sizeof(isOptimized);
199199+ err = AudioFileGetProperty(afid, kAudioFilePropertyIsOptimized, &propertySize, &isOptimized);
200200+ if (err) {
201201+ fprintf(stderr, "AudioFileGetProperty kAudioFilePropertyIsOptimized failed for '%s'\n", argv[i]);
202202+ } else {
203203+ printf(isOptimized ? "optimized\n" : "not optimized\n");
204204+ }
205205+206206+ Bail1:
207207+ AudioFileClose(afid);
208208+ Bail2:
209209+ CFRelease(url);
210210+ Bail3:
211211+ CFRelease(filename);
212212+ free(acl);
213213+214214+ printf("----\n");
215215+ }
216216+ return 0;
217217+}
+252
src/CoreAudio/AudioFileTools/afinterleave.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ Interleaver.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAAudioFile.h"
4444+#include "CAXException.h"
4545+#include <unistd.h>
4646+#include "CAChannelLayouts.h"
4747+#include "CAFilePathUtils.h"
4848+4949+static void usage()
5050+{
5151+ fprintf(stderr,
5252+ "Usage:\n"
5353+ "%s [option...] input_file... -o output_file\n\n"
5454+ "Options: (may appear before or after arguments)\n"
5555+ " { -l | --channellayout } layout_tag\n"
5656+ " layout_tag: name of a constant from CoreAudioTypes.h\n"
5757+ " (prefix \"kAudioChannelLayoutTag_\" may be omitted)\n",
5858+ getprogname()
5959+ );
6060+ exit(1);
6161+}
6262+6363+6464+void Interleave(int nInputs, const char *infilenames[], const char *outfilename, const CAAudioChannelLayout *layout)
6565+{
6666+ const UInt32 kBufferSizeFrames = 0x8000;
6767+ const UInt32 kBufferSizeBytes = kBufferSizeFrames * sizeof(Float32);
6868+ class FileAndBuffer : public CAAudioFile {
6969+ public:
7070+ FileAndBuffer() : mBuf(NULL), mPtrs(NULL) { }
7171+ ~FileAndBuffer() { delete mBuf; delete mPtrs; }
7272+7373+ CABufferList * mBuf;
7474+ CABufferList * mPtrs;
7575+ };
7676+ FileAndBuffer *infiles = new FileAndBuffer[nInputs], *file;
7777+ FileAndBuffer outfile;
7878+ int i;
7979+ UInt32 outputChannels = 0;
8080+ double sampleRate = 0.;
8181+ UInt32 maxBitDepth = 0;
8282+ CAStreamBasicDescription clientFormat;
8383+ bool outFileCreated = false;
8484+8585+ try {
8686+ // set up input files
8787+ for (i = 0; i < nInputs; ++i) {
8888+ file = &infiles[i];
8989+ file->Open(infilenames[i]);
9090+ const CAStreamBasicDescription &fmt = file->GetFileDataFormat();
9191+ //fmt.PrintFormat(stdout, "", "input file");
9292+ XThrowIf(fmt.mFormatID != kAudioFormatLinearPCM, -1, "input files must be PCM");
9393+ outputChannels += fmt.mChannelsPerFrame;
9494+ if (sampleRate == 0.)
9595+ sampleRate = fmt.mSampleRate;
9696+ else
9797+ XThrowIf(fmt.mSampleRate != sampleRate, -1, "input files must have the same sample rate");
9898+ if (fmt.mBitsPerChannel > maxBitDepth)
9999+ maxBitDepth = fmt.mBitsPerChannel;
100100+ clientFormat.mSampleRate = sampleRate;
101101+ clientFormat.SetCanonical(fmt.mChannelsPerFrame, false); // deinterleaved
102102+ file->SetClientFormat(clientFormat, NULL);
103103+ file->mBuf = CABufferList::New("readbuf", clientFormat);
104104+ file->mBuf->AllocateBuffers(kBufferSizeBytes);
105105+ file->mPtrs = CABufferList::New("readptrs", clientFormat);
106106+ //clientFormat.PrintFormat(stdout, "", "input client");
107107+ }
108108+109109+ if (layout != NULL) {
110110+ if (AudioChannelLayoutTag_GetNumberOfChannels(layout->Tag()) != outputChannels) {
111111+ fprintf(stderr, "Channel layout tag '%s' is inappropriate for %lu channels of audio -- aborting\n",
112112+ CAChannelLayouts::ConstantToString(layout->Tag()), outputChannels);
113113+ exit(2);
114114+ }
115115+ }
116116+117117+ // prepare output file format
118118+ CAStreamBasicDescription outfmt;
119119+ outfmt.mSampleRate = sampleRate;
120120+ outfmt.mFormatID = kAudioFormatLinearPCM;
121121+ outfmt.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
122122+ outfmt.mBitsPerChannel = maxBitDepth;
123123+ outfmt.mChannelsPerFrame = outputChannels;
124124+ outfmt.mBytesPerPacket = outfmt.mBytesPerFrame = outputChannels * (maxBitDepth >> 3);
125125+ outfmt.mFramesPerPacket = 1;
126126+ //outfmt.PrintFormat(stdout, "", "output file");
127127+128128+ unlink(outfilename);
129129+ FSRef parentDir;
130130+ CFStringRef outName;
131131+ XThrowIfError(PosixPathToParentFSRefAndName(outfilename, parentDir, outName), "Couldn't locate output directory");
132132+ outfile.CreateNew(parentDir, outName, kAudioFileAIFFType, outfmt, layout ? &layout->Layout() : NULL);
133133+ outFileCreated = true;
134134+135135+ // create the output file and buffers
136136+ clientFormat.mSampleRate = sampleRate;
137137+ clientFormat.SetCanonical(outputChannels, false);
138138+ outfile.SetClientFormat(clientFormat, NULL);
139139+ //clientFormat.PrintFormat(stdout, "", "output client");
140140+141141+ outfile.mPtrs = CABufferList::New("writeptrs", clientFormat);
142142+143143+ AudioBufferList &writebufs = outfile.mPtrs->GetModifiableBufferList();
144144+ int outbuf = 0;
145145+ for (i = 0; i < nInputs; ++i) {
146146+ file = &infiles[i];
147147+ const CABufferList *bl = file->mBuf;
148148+ const AudioBufferList &readbufs = bl->GetBufferList();
149149+ memcpy(&writebufs.mBuffers[outbuf], &readbufs.mBuffers[0],
150150+ readbufs.mNumberBuffers * sizeof(AudioBuffer));
151151+ outbuf += readbufs.mNumberBuffers;
152152+ }
153153+154154+ while (true) {
155155+ UInt32 maxFramesRead = 0;
156156+ UInt32 nframes;
157157+ for (i = 0; i < nInputs; ++i) {
158158+ file = &infiles[i];
159159+ file->mPtrs->SetFrom(file->mBuf);
160160+ nframes = kBufferSizeFrames;
161161+ AudioBufferList &readbufs = file->mPtrs->GetModifiableBufferList();
162162+ file->Read(nframes, &readbufs);
163163+ //CAShowAudioBufferList(&readbufs, 8, 0);
164164+ if (nframes > maxFramesRead)
165165+ maxFramesRead = nframes;
166166+ if (nframes < kBufferSizeFrames)
167167+ file->mPtrs->PadWithZeroes(kBufferSizeBytes);
168168+ }
169169+ if (maxFramesRead == 0)
170170+ break;
171171+172172+ if (maxFramesRead < kBufferSizeFrames)
173173+ outfile.mPtrs->SetNumBytes(maxFramesRead * sizeof(Float32));
174174+ //CAShowAudioBufferList(&writebufs, 8, 0);
175175+ outfile.Write(maxFramesRead, &writebufs);
176176+ if (maxFramesRead < kBufferSizeFrames)
177177+ break;
178178+ }
179179+ }
180180+ catch (...) {
181181+ if (outFileCreated)
182182+ unlink(outfilename);
183183+ delete[] infiles;
184184+ throw;
185185+ }
186186+ outfile.Close();
187187+ // input files are closed from destructors
188188+ delete[] infiles;
189189+}
190190+191191+static void MissingArgument()
192192+{
193193+ fprintf(stderr, "missing argument\n\n");
194194+ usage();
195195+}
196196+197197+int main(int argc, const char *argv[])
198198+{
199199+ int nins = 0;
200200+ static const int MAX_INPUT_FILES = 32;
201201+ const char *infiles[MAX_INPUT_FILES];
202202+ const char *outfile = NULL;
203203+ UInt32 layoutTag = 0;
204204+205205+ for (int i = 1; i < argc; ++i) {
206206+ const char *arg = argv[i];
207207+ if (arg[0] != '-') {
208208+ if (nins >= MAX_INPUT_FILES) {
209209+ fprintf(stderr, "too many input files\n\n");
210210+ usage();
211211+ }
212212+ infiles[nins++] = arg;
213213+ } else {
214214+ arg += 1;
215215+ if (arg[0] == 'o') {
216216+ if (++i == argc) MissingArgument();
217217+ outfile = argv[i];
218218+ } else if (arg[0] == 'l' || !strcmp(arg, "-channellayout")) {
219219+ if (++i == argc) MissingArgument();
220220+ layoutTag = CAChannelLayouts::StringToConstant(argv[i]);
221221+ if (layoutTag == CAChannelLayouts::kInvalidTag) {
222222+ fprintf(stderr, "unknown channel layout tag: %s\n\n", argv[i]);
223223+ usage();
224224+ }
225225+ } else {
226226+ fprintf(stderr, "unknown argument: %s\n\n", arg - 1);
227227+ usage();
228228+ }
229229+ }
230230+ }
231231+232232+ if (nins < 2 || outfile == NULL)
233233+ usage();
234234+235235+ try {
236236+ if (layoutTag != 0) {
237237+ CAAudioChannelLayout layout = CAAudioChannelLayout(layoutTag);
238238+ Interleave(nins, infiles, outfile, &layout);
239239+ } else
240240+ Interleave(nins, infiles, outfile, NULL);
241241+ }
242242+ catch (CAXException &e) {
243243+ char buf[256];
244244+ fprintf(stderr, "Error: %s (%s)\n", e.mOperation, CAXException::FormatError(buf, e.mError));
245245+ return 1;
246246+ }
247247+ catch (...) {
248248+ fprintf(stderr, "An unknown error occurred\n");
249249+ return 1;
250250+ }
251251+ return 0;
252252+}
+193
src/CoreAudio/AudioFileTools/afplay.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ playaudiofile.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAChannelMappingPlayer.h"
4444+#include "CAXException.h"
4545+4646+#if TARGET_OS_MAC
4747+ #include <unistd.h>
4848+#else
4949+ #include <QTML.h>
5050+ #include "CAWindows.h"
5151+#endif
5252+5353+static void usage()
5454+{
5555+ fprintf(stderr,
5656+ "Usage:\n"
5757+ "%s [option...] audio_file\n\n"
5858+ "Options: (may appear before or after arguments)\n"
5959+ " {-a --all}\n"
6060+ " for files with >2 channels, play each pair of channels in succession\n"
6161+ " {-f --frame} FRAME\n"
6262+ " starting sample frame number\n"
6363+ " {-s --seconds} START_SECONDS END_SECONDS\n"
6464+ " segment of file to play, in seconds\n"
6565+#if !TARGET_OS_WIN32
6666+ , getprogname());
6767+#else
6868+ , "afplay");
6969+#endif
7070+ exit(1);
7171+}
7272+7373+static void Play(CAChannelMappingPlayer &player, SInt64 startFrame, SInt64 endFrame)
7474+{
7575+ CAAudioFile &file = player.GetFile();
7676+ if (startFrame < 0) {
7777+ startFrame = 0;
7878+ }
7979+ if (endFrame <= 0) {
8080+ SInt64 numFrames = SInt64(file.GetNumberFrames() * file.GetClientDataFormat().mSampleRate / file.GetFileDataFormat().mSampleRate);
8181+ endFrame = numFrames;
8282+ }
8383+ player.Start();
8484+ while (true) {
8585+ SInt64 pos = player.GetCurrentFrame();
8686+ //file.Tell();
8787+ if (pos >= endFrame)
8888+ break;
8989+ usleep(250000); // 250 ms
9090+ }
9191+ player.Stop();
9292+}
9393+9494+void MissingArgument()
9595+{
9696+ fprintf(stderr, "Missing argument\n");
9797+ usage();
9898+}
9999+100100+int main(int argc, const char *argv[])
101101+{
102102+ const char *fileToPlay = NULL;
103103+ bool playallpairs = false;
104104+ double startSeconds = -1, endSeconds = -1;
105105+ SInt64 startFrame = 0, endFrame = 0;
106106+107107+ #if TARGET_OS_WIN32
108108+ InitializeQTML(0L);
109109+ #endif
110110+111111+ for (int i = 1; i < argc; ++i) {
112112+ const char *arg = argv[i];
113113+ if (arg[0] != '-') {
114114+ if (fileToPlay != NULL) {
115115+ fprintf(stderr, "may only specify one file to play\n");
116116+ usage();
117117+ }
118118+ fileToPlay = arg;
119119+ } else {
120120+ arg += 1;
121121+ if (arg[0] == 'a' || !strcmp(arg, "-all"))
122122+ playallpairs = true;
123123+ else if (arg[0] == 'f' || !strcmp(arg, "-frame")) {
124124+ if (++i == argc)
125125+ MissingArgument();
126126+ arg = argv[i];
127127+ sscanf(arg, "%qd", &startFrame);
128128+ } else if (arg[0] == 's' || !strcmp(arg, "-seconds")) {
129129+ if (++i == argc)
130130+ MissingArgument();
131131+ arg = argv[i];
132132+ sscanf(arg, "%lf", &startSeconds);
133133+ if (i + 1 < argc && argv[i+1][0] != '-') {
134134+ arg = argv[++i];
135135+ sscanf(arg, "%lf", &endSeconds);
136136+ }
137137+ } else {
138138+ fprintf(stderr, "unknown argument: %s\n\n", arg - 1);
139139+ usage();
140140+ }
141141+ }
142142+ }
143143+144144+ if (fileToPlay == NULL)
145145+ usage();
146146+147147+ try {
148148+ const int kNumberBuffers = 3;
149149+ const unsigned kBufferSize = 0x1000;
150150+ FSRef playFSRef;
151151+ XThrowIfError(FSPathMakeRef((UInt8 *)fileToPlay, &playFSRef, NULL), "Input file not found");
152152+ CAChannelMappingPlayer player(kNumberBuffers, kBufferSize);
153153+ player.SetFile(playFSRef);
154154+ CAAudioFile &file = player.GetFile();
155155+ CAChannelMapper *mapper = player.GetMapper();
156156+ if (playallpairs && mapper == NULL)
157157+ playallpairs = false;
158158+159159+ if (startSeconds >= 0) {
160160+ Float64 sr = file.GetClientDataFormat().mSampleRate;
161161+ startFrame = SInt64(startSeconds * sr);
162162+ if (endSeconds > startSeconds)
163163+ endFrame = SInt64(endSeconds * sr);
164164+ printf("secs: %.1f-%.1f frames: %qd-%qd\n", startSeconds, endSeconds, startFrame, endFrame);
165165+ }
166166+167167+ if (playallpairs) {
168168+ int nChannelsInFile = file.GetFileDataFormat().NumberChannels();
169169+ for (int channel = 0; channel < nChannelsInFile && playallpairs; channel += 2) {
170170+ printf("channels %d-%d of %d\n", channel, channel+1, nChannelsInFile);
171171+ mapper->ResetMixer();
172172+ mapper->ConnectChannelToChannel(channel, 0);
173173+ mapper->ConnectChannelToChannel(channel+1, 1);
174174+ player.SetCurrentPosition(0.);
175175+ Play(player, startFrame, endFrame);
176176+ }
177177+ } else {
178178+ file.Seek(startFrame);
179179+ Play(player, startFrame, endFrame);
180180+ }
181181+ }
182182+ catch (CAXException &e) {
183183+ char buf[256];
184184+ fprintf(stderr, "Error: %s (%s)\n", e.mOperation, CAXException::FormatError(buf, sizeof(buf), e.mError));
185185+ return 1;
186186+ }
187187+ catch (...) {
188188+ fprintf(stderr, "An unknown error occurred\n");
189189+ return 1;
190190+ }
191191+ return 0;
192192+}
193193+
+225
src/CoreAudio/AudioFileTools/afrecord.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ afrecord.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAAudioFileRecorder.h"
4444+#include "CAXException.h"
4545+#include <unistd.h>
4646+#include "AFToolsCommon.h"
4747+#include "CAFilePathUtils.h"
4848+#include "CAAudioFileFormats.h"
4949+5050+static void usage()
5151+{
5252+ fprintf(stderr,
5353+ "Usage:\n"
5454+ "%s [option...] audio_file\n\n"
5555+ "Options: (may appear before or after arguments)\n"
5656+ " { -f | --file } file_format:\n"
5757+ , getprogname());
5858+ PrintAudioFileTypesAndFormats(stderr);
5959+ fprintf(stderr,
6060+ " { -d | --data } data_format[@sample_rate_hz]:\n"
6161+ " [-][BE|LE]{F|[U]I}{8|16|24|32|64} (PCM)\n"
6262+ " e.g. -BEI16 -F32@44100\n"
6363+ " or a data format appropriate to file format, as above\n"
6464+ " { -c | --channels } number_of_channels\n"
6565+ " add/remove channels without regard to order\n"
6666+ " { -l | --channellayout } layout_tag\n"
6767+ " layout_tag: name of a constant from CoreAudioTypes.h\n"
6868+ " (prefix \"kAudioChannelLayoutTag_\" may be omitted)\n"
6969+ " if specified once, applies to output file; if twice, the first\n"
7070+ " applies to the input file, the second to the output file\n"
7171+ " { -b | --bitrate } bit_rate_bps\n"
7272+ " e.g. 128000\n"
7373+ " { -q | --quality } quality\n"
7474+ " quality: 0-127\n"
7575+ " { -v | --verbose }\n"
7676+ " print progress verbosely\n"
7777+ " { -p | --profile }\n"
7878+ " collect and print performance profile\n"
7979+ );
8080+ exit(1);
8181+}
8282+8383+static void MissingArgument()
8484+{
8585+ fprintf(stderr, "missing argument\n\n");
8686+ usage();
8787+}
8888+8989+static OSType Parse4CharCode(const char *arg, const char *name)
9090+{
9191+ OSType t;
9292+ StrToOSType(arg, t);
9393+ if (t == 0) {
9494+ fprintf(stderr, "invalid 4-char-code argument for %s: '%s'\n\n", name, arg);
9595+ usage();
9696+ }
9797+ return t;
9898+}
9999+100100+static int ParseInt(const char *arg, const char *name)
101101+{
102102+ int x;
103103+ if (sscanf(arg, "%d", &x) != 1) {
104104+ fprintf(stderr, "invalid integer argument for %s: '%s'\n\n", name, arg);
105105+ usage();
106106+ }
107107+ return x;
108108+}
109109+110110+static void Record(CAAudioFileRecorder &recorder)
111111+{
112112+ recorder.Start();
113113+ printf("Recording, press any key to stop:");
114114+ fflush(stdout);
115115+ getchar();
116116+ //sleep(10);
117117+ recorder.Stop();
118118+}
119119+120120+int main(int argc, const char *argv[])
121121+{
122122+ const char *recordFileName = NULL;
123123+124124+ // set up defaults
125125+ AudioFileTypeID filetype = kAudioFileAIFFType;
126126+127127+ bool gotOutDataFormat = false;
128128+ CAStreamBasicDescription dataFormat;
129129+ dataFormat.mSampleRate = 44100.; // later get this from the hardware
130130+ dataFormat.mFormatID = kAudioFormatLinearPCM;
131131+ dataFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
132132+ dataFormat.mFramesPerPacket = 1;
133133+ dataFormat.mChannelsPerFrame = 2;
134134+ dataFormat.mBitsPerChannel = 16;
135135+ dataFormat.mBytesPerPacket = dataFormat.mBytesPerFrame = 4;
136136+137137+ SInt32 bitrate = -1, quality = -1;
138138+139139+ // parse arguments
140140+ for (int i = 1; i < argc; ++i) {
141141+ const char *arg = argv[i];
142142+ if (arg[0] != '-') {
143143+ if (recordFileName != NULL) {
144144+ fprintf(stderr, "may only specify one record file\n");
145145+ usage();
146146+ }
147147+ recordFileName = arg;
148148+ } else {
149149+ arg += 1;
150150+ if (arg[0] == 'f' || !strcmp(arg, "-file")) {
151151+ if (++i == argc) MissingArgument();
152152+ filetype = Parse4CharCode(argv[i], "-f | --file");
153153+ } else if (arg[0] == 'd' || !strcmp(arg, "-data")) {
154154+ if (++i == argc) MissingArgument();
155155+ if (!ParseStreamDescription(argv[i], dataFormat))
156156+ usage();
157157+ gotOutDataFormat = true;
158158+ } else if (arg[0] == 'b' || !strcmp(arg, "-bitrate")) {
159159+ if (++i == argc) MissingArgument();
160160+ bitrate = ParseInt(argv[i], "-b | --bitrate");
161161+ } else if (arg[0] == 'q' || !strcmp(arg, "-quality")) {
162162+ if (++i == argc) MissingArgument();
163163+ quality = ParseInt(argv[i], "-q | --quality");
164164+ } else {
165165+ fprintf(stderr, "unknown argument: %s\n\n", arg - 1);
166166+ usage();
167167+ }
168168+ }
169169+ }
170170+171171+ if (recordFileName == NULL)
172172+ usage();
173173+174174+ if (!gotOutDataFormat) {
175175+ if (filetype == 0) {
176176+ fprintf(stderr, "no output file or data format specified\n\n");
177177+ usage();
178178+ }
179179+ if (!CAAudioFileFormats::Instance()->InferDataFormatFromFileFormat(filetype, dataFormat)) {
180180+ fprintf(stderr, "Couldn't infer data format from file format\n\n");
181181+ usage();
182182+ }
183183+ } else if (filetype == 0) {
184184+ if (!CAAudioFileFormats::Instance()->InferFileFormatFromDataFormat(dataFormat, filetype)) {
185185+ dataFormat.PrintFormat(stderr, "", "Couldn't infer file format from data format");
186186+ usage();
187187+ }
188188+ }
189189+190190+ unlink(recordFileName);
191191+192192+ if (dataFormat.IsPCM())
193193+ dataFormat.ChangeNumberChannels(2, true);
194194+ else
195195+ dataFormat.mChannelsPerFrame = 2;
196196+197197+ try {
198198+ const int kNumberBuffers = 3;
199199+ const unsigned kBufferSize = 0x8000;
200200+ CAAudioFileRecorder recorder(kNumberBuffers, kBufferSize);
201201+ FSRef parentDir;
202202+ CFStringRef filename;
203203+ XThrowIfError(PosixPathToParentFSRefAndName(recordFileName, parentDir, filename), "couldn't find output directory");
204204+ recorder.SetFile(parentDir, filename, filetype, dataFormat, NULL);
205205+206206+ CAAudioFile &recfile = recorder.GetFile();
207207+ if (bitrate >= 0)
208208+ recfile.SetConverterProperty(kAudioConverterEncodeBitRate, sizeof(UInt32), &bitrate);
209209+ if (quality >= 0)
210210+ recfile.SetConverterProperty(kAudioConverterCodecQuality, sizeof(UInt32), &quality);
211211+212212+ Record(recorder);
213213+ }
214214+ catch (CAXException &e) {
215215+ char buf[256];
216216+ fprintf(stderr, "Error: %s (%s)\n", e.mOperation, CAXException::FormatError(buf, sizeof(buf), e.mError));
217217+ return 1;
218218+ }
219219+ catch (...) {
220220+ fprintf(stderr, "An unknown error occurred\n");
221221+ return 1;
222222+ }
223223+ return 0;
224224+}
225225+
+154
src/CoreAudio/AudioFileTools/audioformats.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ audioformats.cpp
4040+4141+=============================================================================*/
4242+4343+#include "CAAudioFileFormats.h"
4444+#include <stdlib.h>
4545+#include "AFToolsCommon.h"
4646+4747+#if TARGET_OS_WIN32
4848+ #include <QTML.h>
4949+#endif
5050+5151+// This program interrogates the AudioFile and AudioFormat API's for information
5252+// useful in constructing test scripts. It might also be useful as an example
5353+// of how to use these API's.
5454+5555+void PrintFileFormats()
5656+{
5757+ CAAudioFileFormats *fileFormats = CAAudioFileFormats::Instance();
5858+5959+ for (int i = 0; i < fileFormats->mNumFileFormats; ++i) {
6060+ CAAudioFileFormats::FileFormatInfo *ffi = &fileFormats->mFileFormats[i];
6161+ char buf[20], extbuf[32];
6262+ printf("('%s', '%s'", OSTypeToStr(buf, ffi->mFileTypeID), ffi->GetExtension(0, extbuf, sizeof(extbuf)));
6363+6464+ for (int j = 0; j < ffi->mNumDataFormats; ++j) {
6565+ CAAudioFileFormats::DataFormatInfo *dfi = &ffi->mDataFormats[j];
6666+ if (dfi->mFormatID == kAudioFormatLinearPCM) {
6767+ for (int k = 0; k < dfi->mNumVariants; ++k) {
6868+ AudioStreamBasicDescription *asbd = &dfi->mVariants[k];
6969+ if (asbd->mFormatFlags & ~(kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsFloat))
7070+ printf("(%08lx/%ld) ", asbd->mFormatFlags, asbd->mBitsPerChannel);
7171+ else {
7272+ printf(", '%s",
7373+ (asbd->mFormatFlags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE");
7474+ if (asbd->mFormatFlags & kAudioFormatFlagIsFloat)
7575+ printf("F");
7676+ else
7777+ printf("%sI",
7878+ (asbd->mFormatFlags & kAudioFormatFlagIsSignedInteger) ? "" : "U");
7979+ printf("%ld'", asbd->mBitsPerChannel);
8080+ }
8181+ }
8282+ } else {
8383+ printf(", '%s'", OSTypeToStr(buf, dfi->mFormatID));
8484+ }
8585+ }
8686+ printf("),\n");
8787+ }
8888+}
8989+9090+struct LayoutTag {
9191+ UInt32 constant;
9292+ const char *name;
9393+};
9494+9595+#define TAG(x) { x, #x },
9696+9797+static LayoutTag gLayoutTags[] = {
9898+ TAG(kAudioChannelLayoutTag_Stereo)
9999+ TAG(kAudioChannelLayoutTag_AAC_Quadraphonic)
100100+ TAG(kAudioChannelLayoutTag_AAC_4_0)
101101+ TAG(kAudioChannelLayoutTag_AAC_5_0)
102102+ TAG(kAudioChannelLayoutTag_AAC_5_1)
103103+ TAG(kAudioChannelLayoutTag_AAC_6_0)
104104+ TAG(kAudioChannelLayoutTag_AAC_6_1)
105105+ TAG(kAudioChannelLayoutTag_AAC_7_0)
106106+ TAG(kAudioChannelLayoutTag_AAC_7_1)
107107+ TAG(kAudioChannelLayoutTag_AAC_Octagonal)
108108+ TAG(kAudioChannelLayoutTag_MPEG_5_0_A)
109109+ TAG(kAudioChannelLayoutTag_MPEG_5_0_B)
110110+ TAG(kAudioChannelLayoutTag_MPEG_5_1_A)
111111+ TAG(kAudioChannelLayoutTag_MPEG_5_1_B)
112112+ { 0, NULL } // sentinel
113113+};
114114+115115+static const char *prefix = "kAudioChannelLayoutTag_";
116116+117117+void PrintCompatibleChannelLayouts()
118118+{
119119+ int plen = strlen(prefix);
120120+ for (LayoutTag *tag1 = gLayoutTags; tag1->name != NULL; ++tag1) {
121121+ AudioChannelLayout layout1 = { tag1->constant, 0, 0 };
122122+ printf("\t'%s' : (", tag1->name + plen);
123123+ int printed = 0;
124124+ for (LayoutTag *tag2 = gLayoutTags; tag2->name != NULL; ++tag2) {
125125+ AudioChannelLayout layout2 = { tag2->constant, 0, 0 };
126126+ AudioChannelLayout *layouts[] = { &layout1, &layout2 };
127127+128128+ UInt32 propertySize;
129129+ OSStatus err = AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelMap, sizeof(layouts), layouts, &propertySize);
130130+ if (err == noErr) {
131131+ SInt32 *map = (SInt32 *)malloc(propertySize);
132132+ err = AudioFormatGetProperty(kAudioFormatProperty_ChannelMap, sizeof(layouts), layouts, &propertySize, map);
133133+ if (err == noErr) {
134134+ if (printed++) printf(", ");
135135+ printf("'%s'", tag2->name + plen);
136136+ }
137137+ }
138138+ }
139139+ printf("),\n");
140140+ }
141141+}
142142+143143+int main(int argc, const char *argv[])
144144+{
145145+ #if TARGET_OS_WIN32
146146+ InitializeQTML(0L);
147147+ #endif
148148+149149+ PrintFileFormats();
150150+ printf("#######################\n");
151151+ PrintCompatibleChannelLayouts();
152152+153153+ return 0;
154154+}
+678
src/CoreAudio/AudioFileTools/auprocess.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ main.cpp
4040+4141+=============================================================================*/
4242+4343+/*
4444+ auprocess
4545+ - takes a source audio file, an AU and generates a processed file
4646+*/
4747+4848+#include "CAAUProcessor.h"
4949+#include "CAAudioFile.h"
5050+#include "CAXException.h"
5151+#include "CAHostTimeBase.h"
5252+#include "CAFilePathUtils.h"
5353+#include "CAAudioFileFormats.h"
5454+5555+#if TARGET_OS_MAC
5656+ #include <pthread.h>
5757+ #include <mach/mach.h>
5858+#endif
5959+6060+#define require_noerr ca_require_noerr
6161+6262+#define CA_AU_PROFILE_TIME 1
6363+6464+#if CA_AU_PROFILE_TIME
6565+ UInt64 sReadTime = 0;
6666+ UInt64 sRenderTime = 0;
6767+#endif
6868+6969+#pragma mark __print helpers
7070+7171+void PRINT_MARKS ()
7272+{
7373+ printf ("| ");
7474+ for (int i = 0; i < 48; ++i)
7575+ printf (" ");
7676+ printf ("|\n");
7777+}
7878+7979+void PerfResult(const char *toolname, int group, const char *testname, double value, const char *units, const char *fmt="%.3f")
8080+{
8181+ printf("<result tool='%s' group='%d' test='%s' value='", toolname, group, testname);
8282+ printf(fmt, value);
8383+ printf("' units='%s' />\n", units);
8484+}
8585+8686+static int lastProgressPrintDone = -1;
8787+void PRINT_PROGRESS (Float32 inPercent)
8888+{
8989+ int current = int(inPercent / 4.0);
9090+ for (int i = lastProgressPrintDone; i < current; ++i)
9191+ printf ("* ");
9292+ lastProgressPrintDone = current;
9393+}
9494+9595+#pragma mark __Inpput Callback Definitions
9696+9797+static AURenderCallbackStruct sInputCallback; // we set one of these two callbacks based on AU type
9898+9999+static OSStatus InputCallback (void *inRefCon,
100100+ AudioUnitRenderActionFlags *ioActionFlags,
101101+ const AudioTimeStamp *inTimeStamp,
102102+ UInt32 inBusNumber,
103103+ UInt32 inNumberFrames,
104104+ AudioBufferList *ioData)
105105+{
106106+ #if CA_AU_PROFILE_TIME
107107+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
108108+ #endif
109109+110110+ CAAudioFile &readFile = *(static_cast<CAAudioFile*>(inRefCon));
111111+112112+#if !CAAF_USE_EXTAUDIOFILE
113113+ if (SInt64(inTimeStamp->mSampleTime) > readFile.GetNumberPackets()) {
114114+#else
115115+ if (SInt64(inTimeStamp->mSampleTime) > readFile.GetNumberFrames()) {
116116+#endif
117117+#if DEBUG
118118+ printf ("reading past end of input\n");
119119+#endif
120120+ return -1;
121121+ }
122122+123123+ readFile.Seek (SInt64(inTimeStamp->mSampleTime));
124124+ readFile.Read (inNumberFrames, ioData);
125125+126126+ #if CA_AU_PROFILE_TIME
127127+ sReadTime += (CAHostTimeBase::GetTheCurrentTime() - now);
128128+ #endif
129129+130130+ return noErr;
131131+}
132132+133133+static OSStatus FConvInputCallback (void *inRefCon,
134134+ AudioUnitRenderActionFlags *ioActionFlags,
135135+ const AudioTimeStamp *inTimeStamp,
136136+ UInt32 inBusNumber,
137137+ UInt32 inNumberFrames,
138138+ AudioBufferList *ioData)
139139+{
140140+ #if CA_AU_PROFILE_TIME
141141+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
142142+ #endif
143143+144144+ CAAudioFile &readFile = *(static_cast<CAAudioFile*>(inRefCon));
145145+146146+ // this test is ONLY needed in case of processing with a Format Converter type of AU
147147+ // in all other cases, the CAAUProcessor class will NEVER call you for input
148148+ // beyond the end of the file....
149149+150150+#if !CAAF_USE_EXTAUDIOFILE
151151+ if (SInt64(inTimeStamp->mSampleTime) >= readFile.GetNumberPackets()) {
152152+#else
153153+ if (SInt64(inTimeStamp->mSampleTime) >= readFile.GetNumberFrames()) {
154154+#endif
155155+ return -1;
156156+ }
157157+158158+ readFile.Seek (SInt64(inTimeStamp->mSampleTime));
159159+ UInt32 readPackets = inNumberFrames;
160160+161161+ // also, have to do this for a format converter AU - otherwise we'd just read what we're told
162162+#if !CAAF_USE_EXTAUDIOFILE
163163+ if (SInt64(inTimeStamp->mSampleTime + inNumberFrames) > readFile.GetNumberPackets()) {
164164+#else
165165+ if (SInt64(inTimeStamp->mSampleTime + inNumberFrames) > readFile.GetNumberFrames()) {
166166+#endif
167167+ // first set this to zero as we're only going to read a partial number of frames
168168+ AudioBuffer *buf = ioData->mBuffers;
169169+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
170170+ memset((Byte *)buf->mData, 0, buf->mDataByteSize);
171171+#if !CAAF_USE_EXTAUDIOFILE
172172+ readPackets = UInt32 (readFile.GetNumberPackets() - SInt64(inTimeStamp->mSampleTime));
173173+#else
174174+ readPackets = UInt32 (readFile.GetNumberFrames() - SInt64(inTimeStamp->mSampleTime));
175175+#endif
176176+ }
177177+178178+ readFile.Read (readPackets, ioData);
179179+180180+ #if CA_AU_PROFILE_TIME
181181+ sReadTime += (CAHostTimeBase::GetTheCurrentTime() - now);
182182+ #endif
183183+184184+ return noErr;
185185+}
186186+187187+struct ReadBuffer {
188188+ AUOutputBL *readData;
189189+ UInt32 readFrames;
190190+};
191191+192192+static OSStatus MemoryInputCallback (void *inRefCon,
193193+ AudioUnitRenderActionFlags *ioActionFlags,
194194+ const AudioTimeStamp *inTimeStamp,
195195+ UInt32 inBusNumber,
196196+ UInt32 inNumberFrames,
197197+ AudioBufferList *ioData)
198198+{
199199+ #if CA_AU_PROFILE_TIME
200200+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
201201+ #endif
202202+203203+ ReadBuffer *readBuffer = (ReadBuffer*)inRefCon;
204204+205205+ if (((readBuffer->readFrames + inNumberFrames) * sizeof(Float32)) > (readBuffer->readData->ABL()->mBuffers[0].mDataByteSize))
206206+ {
207207+ // going past read size
208208+ AudioBuffer *buf = ioData->mBuffers;
209209+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
210210+ memset((Byte *)buf->mData, 0, buf->mDataByteSize);
211211+ }
212212+ else
213213+ {
214214+ AudioBuffer *buf = ioData->mBuffers;
215215+ AudioBuffer *rBuf = readBuffer->readData->ABL()->mBuffers;
216216+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf, ++rBuf) {
217217+ AudioBuffer readB = *rBuf;
218218+ readB.mData = static_cast<Float32*>(rBuf->mData) + readBuffer->readFrames;
219219+ memcpy (buf->mData, readB.mData, buf->mDataByteSize);
220220+ }
221221+ readBuffer->readFrames += inNumberFrames;
222222+ }
223223+224224+ #if CA_AU_PROFILE_TIME
225225+ sReadTime += (CAHostTimeBase::GetTheCurrentTime() - now);
226226+ #endif
227227+228228+ return noErr;
229229+}
230230+231231+#pragma mark __Utility Helpers
232232+233233+CFPropertyListRef ReadPresetFromPresetFile (char* filePath)
234234+{
235235+ if (!filePath)
236236+ return NULL;
237237+238238+ FSRef ref;
239239+ if (FSPathMakeRef((UInt8 *)filePath, &ref, NULL))
240240+ return NULL;
241241+242242+ CFDataRef resourceData = NULL;
243243+ CFPropertyListRef theData = NULL;
244244+ CFStringRef errString = NULL;
245245+ CFURLRef fileURL = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref);
246246+ if (fileURL == NULL) {
247247+ goto home;
248248+ }
249249+250250+ SInt32 result;
251251+252252+ // Read the XML file.
253253+ Boolean status; status = CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, fileURL,
254254+ &resourceData, // place to put file data
255255+ NULL, NULL, &result);
256256+ if (status == false || result) {
257257+ goto home;
258258+ }
259259+260260+ theData = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, resourceData,
261261+ kCFPropertyListImmutable, &errString);
262262+ if (theData == NULL || errString) {
263263+ if (theData)
264264+ CFRelease (theData);
265265+ theData = NULL;
266266+ goto home;
267267+ }
268268+269269+home:
270270+ if (fileURL)
271271+ CFRelease (fileURL);
272272+ if (resourceData)
273273+ CFRelease (resourceData);
274274+ if (errString)
275275+ CFRelease (errString);
276276+277277+ return theData;
278278+}
279279+280280+#pragma mark __the setup code
281281+282282+#define OFFLINE_AU_CMD "[-au TYPE SUBTYPE MANU] The Audio Unit component description\n\t"
283283+#define INPUT_FILE "[-i /Path/To/File] The file that is to be processed.\n\t"
284284+#define OUTPUT_FILE "[-o /Path/To/File/To/Create] This will be in the same format as the input file\n\t"
285285+#define AU_PRESET_CMD "[-p /Path/To/AUPreset/File] Specify an AU Preset File to establish the state of the AU\n\t"
286286+#define SHORT_MEM_CMD "[-m] Just reads and processes the first half second of the input file\n\t"
287287+#define USE_MAX_FRAMES "[-f max_frames] default is 32768 (512 for aufc units)"
288288+289289+static char* usageStr = "Usage: auprocess\n\t"
290290+ OFFLINE_AU_CMD
291291+ INPUT_FILE
292292+ OUTPUT_FILE
293293+ AU_PRESET_CMD
294294+ SHORT_MEM_CMD
295295+ USE_MAX_FRAMES;
296296+297297+int main(int argc, const char * argv[])
298298+{
299299+ setbuf (stdout, NULL);
300300+301301+302302+#if TARGET_OS_MAC
303303+ {
304304+ thread_extended_policy_data_t theFixedPolicy;
305305+ theFixedPolicy.timeshare = false; // set to true for a non-fixed thread
306306+ thread_policy_set(pthread_mach_thread_np(pthread_self()),
307307+ THREAD_EXTENDED_POLICY,
308308+ (thread_policy_t)&theFixedPolicy,
309309+ THREAD_EXTENDED_POLICY_COUNT);
310310+311311+ // We keep a reference to the spawning thread's priority around (initialized in the constructor),
312312+ // and set the importance of the child thread relative to the spawning thread's priority.
313313+ thread_precedence_policy_data_t thePrecedencePolicy;
314314+315315+ thePrecedencePolicy.importance = 63 - 36;
316316+ thread_policy_set(pthread_mach_thread_np(pthread_self()),
317317+ THREAD_PRECEDENCE_POLICY,
318318+ (thread_policy_t)&thePrecedencePolicy,
319319+ THREAD_PRECEDENCE_POLICY_COUNT);
320320+ }
321321+#endif
322322+323323+324324+// These are the variables that are set up from the input parsing
325325+ char* srcFilePath = NULL;
326326+ char* destFilePath = NULL;
327327+ char* auPresetFile = NULL;
328328+ bool shortMemoryProfile = false;
329329+ OSType manu, subType, type = 0;
330330+ int userSetFrames = -1;
331331+332332+ for (int i = 1; i < argc; ++i)
333333+ {
334334+ if (strcmp (argv[i], "-au") == 0) {
335335+ if ( (i + 3) < argc ) {
336336+ StrToOSType (argv[i + 1], type);
337337+ StrToOSType (argv[i + 2], subType);
338338+ StrToOSType (argv[i + 3], manu);
339339+ i += 3;
340340+ } else {
341341+ printf ("Which Audio Unit:\n%s", usageStr);
342342+ exit(1);
343343+ }
344344+ }
345345+ else if (strcmp (argv[i], "-i") == 0) {
346346+ srcFilePath = const_cast<char*>(argv[++i]);
347347+ }
348348+ else if (strcmp (argv[i], "-o") == 0) {
349349+ destFilePath = const_cast<char*>(argv[++i]);
350350+ }
351351+ else if (strcmp (argv[i], "-p") == 0) {
352352+ auPresetFile = const_cast<char*>(argv[++i]);
353353+ }
354354+ else if (strcmp (argv[i], "-m") == 0) {
355355+ shortMemoryProfile = true;
356356+ }
357357+ else if (strcmp (argv[i], "-f") == 0) {
358358+ sscanf(argv[++i], "%d", &userSetFrames);
359359+ }
360360+ else {
361361+ printf ("%s\n", usageStr);
362362+ exit(1);
363363+ }
364364+ }
365365+366366+ if (!type || !srcFilePath) {
367367+ printf ("%s\n", usageStr);
368368+ exit(1);
369369+ }
370370+ if (!destFilePath) {
371371+ if (!shortMemoryProfile) {
372372+ printf ("%s\n", usageStr);
373373+ exit(1);
374374+ }
375375+ }
376376+ // delete pre-existing output file
377377+ if (!shortMemoryProfile) {
378378+ FSRef destFSRef;
379379+ if (FSPathMakeRef((UInt8 *)destFilePath, &destFSRef, NULL) == noErr) {
380380+ // output file exists - delete it
381381+ if (FSDeleteObject(&destFSRef)) {
382382+ printf ("Cannot Delete Output File\n");
383383+ exit(1);
384384+ }
385385+ }
386386+ }
387387+388388+ CAComponentDescription desc(type, subType, manu);
389389+390390+ CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile);
391391+392392+ // the num of frames to use when processing the file with the Render call
393393+ UInt32 maxFramesToUse = shortMemoryProfile ? 512 : 32768;
394394+395395+ // not set from command line
396396+ if (userSetFrames > 0) {
397397+ maxFramesToUse = userSetFrames;
398398+ }
399399+400400+ // in some settings (for instance a delay with 100% feedback) tail time is essentially infinite
401401+ // so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through
402402+ // if you want to bypass this completely, just set this to zero.
403403+ Float64 maxTailTimeSecs = 10.;
404404+405405+#pragma mark -
406406+#pragma mark __ The driving code
407407+#pragma mark -
408408+409409+ try
410410+ {
411411+ CAComponent comp(desc);
412412+413413+ // CAAUProcessor's constructor throws... so make sure the component is valid
414414+ if (comp.IsValid() == false) {
415415+ printf ("Can't Find Component\n");
416416+ desc.Print();
417417+ exit(1);
418418+ }
419419+420420+ CAAUProcessor processor(comp);
421421+ processor.AU().Print();
422422+423423+ CAAudioFile srcFile;
424424+ CAAudioFile destFile;
425425+426426+ srcFile.Open(srcFilePath);
427427+428428+ CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat());
429429+ procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false);
430430+431431+ printf ("Processing Format:\n\t");
432432+ procFormat.Print();
433433+434434+435435+ if (!shortMemoryProfile) {
436436+ FSRef parentDir;
437437+ CFStringRef filename;
438438+ PosixPathToParentFSRefAndName(destFilePath, parentDir, filename);
439439+ destFile.CreateNew (parentDir, filename, 'AIFF', srcFile.GetFileDataFormat());
440440+ destFile.SetClientFormat (procFormat);
441441+ }
442442+443443+ srcFile.SetClientFormat (procFormat);
444444+445445+ AUOutputBL outputList(procFormat);
446446+447447+ ReadBuffer* readBuf = NULL;
448448+449449+#if !CAAF_USE_EXTAUDIOFILE
450450+ UInt64 numInputSamples = srcFile.GetNumberPackets();
451451+#else
452452+ UInt64 numInputSamples = srcFile.GetNumberFrames();
453453+#endif
454454+455455+ if (shortMemoryProfile) {
456456+ readBuf = new ReadBuffer;
457457+ readBuf->readData = new AUOutputBL(procFormat);
458458+ readBuf->readFrames = 0;
459459+ UInt32 numFrames = UInt32(procFormat.mSampleRate / 2);
460460+ readBuf->readData->Allocate (numFrames); // half a second of audio data
461461+ readBuf->readData->Prepare(); // half a second of audio data
462462+463463+ // read 1/2 second of audio into this read buffer
464464+ srcFile.Read (numFrames, readBuf->readData->ABL());
465465+466466+ sInputCallback.inputProc = MemoryInputCallback;
467467+ sInputCallback.inputProcRefCon = readBuf;
468468+ numInputSamples = numFrames;
469469+ }
470470+ else {
471471+ if (desc.IsFConv()) {
472472+ maxFramesToUse = userSetFrames == -1 ? 512 : maxFramesToUse;
473473+ // some format converter's can call you several times in small granularities
474474+ // so you can't use a large buffer to render or you won't return all of the input data
475475+ // this also lessens the final difference between what you should get and what you do
476476+ // converter units *really* should have a version that are offline AU's to
477477+ // handle this for you.
478478+ sInputCallback.inputProc = FConvInputCallback;
479479+ } else
480480+ sInputCallback.inputProc = InputCallback;
481481+482482+ sInputCallback.inputProcRefCon = &srcFile;
483483+ }
484484+485485+ OSStatus result;
486486+ require_noerr (result = processor.EstablishInputCallback (sInputCallback), home);
487487+ require_noerr (result = processor.SetMaxFramesPerRender (maxFramesToUse), home);
488488+ processor.SetMaxTailTime (maxTailTimeSecs);
489489+ require_noerr (result = processor.Initialize (procFormat, numInputSamples), home);
490490+ if (presetDict) {
491491+ require_noerr (result = processor.SetAUPreset (presetDict), home);
492492+ CFRelease (presetDict);
493493+ }
494494+ // this does ALL of the preflighting.. could be specialise for an OfflineAU type
495495+ // to do this piecemeal and do a progress bar by using the OfflineAUPreflight method
496496+ require_noerr (result = processor.Preflight (), home);
497497+498498+ bool isDone; isDone = false;
499499+ bool needsPostProcessing;
500500+ bool isSilence;
501501+ UInt32 numFrames; numFrames = processor.MaxFramesPerRender();
502502+503503+#if CA_AU_PROFILE_TIME
504504+ sReadTime = 0;
505505+ sRenderTime = 0;
506506+#endif
507507+508508+PRINT_MARKS();
509509+ // this is the render loop
510510+ while (!isDone)
511511+ {
512512+ #if CA_AU_PROFILE_TIME
513513+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
514514+ #endif
515515+ outputList.Prepare(); // have to do this every time...
516516+ require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone,
517517+ &needsPostProcessing), home);
518518+ #if CA_AU_PROFILE_TIME
519519+ sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now);
520520+ #endif
521521+522522+if (!shortMemoryProfile)
523523+ PRINT_PROGRESS(processor.GetOLPercentComplete());
524524+else
525525+ PRINT_PROGRESS(((processor.SampleTime() / numInputSamples) * 100.));
526526+527527+ if (numFrames && !shortMemoryProfile)
528528+ destFile.Write (numFrames, outputList.ABL());
529529+ }
530530+531531+ // this is the postprocessing if needed
532532+ if (!shortMemoryProfile && needsPostProcessing)
533533+ {
534534+ isDone = false;
535535+ numFrames = processor.MaxFramesPerRender();
536536+ while (!isDone) {
537537+ outputList.Prepare(); // have to do this every time...
538538+ #if CA_AU_PROFILE_TIME
539539+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
540540+ #endif
541541+ require_noerr (result = processor.PostProcess (outputList.ABL(), numFrames,
542542+ isSilence, isDone), home);
543543+ #if CA_AU_PROFILE_TIME
544544+ sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now);
545545+ #endif
546546+547547+PRINT_PROGRESS(processor.GetOLPercentComplete());
548548+549549+ if (numFrames && !shortMemoryProfile)
550550+ destFile.Write (numFrames, outputList.ABL());
551551+ }
552552+ }
553553+554554+printf ("\n");
555555+556556+home:
557557+ if (result) {
558558+ printf ("Exit with bad result:%ld\n", result);
559559+ exit(result);
560560+ }
561561+562562+ if (readBuf) {
563563+ delete readBuf->readData;
564564+ delete readBuf;
565565+ }
566566+567567+#if CA_AU_PROFILE_TIME
568568+ if (!shortMemoryProfile) {
569569+ // this flushes any remaing data to be written to the disk.
570570+ // the source file is closed in its destructor of course
571571+ destFile.Close();
572572+ // open the file again, to get stats about it for profiling
573573+ destFile.Open(destFilePath);
574574+ }
575575+576576+ SInt64 numWritten;
577577+ if (shortMemoryProfile)
578578+ numWritten = 0;
579579+ else {
580580+#if !CAAF_USE_EXTAUDIOFILE
581581+ numWritten = destFile.GetNumberPackets();
582582+#else
583583+ numWritten = destFile.GetNumberFrames();
584584+#endif
585585+ }
586586+587587+ printf ("Read File Time:%.2f secs for %lld packets (%.1f secs), wrote %lld packets\n",
588588+ (CAHostTimeBase::ConvertToNanos (sReadTime) / 1.0e9),
589589+ numInputSamples,
590590+ (numInputSamples / procFormat.mSampleRate),
591591+ numWritten);
592592+593593+ if (!shortMemoryProfile)
594594+ {
595595+#if !CAAF_USE_EXTAUDIOFILE
596596+ UInt64 numOutputSamples = destFile.GetNumberPackets();
597597+#else
598598+ UInt64 numOutputSamples = destFile.GetNumberFrames();
599599+#endif
600600+601601+ if (numOutputSamples == numInputSamples) {
602602+ printf ("\tWrote the same number of packets as read\n");
603603+ } else {
604604+ bool expectationMet = !desc.IsOffline(); // we don't have any expectations for offline AU's
605605+ if (processor.LatencySampleCount() || processor.TailSampleCount()) {
606606+ if (numOutputSamples - numInputSamples == processor.TailSampleCount())
607607+ expectationMet = true;
608608+ if (expectationMet)
609609+ printf ("Correctly wrote \'Read Size + Tail\'. ");
610610+ printf ("AU reports (samples): %ld latency, %ld tail\n",
611611+ processor.LatencySampleCount(), processor.TailSampleCount());
612612+ }
613613+ if (expectationMet == false)
614614+ {
615615+ if (numOutputSamples > numInputSamples) {
616616+ printf ("\tWrote %lld packets (%.2f secs) more than read\n",
617617+ (numOutputSamples - numInputSamples),
618618+ ((numOutputSamples - numInputSamples) / procFormat.mSampleRate));
619619+ } else {
620620+ printf ("\tRead %lld packets (%.2f secs) more than wrote\n",
621621+ (numInputSamples - numOutputSamples),
622622+ ((numInputSamples - numOutputSamples) / procFormat.mSampleRate));
623623+ }
624624+ }
625625+ }
626626+ }
627627+628628+ Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (sRenderTime - sReadTime) / 1.0e9;
629629+ printf ("Total Render Time:%.2f secs, using render slice size of %ld frames\n",
630630+ renderTimeSecs, maxFramesToUse);
631631+632632+ Float64 cpuUsage;
633633+ if (shortMemoryProfile)
634634+ cpuUsage = (renderTimeSecs / 0.5) * 100.;
635635+ else
636636+ cpuUsage = (renderTimeSecs / (numInputSamples / procFormat.mSampleRate)) * 100.;
637637+ printf ("CPU Usage for Render Time:%.2f%%\n", cpuUsage);
638638+639639+ CFStringRef str = comp.GetCompName();
640640+ UInt32 compNameLen = CFStringGetLength (str);
641641+642642+ CFStringRef presetName = NULL;
643643+ if (auPresetFile) {
644644+ CFPropertyListRef dict;
645645+ if (processor.AU().GetAUPreset (dict) == noErr) {
646646+ presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name"));
647647+ CFRelease (dict);
648648+ }
649649+ }
650650+651651+ UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0;
652652+653653+ char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1);
654654+ CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII);
655655+ if (presetName) {
656656+ cstr[compNameLen] = ':';
657657+ cstr[compNameLen+1] = ':';
658658+ CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII);
659659+ }
660660+ PerfResult("AudioUnitProcess", EndianU32_NtoB(comp.Desc().componentSubType), cstr, cpuUsage, "%realtime");
661661+ free (cstr);
662662+#endif
663663+664664+665665+ }
666666+ catch (CAXException &e) {
667667+ char buf[256];
668668+ printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf, sizeof(buf)));
669669+ exit(1);
670670+ }
671671+ catch (...) {
672672+ printf("An unknown error occurred\n");
673673+ exit(1);
674674+ }
675675+676676+ return 0;
677677+}
678678+
+461
src/CoreAudio/AudioFileTools/auprofile.cpp
···11+/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
22+33+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
44+ ("Apple") in consideration of your agreement to the following terms, and your
55+ use, installation, modification or redistribution of this Apple software
66+ constitutes acceptance of these terms. If you do not agree with these terms,
77+ please do not use, install, modify or redistribute this Apple software.
88+99+ In consideration of your agreement to abide by the following terms, and subject
1010+ to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
1111+ copyrights in this original Apple software (the "Apple Software"), to use,
1212+ reproduce, modify and redistribute the Apple Software, with or without
1313+ modifications, in source and/or binary forms; provided that if you redistribute
1414+ the Apple Software in its entirety and without modifications, you must retain
1515+ this notice and the following text and disclaimers in all such redistributions of
1616+ the Apple Software. Neither the name, trademarks, service marks or logos of
1717+ Apple Computer, Inc. may be used to endorse or promote products derived from the
1818+ Apple Software without specific prior written permission from Apple. Except as
1919+ expressly stated in this notice, no other rights or licenses, express or implied,
2020+ are granted by Apple herein, including but not limited to any patent rights that
2121+ may be infringed by your derivative works or by other works in which the Apple
2222+ Software may be incorporated.
2323+2424+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
2525+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
2626+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2727+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
2828+ COMBINATION WITH YOUR PRODUCTS.
2929+3030+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
3131+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3232+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3333+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
3434+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
3535+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
3636+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737+*/
3838+/*=============================================================================
3939+ auprofile.cpp
4040+4141+=============================================================================*/
4242+4343+/*
4444+ auprofile
4545+ - takes a source audio file, an AU and processes this for performance metrics
4646+*/
4747+4848+#include "CAAUProcessor.h"
4949+#include "CAAudioFile.h"
5050+#include "CAXException.h"
5151+#include "CAHostTimeBase.h"
5252+#include "CAFilePathUtils.h"
5353+#include "CAAudioFileFormats.h"
5454+5555+#if TARGET_OS_MAC
5656+ #include <pthread.h>
5757+ #include <mach/mach.h>
5858+#endif
5959+6060+#if DEBUG
6161+ #define VERBOSE 0
6262+#endif
6363+6464+UInt64 sLastReadTime = 0;
6565+Float64 sMinTime = 9999999999.; // too big a time!
6666+Float64 sMaxTime = 0;
6767+6868+#pragma mark __print helpers
6969+7070+void PerfResult(const char *toolname, int group, const char *testname, double value, const char *units, const char *fmt="%.3f")
7171+{
7272+ printf("<result tool='%s' group='%d' test='%s' value='", toolname, group, testname);
7373+ printf(fmt, value);
7474+ printf("' units='%s' />\n", units);
7575+}
7676+7777+#pragma mark __Inpput Callback Definitions
7878+7979+8080+// the file is read into memory - the input's role is to parse through this memory
8181+8282+struct ReadBuffer {
8383+ AUOutputBL *readData;
8484+ UInt64 totalInputFrames;
8585+ UInt32 lastInputFrames;
8686+};
8787+8888+const int kEndOfInput = 12345;
8989+9090+static OSStatus MemoryInputCallback (void *inRefCon,
9191+ AudioUnitRenderActionFlags *ioActionFlags,
9292+ const AudioTimeStamp *inTimeStamp,
9393+ UInt32 inBusNumber,
9494+ UInt32 inNumberFrames,
9595+ AudioBufferList *ioData)
9696+{
9797+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
9898+ OSStatus result = 0;
9999+100100+ ReadBuffer *readBuffer = (ReadBuffer*)inRefCon;
101101+ if (inTimeStamp->mSampleTime >= readBuffer->totalInputFrames) {
102102+ #if VERBOSE
103103+ printf ("reading: %.0f past input: %.0f\n", inTimeStamp->mSampleTime,
104104+ (double)readBuffer->totalInputFrames);
105105+ #endif
106106+ result = kEndOfInput;
107107+ readBuffer->lastInputFrames = 0;
108108+ goto end;
109109+ }
110110+111111+ // can get pulled multiple times
112112+ readBuffer->lastInputFrames += inNumberFrames;
113113+114114+ if (UInt64(inTimeStamp->mSampleTime + inNumberFrames) > readBuffer->totalInputFrames) {
115115+ // first set this to zero as we're only going to read a partial number of frames
116116+ AudioBuffer *buf = ioData->mBuffers;
117117+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
118118+ memset((Byte *)buf->mData, 0, buf->mDataByteSize);
119119+120120+ inNumberFrames = UInt32 (readBuffer->totalInputFrames - UInt64(inTimeStamp->mSampleTime));
121121+ }
122122+123123+ // copy data from the source to the ioData buffers
124124+ {
125125+ AudioBuffer *buf = ioData->mBuffers;
126126+ AudioBuffer *rBuf = readBuffer->readData->ABL()->mBuffers;
127127+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf, ++rBuf) {
128128+ AudioBuffer readB = *rBuf;
129129+ readB.mData = static_cast<Float32*>(rBuf->mData) + UInt32(inTimeStamp->mSampleTime);
130130+ memcpy (buf->mData, readB.mData, (inNumberFrames * sizeof(Float32)));
131131+ }
132132+ }
133133+134134+end:
135135+ sLastReadTime += (CAHostTimeBase::GetTheCurrentTime() - now);
136136+137137+ return result;
138138+}
139139+140140+#pragma mark __Utility Helpers
141141+142142+CFPropertyListRef ReadPresetFromPresetFile (char* filePath)
143143+{
144144+ if (!filePath)
145145+ return NULL;
146146+147147+ FSRef ref;
148148+ if (FSPathMakeRef((UInt8 *)filePath, &ref, NULL))
149149+ return NULL;
150150+151151+ CFDataRef resourceData = NULL;
152152+ CFPropertyListRef theData = NULL;
153153+ CFStringRef errString = NULL;
154154+ CFURLRef fileURL = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref);
155155+ if (fileURL == NULL) {
156156+ goto home;
157157+ }
158158+159159+ SInt32 result;
160160+161161+ // Read the XML file.
162162+ Boolean status; status = CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, fileURL,
163163+ &resourceData, // place to put file data
164164+ NULL, NULL, &result);
165165+ if (status == false || result) {
166166+ goto home;
167167+ }
168168+169169+ theData = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, resourceData,
170170+ kCFPropertyListImmutable, &errString);
171171+ if (theData == NULL || errString) {
172172+ if (theData)
173173+ CFRelease (theData);
174174+ theData = NULL;
175175+ goto home;
176176+ }
177177+178178+home:
179179+ if (fileURL)
180180+ CFRelease (fileURL);
181181+ if (resourceData)
182182+ CFRelease (resourceData);
183183+ if (errString)
184184+ CFRelease (errString);
185185+186186+ return theData;
187187+}
188188+189189+#pragma mark __the setup code
190190+191191+#define OFFLINE_AU_CMD "[-au TYPE SUBTYPE MANU] The Audio Unit component description\n\t"
192192+#define INPUT_FILE "[-i /Path/To/File] The file that is to be processed.\n\t"
193193+#define AU_PRESET_CMD "[-p /Path/To/AUPreset/File] Specify an AU Preset File to establish the state of the AU\n\t"
194194+#define USE_MAX_FRAMES "[-f max_frames] default is 4096"
195195+196196+static char* usageStr = "Usage: auprofile\n\t"
197197+ OFFLINE_AU_CMD
198198+ INPUT_FILE
199199+ AU_PRESET_CMD
200200+ USE_MAX_FRAMES;
201201+202202+int main(int argc, const char * argv[])
203203+{
204204+#if TARGET_OS_MAC
205205+ {
206206+ thread_extended_policy_data_t theFixedPolicy;
207207+ theFixedPolicy.timeshare = false; // set to true for a non-fixed thread
208208+ thread_policy_set(pthread_mach_thread_np(pthread_self()),
209209+ THREAD_EXTENDED_POLICY,
210210+ (thread_policy_t)&theFixedPolicy,
211211+ THREAD_EXTENDED_POLICY_COUNT);
212212+213213+ // We keep a reference to the spawning thread's priority around (initialized in the constructor),
214214+ // and set the importance of the child thread relative to the spawning thread's priority.
215215+ thread_precedence_policy_data_t thePrecedencePolicy;
216216+217217+ thePrecedencePolicy.importance = 63 - 36;
218218+ thread_policy_set(pthread_mach_thread_np(pthread_self()),
219219+ THREAD_PRECEDENCE_POLICY,
220220+ (thread_policy_t)&thePrecedencePolicy,
221221+ THREAD_PRECEDENCE_POLICY_COUNT);
222222+ }
223223+#endif
224224+225225+226226+// These are the variables that are set up from the input parsing
227227+ char* srcFilePath = NULL;
228228+ char* auPresetFile = NULL;
229229+ OSType manu, subType, type = 0;
230230+ UInt32 numFrames = 4096;
231231+232232+ for (int i = 1; i < argc; ++i)
233233+ {
234234+ if (strcmp (argv[i], "-au") == 0) {
235235+ if ( (i + 3) < argc ) {
236236+ StrToOSType (argv[i + 1], type);
237237+ StrToOSType (argv[i + 2], subType);
238238+ StrToOSType (argv[i + 3], manu);
239239+ i += 3;
240240+ } else {
241241+ printf ("Which Audio Unit:\n%s", usageStr);
242242+ exit(1);
243243+ }
244244+ }
245245+ else if (strcmp (argv[i], "-i") == 0) {
246246+ srcFilePath = const_cast<char*>(argv[++i]);
247247+ }
248248+ else if (strcmp (argv[i], "-p") == 0) {
249249+ auPresetFile = const_cast<char*>(argv[++i]);
250250+ }
251251+ else if (strcmp (argv[i], "-f") == 0) {
252252+ sscanf(argv[++i], "%ld", &numFrames);
253253+ }
254254+ else {
255255+ printf ("%s\n", usageStr);
256256+ exit(1);
257257+ }
258258+ }
259259+260260+ if (!type || !srcFilePath) {
261261+ printf ("%s\n", usageStr);
262262+ exit(1);
263263+ }
264264+265265+ CAComponentDescription desc(type, subType, manu);
266266+267267+ CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile);
268268+269269+#pragma mark -
270270+#pragma mark __ The driving code
271271+#pragma mark -
272272+273273+ try
274274+ {
275275+ CAComponent comp(desc);
276276+277277+ // CAAUProcessor's constructor throws... so make sure the component is valid
278278+ if (comp.IsValid() == false) {
279279+ printf ("Can't Find Component\n");
280280+ desc.Print();
281281+ exit(1);
282282+ }
283283+284284+ CAAUProcessor processor(comp);
285285+ processor.AU().Comp().Print();
286286+287287+ CAAudioFile srcFile;
288288+289289+ srcFile.Open(srcFilePath);
290290+291291+#if !CAAF_USE_EXTAUDIOFILE
292292+ UInt64 numInputSamples = srcFile.GetNumberPackets();
293293+#else
294294+ UInt64 numInputSamples = srcFile.GetNumberFrames();
295295+#endif
296296+297297+ Float64 inputSecs = (numInputSamples / srcFile.GetFileDataFormat().mSampleRate);
298298+299299+ CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat());
300300+ procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false);
301301+302302+ printf ("Processing file: %s, %.1f secs [proc: %ld frames]\n", srcFilePath, inputSecs, numFrames);
303303+ #if VERBOSE
304304+ printf("\t");
305305+ procFormat.Print();
306306+ #endif
307307+308308+ srcFile.SetClientFormat (procFormat);
309309+310310+ AUOutputBL outputList(procFormat);
311311+312312+ // read the entire file into memory
313313+ ReadBuffer* readBuf = new ReadBuffer;
314314+ readBuf->readData = new AUOutputBL(procFormat);
315315+ readBuf->totalInputFrames = numInputSamples;
316316+ readBuf->readData->Allocate (numInputSamples);
317317+ readBuf->readData->Prepare();
318318+ UInt32 readSamps = (UInt32)numInputSamples;
319319+ srcFile.Read (readSamps, readBuf->readData->ABL());
320320+321321+ AURenderCallbackStruct inputCallback;
322322+ inputCallback.inputProc = MemoryInputCallback;
323323+ inputCallback.inputProcRefCon = readBuf;
324324+325325+ OSStatus result;
326326+ require_noerr (result = processor.EstablishInputCallback (inputCallback), home);
327327+ require_noerr (result = processor.SetMaxFramesPerRender (numFrames), home);
328328+ require_noerr (result = processor.Initialize (procFormat, numInputSamples), home);
329329+ if (presetDict) {
330330+ require_noerr (result = processor.SetAUPreset (presetDict), home);
331331+ CFRelease (presetDict);
332332+ }
333333+ // this does ALL of the preflighting.. could be specialise for an OfflineAU type
334334+ // to do this piecemeal and do a progress bar by using the OfflineAUPreflight method
335335+ readBuf->lastInputFrames = 0;
336336+ require_noerr (result = processor.Preflight (), home);
337337+338338+ float mean;
339339+340340+ // now do the processing....
341341+ {
342342+ const int kThrasherSize = 4000000;
343343+ char* thrasher = new char[kThrasherSize];
344344+345345+ bool isDone = false;
346346+347347+ UInt32 numMeasures = 0;
348348+ Float64 totalMSqrd;
349349+ Float64 totalM;
350350+351351+ int i = 0;
352352+ int discardResults = 3;
353353+354354+ // this is the render loop
355355+ while (!isDone)
356356+ {
357357+ bool isSilence, postProcess;
358358+359359+ outputList.Prepare(); // have to do this every time...
360360+ readBuf->lastInputFrames = 0;
361361+ sLastReadTime = 0;
362362+ memset (thrasher, numMeasures, kThrasherSize);
363363+364364+ UInt64 now = CAHostTimeBase::GetTheCurrentTime();
365365+ require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone, &postProcess), home);
366366+ UInt64 renderTime = (CAHostTimeBase::GetTheCurrentTime() - now);
367367+368368+ if (i++ < discardResults) continue;
369369+ if (!readBuf->lastInputFrames) break;
370370+371371+ Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (renderTime - sLastReadTime) / 1.0e9;
372372+373373+ Float64 cpuTime = (renderTimeSecs / (readBuf->lastInputFrames / procFormat.mSampleRate)) * 100.;
374374+ numMeasures++;
375375+376376+ totalMSqrd += (cpuTime * cpuTime);
377377+ totalM += cpuTime;
378378+379379+ if (cpuTime > sMaxTime)
380380+ sMaxTime = cpuTime;
381381+ if (cpuTime < sMinTime)
382382+ sMinTime = cpuTime;
383383+384384+#if VERBOSE
385385+// printf ("current measure: %.2f\n", cpuTime);
386386+ if (numMeasures % 5 == 0) {
387387+ Float64 mean = totalM / numMeasures;
388388+ // stdDev = (sum of Xsquared -((sum of X)*(sum of X)/N)) / (N-1))
389389+ Float64 stdDev = sqrt ((totalMSqrd - ((totalM * totalM) / numMeasures)) / (numMeasures-1.0));
390390+ printf ("ave: %.2f, min: %.2f, max: %.2f, stdev: %.2f, numMeasures: %ld, current: %f\n",
391391+ mean, sMinTime, sMaxTime, stdDev, numMeasures, cpuTime);
392392+ }
393393+#endif
394394+ }
395395+ delete [] thrasher;
396396+397397+ mean = totalM / numMeasures;
398398+ // stdDev = (sum of Xsquared -((sum of X)*(sum of X)/N)) / (N-1))
399399+ Float64 stdDev = sqrt ((totalMSqrd - ((totalM * totalM) / numMeasures)) / (numMeasures-1.0));
400400+401401+ printf ("ave: %.2f, min: %.2f, max: %.2f, sd: %.2f, sd / mean: %.2f%%\n",
402402+ mean, sMinTime, sMaxTime, stdDev, (stdDev / mean * 100.));
403403+ }
404404+405405+ // we don't care about post-processing
406406+407407+home:
408408+ if (result) {
409409+ printf ("Exit with bad result:%ld\n", result);
410410+ exit(result);
411411+ }
412412+413413+ if (readBuf) {
414414+ delete readBuf->readData;
415415+ delete readBuf;
416416+ }
417417+418418+419419+ CFStringRef str = comp.GetCompName();
420420+ UInt32 compNameLen = CFStringGetLength (str);
421421+422422+ CFStringRef presetName = NULL;
423423+ if (auPresetFile) {
424424+ CFPropertyListRef dict;
425425+ if (processor.AU().GetAUPreset (dict) == noErr) {
426426+ presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name"));
427427+ CFRelease (dict);
428428+ }
429429+ }
430430+431431+ UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0;
432432+433433+ UInt32 groupID = comp.Desc().componentSubType;
434434+435435+ char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1);
436436+ CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII);
437437+ if (presetName) {
438438+ cstr[compNameLen] = ':';
439439+ cstr[compNameLen+1] = ':';
440440+ CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII);
441441+ int len = strlen(cstr);
442442+ for (int i = 0; i < len; ++i)
443443+ groupID += cstr[i];
444444+ }
445445+ PerfResult("AU Profile", EndianU32_NtoB(groupID), cstr, mean, "%realtime");
446446+ free (cstr);
447447+448448+ }
449449+ catch (CAXException &e) {
450450+ char buf[256];
451451+ printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
452452+ exit(1);
453453+ }
454454+ catch (...) {
455455+ printf("An unknown error occurred\n");
456456+ exit(1);
457457+ }
458458+459459+ return 0;
460460+}
461461+