summaryrefslogtreecommitdiff
path: root/libs/appleutility/CAAudioFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CAAudioFile.cpp')
-rw-r--r--libs/appleutility/CAAudioFile.cpp1241
1 files changed, 0 insertions, 1241 deletions
diff --git a/libs/appleutility/CAAudioFile.cpp b/libs/appleutility/CAAudioFile.cpp
deleted file mode 100644
index e1e39b0ec9..0000000000
--- a/libs/appleutility/CAAudioFile.cpp
+++ /dev/null
@@ -1,1241 +0,0 @@
-/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*=============================================================================
- CAAudioFile.cpp
-
-=============================================================================*/
-
-#include "CAAudioFile.h"
-
-#if !CAAF_USE_EXTAUDIOFILE
-
-#include "CAXException.h"
-#include <algorithm>
-#include "CAHostTimeBase.h"
-#include "CADebugMacros.h"
-
-#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
- #include <AudioToolbox/AudioToolbox.h>
-#else
- #include <AudioFormat.h>
-#endif
-
-#if DEBUG
- //#define VERBOSE_IO 1
- //#define VERBOSE_CONVERTER 1
- //#define VERBOSE_CHANNELMAP 1
- //#define LOG_FUNCTION_ENTRIES 1
-
- #if VERBOSE_CHANNELMAP
- #include "CAChannelLayouts.h" // this is in Source/Tests/AudioFileTools/Utility
- #endif
-#endif
-
-#if LOG_FUNCTION_ENTRIES
- class FunctionLogger {
- public:
- FunctionLogger(const char *name, const char *fmt=NULL, ...) : mName(name) {
- Indent();
- printf("-> %s ", name);
- if (fmt) {
- va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- }
- printf("\n");
- ++sIndent;
- }
- ~FunctionLogger() {
- --sIndent;
- Indent();
- printf("<- %s\n", mName);
- if (sIndent == 0)
- printf("\n");
- }
-
- static void Indent() {
- for (int i = sIndent; --i >= 0; ) {
- putchar(' '); putchar(' ');
- }
- }
-
- const char *mName;
- static int sIndent;
- };
- int FunctionLogger::sIndent = 0;
-
- #define LOG_FUNCTION(name, format, ...) FunctionLogger _flog(name, format, ## __VA_ARGS__);
-#else
- #define LOG_FUNCTION(name, format, foo)
-#endif
-
-static const UInt32 kDefaultIOBufferSizeBytes = 0x10000;
-
-#if CAAUDIOFILE_PROFILE
- #define StartTiming(af, starttime) UInt64 starttime = af->mProfiling ? CAHostTimeBase::GetTheCurrentTime() : 0
- #define ElapsedTime(af, starttime, counter) if (af->mProfiling) counter += (CAHostTimeBase::GetTheCurrentTime() - starttime)
-#else
- #define StartTiming(af, starttime)
- #define ElapsedTime(af, starttime, counter)
-#endif
-
-#define kNoMoreInputRightNow 'nein'
-
-// _______________________________________________________________________________________
-//
-CAAudioFile::CAAudioFile() :
- mAudioFile(0),
- mUseCache(false),
- mFinishingEncoding(false),
- mMode(kClosed),
- mFileDataOffset(-1),
- mFramesToSkipFollowingSeek(0),
-
- mClientOwnsIOBuffer(false),
- mPacketDescs(NULL),
- mNumPacketDescs(0),
- mConverter(NULL),
- mMagicCookie(NULL),
- mWriteBufferList(NULL)
-#if CAAUDIOFILE_PROFILE
- ,
- mProfiling(false),
- mTicksInConverter(0),
- mTicksInReadInConverter(0),
- mTicksInIO(0),
- mInConverter(false)
-#endif
-{
- mIOBufferList.mBuffers[0].mData = NULL;
- mIOBufferList.mBuffers[0].mDataByteSize = 0;
- mClientMaxPacketSize = 0;
- mIOBufferSizeBytes = kDefaultIOBufferSizeBytes;
-}
-
-// _______________________________________________________________________________________
-//
-CAAudioFile::~CAAudioFile()
-{
- Close();
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::Close()
-{
- LOG_FUNCTION("CAAudioFile::Close", NULL, NULL);
- if (mMode == kClosed)
- return;
- if (mMode == kWriting)
- FlushEncoder();
- CloseConverter();
- if (mAudioFile != 0 && mOwnOpenFile) {
- AudioFileClose(mAudioFile);
- mAudioFile = 0;
- }
- if (!mClientOwnsIOBuffer) {
- delete[] (Byte *)mIOBufferList.mBuffers[0].mData;
- mIOBufferList.mBuffers[0].mData = NULL;
- mIOBufferList.mBuffers[0].mDataByteSize = 0;
- }
- delete[] mPacketDescs; mPacketDescs = NULL; mNumPacketDescs = 0;
- delete[] mMagicCookie; mMagicCookie = NULL;
- delete mWriteBufferList; mWriteBufferList = NULL;
- mMode = kClosed;
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::CloseConverter()
-{
- if (mConverter) {
-#if VERBOSE_CONVERTER
- printf("CAAudioFile %p : CloseConverter\n", this);
-#endif
- AudioConverterDispose(mConverter);
- mConverter = NULL;
- }
-}
-
-// =======================================================================================
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::Open(const FSRef &fsref)
-{
- LOG_FUNCTION("CAAudioFile::Open", "%p", this);
- XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open");
- mFSRef = fsref;
- XThrowIfError(AudioFileOpen(&mFSRef, fsRdPerm, 0, &mAudioFile), "open audio file");
- mOwnOpenFile = true;
- mMode = kReading;
- GetExistingFileInfo();
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::Wrap(AudioFileID fileID, bool forWriting)
-{
- LOG_FUNCTION("CAAudioFile::Wrap", "%p", this);
- XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open");
-
- mAudioFile = fileID;
- mOwnOpenFile = false;
- mMode = forWriting ? kPreparingToWrite : kReading;
- GetExistingFileInfo();
- if (forWriting)
- FileFormatChanged();
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::CreateNew(const FSRef &parentDir, CFStringRef filename, AudioFileTypeID filetype, const AudioStreamBasicDescription &dataFormat, const AudioChannelLayout *layout)
-{
- LOG_FUNCTION("CAAudioFile::CreateNew", "%p", this);
- XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open");
-
- mFileDataFormat = dataFormat;
- if (layout) {
- mFileChannelLayout = layout;
-#if VERBOSE_CHANNELMAP
- printf("PrepareNew passed channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
-#endif
- }
- mMode = kPreparingToCreate;
- FileFormatChanged(&parentDir, filename, filetype);
-}
-
-// _______________________________________________________________________________________
-//
-// called to create the file -- or update its format/channel layout/properties based on an encoder
-// setting change
-void CAAudioFile::FileFormatChanged(const FSRef *parentDir, CFStringRef filename, AudioFileTypeID filetype)
-{
- LOG_FUNCTION("CAAudioFile::FileFormatChanged", "%p", this);
- XThrowIf(mMode != kPreparingToCreate && mMode != kPreparingToWrite, kExtAudioFileError_InvalidOperationOrder, "new file not prepared");
-
- UInt32 propertySize;
- OSStatus err;
- AudioStreamBasicDescription saveFileDataFormat = mFileDataFormat;
-
-#if VERBOSE_CONVERTER
- mFileDataFormat.PrintFormat(stdout, "", "Specified file data format");
-#endif
-
- // Find out the actual format the converter will produce. This is necessary in
- // case the bitrate has forced a lower sample rate, which needs to be set correctly
- // in the stream description passed to AudioFileCreate.
- if (mConverter != NULL) {
- propertySize = sizeof(AudioStreamBasicDescription);
- Float64 origSampleRate = mFileDataFormat.mSampleRate;
- XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterCurrentOutputStreamDescription, &propertySize, &mFileDataFormat), "get audio converter's output stream description");
- // do the same for the channel layout being output by the converter
-#if VERBOSE_CONVERTER
- mFileDataFormat.PrintFormat(stdout, "", "Converter output");
-#endif
- if (fiszero(mFileDataFormat.mSampleRate))
- mFileDataFormat.mSampleRate = origSampleRate;
- err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterOutputChannelLayout, &propertySize, NULL);
- if (err == noErr && propertySize > 0) {
- AudioChannelLayout *layout = static_cast<AudioChannelLayout *>(malloc(propertySize));
- err = AudioConverterGetProperty(mConverter, kAudioConverterOutputChannelLayout, &propertySize, layout);
- if (err) {
- free(layout);
- XThrow(err, "couldn't get audio converter's output channel layout");
- }
- mFileChannelLayout = layout;
-#if VERBOSE_CHANNELMAP
- printf("got new file's channel layout from converter: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
-#endif
- free(layout);
- }
- }
-
- // create the output file
- if (mMode == kPreparingToCreate) {
- CAStreamBasicDescription newFileDataFormat = mFileDataFormat;
- if (fiszero(newFileDataFormat.mSampleRate))
- newFileDataFormat.mSampleRate = 44100; // just make something up for now
-#if VERBOSE_CONVERTER
- newFileDataFormat.PrintFormat(stdout, "", "Applied to new file");
-#endif
- XThrowIfError(AudioFileCreate(parentDir, filename, filetype, &newFileDataFormat, 0, &mFSRef, &mAudioFile), "create audio file");
- mMode = kPreparingToWrite;
- mOwnOpenFile = true;
- } else if (saveFileDataFormat != mFileDataFormat || fnotequal(saveFileDataFormat.mSampleRate, mFileDataFormat.mSampleRate)) {
- // second check must be explicit since operator== on ASBD treats SR of zero as "don't care"
- if (fiszero(mFileDataFormat.mSampleRate))
- mFileDataFormat.mSampleRate = mClientDataFormat.mSampleRate;
-#if VERBOSE_CONVERTER
- mFileDataFormat.PrintFormat(stdout, "", "Applied to new file");
-#endif
- XThrowIf(fiszero(mFileDataFormat.mSampleRate), kExtAudioFileError_InvalidDataFormat, "file's sample rate is 0");
- XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyDataFormat, sizeof(AudioStreamBasicDescription), &mFileDataFormat), "couldn't update file's data format");
- }
-
- UInt32 deferSizeUpdates = 1;
- err = AudioFileSetProperty(mAudioFile, kAudioFilePropertyDeferSizeUpdates, sizeof(UInt32), &deferSizeUpdates);
-
- if (mConverter != NULL) {
- // encoder
- // get the magic cookie, if any, from the converter
- delete[] mMagicCookie; mMagicCookie = NULL;
- mMagicCookieSize = 0;
-
- err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, NULL);
-
- // we can get a noErr result and also a propertySize == 0
- // -- if the file format does support magic cookies, but this file doesn't have one.
- if (err == noErr && propertySize > 0) {
- mMagicCookie = new Byte[propertySize];
- XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, mMagicCookie), "get audio converter's magic cookie");
- mMagicCookieSize = propertySize; // the converter lies and tell us the wrong size
- // now set the magic cookie on the output file
- UInt32 willEatTheCookie = false;
- // the converter wants to give us one; will the file take it?
- err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyMagicCookieData,
- NULL, &willEatTheCookie);
- if (err == noErr && willEatTheCookie) {
-#if VERBOSE_CONVERTER
- printf("Setting cookie on encoded file\n");
-#endif
- XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyMagicCookieData, mMagicCookieSize, mMagicCookie), "set audio file's magic cookie");
- }
- }
-
- // get maximum packet size
- propertySize = sizeof(UInt32);
- XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterPropertyMaximumOutputPacketSize, &propertySize, &mFileMaxPacketSize), "get audio converter's maximum output packet size");
-
- AllocateBuffers(true /* okToFail */);
- } else {
- InitFileMaxPacketSize();
- }
-
- if (mFileChannelLayout.IsValid() && mFileChannelLayout.NumberChannels() > 2) {
- // don't bother tagging mono/stereo files
- UInt32 isWritable;
- err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, NULL, &isWritable);
- if (!err && isWritable) {
-#if VERBOSE_CHANNELMAP
- printf("writing file's channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
-#endif
- err = AudioFileSetProperty(mAudioFile, kAudioFilePropertyChannelLayout,
- mFileChannelLayout.Size(), &mFileChannelLayout.Layout());
- if (err)
- CAXException::Warning("could not set the file's channel layout", err);
- } else {
-#if VERBOSE_CHANNELMAP
- printf("file won't accept a channel layout (write)\n");
-#endif
- }
- }
-
- UpdateClientMaxPacketSize(); // also sets mFrame0Offset
- mPacketMark = 0;
- mFrameMark = 0;
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::InitFileMaxPacketSize()
-{
- LOG_FUNCTION("CAAudioFile::InitFileMaxPacketSize", "%p", this);
- UInt32 propertySize = sizeof(UInt32);
- OSStatus err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyMaximumPacketSize,
- &propertySize, &mFileMaxPacketSize);
- if (err) {
- // workaround for 3361377: not all file formats' maximum packet sizes are supported
- if (!mFileDataFormat.IsPCM())
- XThrowIfError(err, "get audio file's maximum packet size");
- mFileMaxPacketSize = mFileDataFormat.mBytesPerFrame;
- }
- AllocateBuffers(true /* okToFail */);
-}
-
-
-// _______________________________________________________________________________________
-//
-SInt64 CAAudioFile::FileDataOffset()
-{
- if (mFileDataOffset < 0) {
- UInt32 propertySize = sizeof(SInt64);
- XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataOffset, &propertySize, &mFileDataOffset), "couldn't get file's data offset");
- }
- return mFileDataOffset;
-}
-
-// _______________________________________________________________________________________
-//
-SInt64 CAAudioFile::GetNumberFrames() const
-{
- AudioFilePacketTableInfo pti;
- UInt32 propertySize = sizeof(pti);
- OSStatus err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti);
- if (err == noErr)
- return pti.mNumberValidFrames;
- return mFileDataFormat.mFramesPerPacket * GetNumberPackets() - mFrame0Offset;
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::SetNumberFrames(SInt64 nFrames)
-{
- XThrowIf(mFileDataFormat.mFramesPerPacket != 1, kExtAudioFileError_InvalidDataFormat, "SetNumberFrames only supported for PCM");
- XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, sizeof(SInt64), &nFrames), "Couldn't set number of packets on audio file");
-}
-
-// _______________________________________________________________________________________
-//
-// call for existing file, NOT new one - from Open() or Wrap()
-void CAAudioFile::GetExistingFileInfo()
-{
- LOG_FUNCTION("CAAudioFile::GetExistingFileInfo", "%p", this);
- UInt32 propertySize;
- OSStatus err;
-
- // get mFileDataFormat
- propertySize = sizeof(AudioStreamBasicDescription);
- XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataFormat, &propertySize, &mFileDataFormat), "get audio file's data format");
-
- // get mFileChannelLayout
- err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, &propertySize, NULL);
- if (err == noErr && propertySize > 0) {
- AudioChannelLayout *layout = static_cast<AudioChannelLayout *>(malloc(propertySize));
- err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyChannelLayout, &propertySize, layout);
- if (err == noErr) {
- mFileChannelLayout = layout;
-#if VERBOSE_CHANNELMAP
- printf("existing file's channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
-#endif
- }
- free(layout);
- XThrowIfError(err, "get audio file's channel layout");
- }
- if (mMode != kReading)
- return;
-
-#if 0
- // get mNumberPackets
- propertySize = sizeof(mNumberPackets);
- XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &propertySize, &mNumberPackets), "get audio file's packet count");
-#if VERBOSE_IO
- printf("CAAudioFile::GetExistingFileInfo: %qd packets\n", mNumberPackets);
-#endif
-#endif
-
- // get mMagicCookie
- err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyMagicCookieData, &propertySize, NULL);
- if (err == noErr && propertySize > 0) {
- mMagicCookie = new Byte[propertySize];
- mMagicCookieSize = propertySize;
- XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyMagicCookieData, &propertySize, mMagicCookie), "get audio file's magic cookie");
- }
- InitFileMaxPacketSize();
- mPacketMark = 0;
- mFrameMark = 0;
-
- UpdateClientMaxPacketSize();
-}
-
-// =======================================================================================
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::SetFileChannelLayout(const CAAudioChannelLayout &layout)
-{
- LOG_FUNCTION("CAAudioFile::SetFileChannelLayout", "%p", this);
- mFileChannelLayout = layout;
-#if VERBOSE_CHANNELMAP
- printf("file channel layout set explicitly (%s): %s\n", mMode == kReading ? "read" : "write", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
-#endif
- if (mMode != kReading)
- FileFormatChanged();
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout)
-{
- LOG_FUNCTION("CAAudioFile::SetClientFormat", "%p", this);
- XThrowIf(!dataFormat.IsPCM(), kExtAudioFileError_NonPCMClientFormat, "non-PCM client format on audio file");
-
- bool dataFormatChanging = (mClientDataFormat.mFormatID == 0 || mClientDataFormat != dataFormat);
-
- if (dataFormatChanging) {
- CloseConverter();
- if (mWriteBufferList) {
- delete mWriteBufferList;
- mWriteBufferList = NULL;
- }
- mClientDataFormat = dataFormat;
- }
-
- if (layout && layout->IsValid()) {
- XThrowIf(layout->NumberChannels() != mClientDataFormat.NumberChannels(), kExtAudioFileError_InvalidChannelMap, "inappropriate channel map");
- mClientChannelLayout = *layout;
- }
-
- bool differentLayouts;
- if (mClientChannelLayout.IsValid()) {
- if (mFileChannelLayout.IsValid()) {
- differentLayouts = mClientChannelLayout.Tag() != mFileChannelLayout.Tag();
-#if VERBOSE_CHANNELMAP
- printf("two valid layouts, %s\n", differentLayouts ? "different" : "same");
-#endif
- } else {
- differentLayouts = false;
-#if VERBOSE_CHANNELMAP
- printf("valid client layout, unknown file layout\n");
-#endif
- }
- } else {
- differentLayouts = false;
-#if VERBOSE_CHANNELMAP
- if (mFileChannelLayout.IsValid())
- printf("valid file layout, unknown client layout\n");
- else
- printf("two invalid layouts\n");
-#endif
- }
-
- if (mClientDataFormat != mFileDataFormat || differentLayouts) {
- // We need an AudioConverter.
- if (mMode == kReading) {
- // file -> client (decode)
-//mFileDataFormat.PrintFormat( stdout, "", "File: ");
-//mClientDataFormat.PrintFormat(stdout, "", "Client: ");
-
- if (mConverter == NULL)
- XThrowIfError(AudioConverterNew(&mFileDataFormat, &mClientDataFormat, &mConverter),
- "create audio converter");
-
-#if VERBOSE_CONVERTER
- printf("CAAudioFile %p -- created converter\n", this);
- CAShow(mConverter);
-#endif
- // set the magic cookie, if any (for decode)
- if (mMagicCookie)
- SetConverterProperty(kAudioConverterDecompressionMagicCookie, mMagicCookieSize, mMagicCookie, mFileDataFormat.IsPCM());
- // we get cookies from some AIFF's but the converter barfs on them,
- // so we set canFail to true for PCM
-
- SetConverterChannelLayout(false, mFileChannelLayout);
- SetConverterChannelLayout(true, mClientChannelLayout);
-
- // propagate leading/trailing frame counts
- if (mFileDataFormat.mBitsPerChannel == 0) {
- UInt32 propertySize;
- OSStatus err;
- AudioFilePacketTableInfo pti;
- propertySize = sizeof(pti);
- err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti);
- if (err == noErr && (pti.mPrimingFrames > 0 || pti.mRemainderFrames > 0)) {
- AudioConverterPrimeInfo primeInfo;
- primeInfo.leadingFrames = pti.mPrimingFrames;
- primeInfo.trailingFrames = pti.mRemainderFrames;
- /* ignore any error. better to play it at all than not. */
- /*err = */AudioConverterSetProperty(mConverter, kAudioConverterPrimeInfo, sizeof(primeInfo), &primeInfo);
- //XThrowIfError(err, "couldn't set prime info on converter");
- }
- }
- } else if (mMode == kPreparingToCreate || mMode == kPreparingToWrite) {
- // client -> file (encode)
- if (mConverter == NULL)
- XThrowIfError(AudioConverterNew(&mClientDataFormat, &mFileDataFormat, &mConverter), "create audio converter");
- mWriteBufferList = CABufferList::New("", mClientDataFormat);
- SetConverterChannelLayout(false, mClientChannelLayout);
- SetConverterChannelLayout(true, mFileChannelLayout);
- if (mMode == kPreparingToWrite)
- FileFormatChanged();
- } else
- XThrowIfError(kExtAudioFileError_InvalidOperationOrder, "audio file format not yet known");
- }
- UpdateClientMaxPacketSize();
-}
-
-// _______________________________________________________________________________________
-//
-OSStatus CAAudioFile::SetConverterProperty(
- AudioConverterPropertyID inPropertyID,
- UInt32 inPropertyDataSize,
- const void* inPropertyData,
- bool inCanFail)
-{
- OSStatus err = noErr;
- //LOG_FUNCTION("ExtAudioFile::SetConverterProperty", "%p %-4.4s", this, (char *)&inPropertyID);
- if (inPropertyID == kAudioConverterPropertySettings && *(CFPropertyListRef *)inPropertyData == NULL)
- ;
- else {
- err = AudioConverterSetProperty(mConverter, inPropertyID, inPropertyDataSize, inPropertyData);
- if (!inCanFail) {
- XThrowIfError(err, "set audio converter property");
- }
- }
- UpdateClientMaxPacketSize();
- if (mMode == kPreparingToWrite)
- FileFormatChanged();
- return err;
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout)
-{
- LOG_FUNCTION("CAAudioFile::SetConverterChannelLayout", "%p", this);
- OSStatus err;
-
- if (layout.IsValid()) {
-#if VERBOSE_CHANNELMAP
- printf("Setting converter's %s channel layout: %s\n", output ? "output" : "input",
- CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
-#endif
- if (output) {
- err = AudioConverterSetProperty(mConverter, kAudioConverterOutputChannelLayout,
- layout.Size(), &layout.Layout());
- XThrowIf(err && err != kAudioConverterErr_OperationNotSupported, err, "couldn't set converter's output channel layout");
- } else {
- err = AudioConverterSetProperty(mConverter, kAudioConverterInputChannelLayout,
- layout.Size(), &layout.Layout());
- XThrowIf(err && err != kAudioConverterErr_OperationNotSupported, err, "couldn't set converter's input channel layout");
- }
- if (mMode == kPreparingToWrite)
- FileFormatChanged();
- }
-}
-
-// _______________________________________________________________________________________
-//
-CFArrayRef CAAudioFile::GetConverterConfig()
-{
- CFArrayRef plist;
- UInt32 propertySize = sizeof(plist);
- XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterPropertySettings, &propertySize, &plist), "get converter property settings");
- return plist;
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::UpdateClientMaxPacketSize()
-{
- LOG_FUNCTION("CAAudioFile::UpdateClientMaxPacketSize", "%p", this);
- mFrame0Offset = 0;
- if (mConverter != NULL) {
- AudioConverterPropertyID property = (mMode == kReading) ?
- kAudioConverterPropertyMaximumOutputPacketSize :
- kAudioConverterPropertyMaximumInputPacketSize;
-
- UInt32 propertySize = sizeof(UInt32);
- XThrowIfError(AudioConverterGetProperty(mConverter, property, &propertySize, &mClientMaxPacketSize),
- "get audio converter's maximum packet size");
-
- if (mFileDataFormat.mBitsPerChannel == 0) {
- AudioConverterPrimeInfo primeInfo;
- propertySize = sizeof(primeInfo);
- OSStatus err = AudioConverterGetProperty(mConverter, kAudioConverterPrimeInfo, &propertySize, &primeInfo);
- if (err == noErr)
- mFrame0Offset = primeInfo.leadingFrames;
-#if VERBOSE_CONVERTER
- printf("kAudioConverterPrimeInfo: err = %ld, leadingFrames = %ld\n", err, mFrame0Offset);
-#endif
- }
- } else {
- mClientMaxPacketSize = mFileMaxPacketSize;
- }
-}
-
-// _______________________________________________________________________________________
-// Allocates: mIOBufferList, mIOBufferSizePackets, mPacketDescs
-// Dependent on: mFileMaxPacketSize, mIOBufferSizeBytes
-void CAAudioFile::AllocateBuffers(bool okToFail)
-{
- LOG_FUNCTION("CAAudioFile::AllocateBuffers", "%p", this);
- if (mFileMaxPacketSize == 0) {
- if (okToFail)
- return;
- XThrowIf(true, kExtAudioFileError_MaxPacketSizeUnknown, "file's maximum packet size is 0");
- }
- UInt32 bufferSizeBytes = mIOBufferSizeBytes = std::max(mIOBufferSizeBytes, mFileMaxPacketSize);
- // must be big enough for at least one maximum size packet
-
- if (mIOBufferList.mBuffers[0].mDataByteSize != bufferSizeBytes) {
- mIOBufferList.mNumberBuffers = 1;
- mIOBufferList.mBuffers[0].mNumberChannels = mFileDataFormat.mChannelsPerFrame;
- if (!mClientOwnsIOBuffer) {
- //printf("reallocating I/O buffer\n");
- delete[] (Byte *)mIOBufferList.mBuffers[0].mData;
- mIOBufferList.mBuffers[0].mData = new Byte[bufferSizeBytes];
- }
- mIOBufferList.mBuffers[0].mDataByteSize = bufferSizeBytes;
- mIOBufferSizePackets = bufferSizeBytes / mFileMaxPacketSize;
- }
-
- UInt32 propertySize = sizeof(UInt32);
- UInt32 externallyFramed;
- XThrowIfError(AudioFormatGetProperty(kAudioFormatProperty_FormatIsExternallyFramed,
- sizeof(AudioStreamBasicDescription), &mFileDataFormat, &propertySize, &externallyFramed),
- "is format externally framed");
- if (mNumPacketDescs != (externallyFramed ? mIOBufferSizePackets : 0)) {
- delete[] mPacketDescs;
- mPacketDescs = NULL;
- mNumPacketDescs = 0;
-
- if (externallyFramed) {
- //printf("reallocating packet descs\n");
- mPacketDescs = new AudioStreamPacketDescription[mIOBufferSizePackets];
- mNumPacketDescs = mIOBufferSizePackets;
- }
- }
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::SetIOBuffer(void *buf)
-{
- if (!mClientOwnsIOBuffer)
- delete[] (Byte *)mIOBufferList.mBuffers[0].mData;
- mIOBufferList.mBuffers[0].mData = buf;
-
- if (buf == NULL) {
- mClientOwnsIOBuffer = false;
- SetIOBufferSizeBytes(mIOBufferSizeBytes);
- } else {
- mClientOwnsIOBuffer = true;
- AllocateBuffers();
- }
-// printf("CAAudioFile::SetIOBuffer %p: %p, 0x%lx bytes, mClientOwns = %d\n", this, mIOBufferList.mBuffers[0].mData, mIOBufferSizeBytes, mClientOwnsIOBuffer);
-}
-
-// ===============================================================================
-
-/*
-For Tiger:
-added kAudioFilePropertyPacketToFrame and kAudioFilePropertyFrameToPacket.
-You pass in an AudioFramePacketTranslation struct, with the appropriate field filled in, to AudioFileGetProperty.
-
- kAudioFilePropertyPacketToFrame = 'pkfr',
- // pass a AudioFramePacketTranslation with mPacket filled out and get mFrame back. mFrameOffsetInPacket is ignored.
- kAudioFilePropertyFrameToPacket = 'frpk',
- // pass a AudioFramePacketTranslation with mFrame filled out and get mPacket and mFrameOffsetInPacket back.
-
-struct AudioFramePacketTranslation
-{
- SInt64 mFrame;
- SInt64 mPacket;
- UInt32 mFrameOffsetInPacket;
-};
-*/
-
-SInt64 CAAudioFile::PacketToFrame(SInt64 packet) const
-{
- AudioFramePacketTranslation trans;
- UInt32 propertySize;
-
- switch (mFileDataFormat.mFramesPerPacket) {
- case 1:
- return packet;
- case 0:
- trans.mPacket = packet;
- propertySize = sizeof(trans);
- XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketToFrame, &propertySize, &trans),
- "packet <-> frame translation unimplemented for format with variable frames/packet");
- return trans.mFrame;
- }
- return packet * mFileDataFormat.mFramesPerPacket;
-}
-
-SInt64 CAAudioFile::FrameToPacket(SInt64 inFrame) const
-{
- AudioFramePacketTranslation trans;
- UInt32 propertySize;
-
- switch (mFileDataFormat.mFramesPerPacket) {
- case 1:
- return inFrame;
- case 0:
- trans.mFrame = inFrame;
- propertySize = sizeof(trans);
- XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyFrameToPacket, &propertySize, &trans),
- "packet <-> frame translation unimplemented for format with variable frames/packet");
- return trans.mPacket;
- }
- return inFrame / mFileDataFormat.mFramesPerPacket;
-}
-
-// _______________________________________________________________________________________
-//
-
-SInt64 CAAudioFile::Tell() const // frameNumber
-{
- return mFrameMark - mFrame0Offset;
-}
-
-void CAAudioFile::SeekToPacket(SInt64 packetNumber)
-{
-#if VERBOSE_IO
- printf("CAAudioFile::SeekToPacket: %qd\n", packetNumber);
-#endif
- XThrowIf(mMode != kReading || packetNumber < 0 /*|| packetNumber >= mNumberPackets*/ , kExtAudioFileError_InvalidSeek, "seek to packet in audio file");
- if (mPacketMark == packetNumber)
- return; // already there! don't reset converter
- mPacketMark = packetNumber;
-
- mFrameMark = PacketToFrame(packetNumber) - mFrame0Offset;
- mFramesToSkipFollowingSeek = 0;
- if (mConverter)
- // must reset -- if we reached end of stream. converter will no longer work otherwise
- AudioConverterReset(mConverter);
-}
-
-/*
- Example: AAC, 1024 frames/packet, 2112 frame offset
-
- 2112
- |
- Absolute frames: 0 1024 2048 | 3072
- +---------+---------+--|------+---------+---------+
- Packets: | 0 | 1 | | 2 | 3 | 4 |
- +---------+---------+--|------+---------+---------+
- Client frames: -2112 -1088 -64 | 960 SeekToFrame, TellFrame
- |
- 0
-
- * Offset between absolute and client frames is mFrame0Offset.
- *** mFrameMark is in client frames ***
-
- Examples:
- clientFrame 0 960 1000 1024
- absoluteFrame 2112 3072 3112 3136
- packet 0 0 0 1
- tempFrameMark* -2112 -2112 -2112 -1088
- mFramesToSkipFollowingSeek 2112 3072 3112 2112
-*/
-void CAAudioFile::Seek(SInt64 clientFrame)
-{
- if (clientFrame == mFrameMark)
- return; // already there! don't reset converter
-
- //SInt64 absoluteFrame = clientFrame + mFrame0Offset;
- XThrowIf(mMode != kReading || clientFrame < 0 || !mClientDataFormat.IsPCM(), kExtAudioFileError_InvalidSeek, "seek to frame in audio file");
-
-#if VERBOSE_IO
- SInt64 prevFrameMark = mFrameMark;
-#endif
-
- SInt64 packet;
- packet = FrameToPacket(clientFrame);
- if (packet < 0)
- packet = 0;
- SeekToPacket(packet);
- // this will have backed up mFrameMark to match the beginning of the packet
- mFramesToSkipFollowingSeek = std::max(UInt32(clientFrame - mFrameMark), UInt32(0));
- mFrameMark = clientFrame;
-
-#if VERBOSE_IO
- printf("CAAudioFile::SeekToFrame: frame %qd (from %qd), packet %qd, skip %ld frames\n", mFrameMark, prevFrameMark, packet, mFramesToSkipFollowingSeek);
-#endif
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::Read(UInt32 &ioNumPackets, AudioBufferList *ioData)
- // May read fewer packets than requested if:
- // buffer is not big enough
- // file does not contain that many more packets
- // Note that eofErr is not fatal, just results in 0 packets returned
- // ioData's buffer sizes may be shortened
-{
- XThrowIf(mClientMaxPacketSize == 0, kExtAudioFileError_MaxPacketSizeUnknown, "client maximum packet size is 0");
- if (mIOBufferList.mBuffers[0].mData == NULL) {
-#if DEBUG
- printf("warning: CAAudioFile::AllocateBuffers called from ReadPackets\n");
-#endif
- AllocateBuffers();
- }
- UInt32 bufferSizeBytes = ioData->mBuffers[0].mDataByteSize;
- UInt32 maxNumPackets = bufferSizeBytes / mClientMaxPacketSize;
- // older versions of AudioConverterFillComplexBuffer don't do this, so do our own sanity check
- UInt32 nPackets = std::min(ioNumPackets, maxNumPackets);
-
- mMaxPacketsToRead = ~0UL;
-
- if (mClientDataFormat.mFramesPerPacket == 1) { // PCM or equivalent
- while (mFramesToSkipFollowingSeek > 0) {
- UInt32 skipFrames = std::min(mFramesToSkipFollowingSeek, maxNumPackets);
- UInt32 framesPerPacket;
- if ((framesPerPacket=mFileDataFormat.mFramesPerPacket) > 0)
- mMaxPacketsToRead = (skipFrames + framesPerPacket - 1) / framesPerPacket;
-
- if (mConverter == NULL) {
- XThrowIfError(ReadInputProc(NULL, &skipFrames, ioData, NULL, this), "read audio file");
- } else {
-#if CAAUDIOFILE_PROFILE
- mInConverter = true;
-#endif
- StartTiming(this, fill);
- XThrowIfError(AudioConverterFillComplexBuffer(mConverter, ReadInputProc, this, &skipFrames, ioData, NULL), "convert audio packets (pcm read)");
- ElapsedTime(this, fill, mTicksInConverter);
-#if CAAUDIOFILE_PROFILE
- mInConverter = false;
-#endif
- }
- if (skipFrames == 0) { // hit EOF
- ioNumPackets = 0;
- return;
- }
- mFrameMark += skipFrames;
-#if VERBOSE_IO
- printf("CAAudioFile::ReadPackets: skipped %ld frames\n", skipFrames);
-#endif
-
- mFramesToSkipFollowingSeek -= skipFrames;
-
- // restore mDataByteSize
- for (int i = ioData->mNumberBuffers; --i >= 0 ; )
- ioData->mBuffers[i].mDataByteSize = bufferSizeBytes;
- }
- }
-
- if (mFileDataFormat.mFramesPerPacket > 0)
- // don't read more packets than we are being asked to produce
- mMaxPacketsToRead = nPackets / mFileDataFormat.mFramesPerPacket + 1;
- if (mConverter == NULL) {
- XThrowIfError(ReadInputProc(NULL, &nPackets, ioData, NULL, this), "read audio file");
- } else {
-#if CAAUDIOFILE_PROFILE
- mInConverter = true;
-#endif
- StartTiming(this, fill);
- XThrowIfError(AudioConverterFillComplexBuffer(mConverter, ReadInputProc, this, &nPackets, ioData, NULL), "convert audio packets (read)");
- ElapsedTime(this, fill, mTicksInConverter);
-#if CAAUDIOFILE_PROFILE
- mInConverter = false;
-#endif
- }
- if (mClientDataFormat.mFramesPerPacket == 1)
- mFrameMark += nPackets;
-
- ioNumPackets = nPackets;
-}
-
-// _______________________________________________________________________________________
-//
-OSStatus CAAudioFile::ReadInputProc( AudioConverterRef inAudioConverter,
- UInt32* ioNumberDataPackets,
- AudioBufferList* ioData,
- AudioStreamPacketDescription** outDataPacketDescription,
- void* inUserData)
-{
- CAAudioFile *This = static_cast<CAAudioFile *>(inUserData);
-
-#if 0
- SInt64 remainingPacketsInFile = This->mNumberPackets - This->mPacketMark;
- if (remainingPacketsInFile <= 0) {
- *ioNumberDataPackets = 0;
- ioData->mBuffers[0].mDataByteSize = 0;
- if (outDataPacketDescription)
- *outDataPacketDescription = This->mPacketDescs;
-#if VERBOSE_IO
- printf("CAAudioFile::ReadInputProc: EOF\n");
-#endif
- return noErr; // not eofErr; EOF is signified by 0 packets/0 bytes
- }
-#endif
-
- // determine how much to read
- AudioBufferList *readBuffer;
- UInt32 readPackets;
- if (inAudioConverter != NULL) {
- // getting called from converter, need to use our I/O buffer
- readBuffer = &This->mIOBufferList;
- readPackets = This->mIOBufferSizePackets;
- } else {
- // getting called directly from ReadPackets, use supplied buffer
- if (This->mFileMaxPacketSize == 0)
- return kExtAudioFileError_MaxPacketSizeUnknown;
- readBuffer = ioData;
- readPackets = std::min(*ioNumberDataPackets, readBuffer->mBuffers[0].mDataByteSize / This->mFileMaxPacketSize);
- // don't attempt to read more packets than will fit in the buffer
- }
- // don't try to read past EOF
-// if (readPackets > remainingPacketsInFile)
-// readPackets = remainingPacketsInFile;
- // don't read more packets than necessary to produce the requested amount of converted data
- if (readPackets > This->mMaxPacketsToRead) {
-#if VERBOSE_IO
- printf("CAAudioFile::ReadInputProc: limiting read to %ld packets (from %ld)\n", This->mMaxPacketsToRead, readPackets);
-#endif
- readPackets = This->mMaxPacketsToRead;
- }
-
- // read
- UInt32 bytesRead;
- OSStatus err;
-
- StartTiming(This, read);
- StartTiming(This, readinconv);
- err = AudioFileReadPackets(This->mAudioFile, This->mUseCache, &bytesRead, This->mPacketDescs, This->mPacketMark, &readPackets, readBuffer->mBuffers[0].mData);
-#if CAAUDIOFILE_PROFILE
- if (This->mInConverter) ElapsedTime(This, readinconv, This->mTicksInReadInConverter);
-#endif
- ElapsedTime(This, read, This->mTicksInIO);
-
- if (err) {
- DebugMessageN1("Error %ld from AudioFileReadPackets!!!\n", err);
- return err;
- }
-
-#if VERBOSE_IO
- printf("CAAudioFile::ReadInputProc: read %ld packets (%qd-%qd), %ld bytes, err %ld\n", readPackets, This->mPacketMark, This->mPacketMark + readPackets, bytesRead, err);
-#if VERBOSE_IO >= 2
- if (This->mPacketDescs) {
- for (UInt32 i = 0; i < readPackets; ++i) {
- printf(" read packet %qd : offset %qd, length %ld\n", This->mPacketMark + i, This->mPacketDescs[i].mStartOffset, This->mPacketDescs[i].mDataByteSize);
- }
- }
- printf(" read buffer:"); CAShowAudioBufferList(readBuffer, 0, 4);
-#endif
-#endif
- if (readPackets == 0) {
- *ioNumberDataPackets = 0;
- ioData->mBuffers[0].mDataByteSize = 0;
- return noErr;
- }
-
- if (outDataPacketDescription)
- *outDataPacketDescription = This->mPacketDescs;
- ioData->mBuffers[0].mDataByteSize = bytesRead;
- ioData->mBuffers[0].mData = readBuffer->mBuffers[0].mData;
-
- This->mPacketMark += readPackets;
- if (This->mClientDataFormat.mFramesPerPacket != 1) { // for PCM client formats we update in Read
- // but for non-PCM client format (weird case) we must update here/now
- if (This->mFileDataFormat.mFramesPerPacket > 0)
- This->mFrameMark += readPackets * This->mFileDataFormat.mFramesPerPacket;
- else {
- for (UInt32 i = 0; i < readPackets; ++i)
- This->mFrameMark += This->mPacketDescs[i].mVariableFramesInPacket;
- }
- }
- *ioNumberDataPackets = readPackets;
- return noErr;
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::Write(UInt32 numPackets, const AudioBufferList *data)
-{
- if (mIOBufferList.mBuffers[0].mData == NULL) {
-#if DEBUG
- printf("warning: CAAudioFile::AllocateBuffers called from WritePackets\n");
-#endif
- AllocateBuffers();
- }
-
- if (mMode == kPreparingToWrite)
- mMode = kWriting;
- else
- XThrowIf(mMode != kWriting, kExtAudioFileError_InvalidOperationOrder, "can't write to this file");
- if (mConverter != NULL) {
- mWritePackets = numPackets;
- mWriteBufferList->SetFrom(data);
- WritePacketsFromCallback(WriteInputProc, this);
- } else {
- StartTiming(this, write);
- XThrowIfError(AudioFileWritePackets(mAudioFile, mUseCache, data->mBuffers[0].mDataByteSize,
- NULL, mPacketMark, &numPackets, data->mBuffers[0].mData),
- "write audio file");
- ElapsedTime(this, write, mTicksInIO);
-#if VERBOSE_IO
- printf("CAAudioFile::WritePackets: wrote %ld packets at %qd, %ld bytes\n", numPackets, mPacketMark, data->mBuffers[0].mDataByteSize);
-#endif
- //mNumberPackets =
- mPacketMark += numPackets;
- if (mFileDataFormat.mFramesPerPacket > 0)
- mFrameMark += numPackets * mFileDataFormat.mFramesPerPacket;
- // else: shouldn't happen since we're only called when there's no converter
- }
-}
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::FlushEncoder()
-{
- if (mConverter != NULL) {
- mFinishingEncoding = true;
- WritePacketsFromCallback(WriteInputProc, this);
- mFinishingEncoding = false;
-
- // get priming info from converter, set it on the file
- if (mFileDataFormat.mBitsPerChannel == 0) {
- UInt32 propertySize;
- OSStatus err;
- AudioConverterPrimeInfo primeInfo;
- propertySize = sizeof(primeInfo);
-
- err = AudioConverterGetProperty(mConverter, kAudioConverterPrimeInfo, &propertySize, &primeInfo);
- if (err == noErr) {
- AudioFilePacketTableInfo pti;
- propertySize = sizeof(pti);
- err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti);
- if (err == noErr) {
-//printf("old packet table info: %qd valid, %ld priming, %ld remainder\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames);
- UInt64 totalFrames = pti.mNumberValidFrames + pti.mPrimingFrames + pti.mRemainderFrames;
- pti.mPrimingFrames = primeInfo.leadingFrames;
- pti.mRemainderFrames = primeInfo.trailingFrames;
- pti.mNumberValidFrames = totalFrames - pti.mPrimingFrames - pti.mRemainderFrames;
-//printf("new packet table info: %qd valid, %ld priming, %ld remainder\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames);
- XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, sizeof(pti), &pti), "couldn't set packet table info on audio file");
- }
- }
- }
- }
-}
-
-// _______________________________________________________________________________________
-//
-OSStatus CAAudioFile::WriteInputProc( AudioConverterRef /*inAudioConverter*/,
- UInt32 * ioNumberDataPackets,
- AudioBufferList* ioData,
- AudioStreamPacketDescription ** outDataPacketDescription,
- void* inUserData)
-{
- CAAudioFile *This = static_cast<CAAudioFile *>(inUserData);
- if (This->mFinishingEncoding) {
- *ioNumberDataPackets = 0;
- ioData->mBuffers[0].mDataByteSize = 0;
- ioData->mBuffers[0].mData = NULL;
- if (outDataPacketDescription)
- *outDataPacketDescription = NULL;
- return noErr;
- }
- UInt32 numPackets = This->mWritePackets;
- if (numPackets == 0) {
- return kNoMoreInputRightNow;
- }
- This->mWriteBufferList->ToAudioBufferList(ioData);
- This->mWriteBufferList->BytesConsumed(numPackets * This->mClientDataFormat.mBytesPerFrame);
- *ioNumberDataPackets = numPackets;
- if (outDataPacketDescription)
- *outDataPacketDescription = NULL;
- This->mWritePackets -= numPackets;
- return noErr;
-}
-
-// _______________________________________________________________________________________
-//
-#if VERBOSE_IO
-static void hexdump(const void *addr, long len)
-{
- const Byte *p = (Byte *)addr;
- UInt32 offset = 0;
-
- if (len > 0x400) len = 0x400;
-
- while (len > 0) {
- int n = len > 16 ? 16 : len;
- printf("%08lX: ", offset);
- for (int i = 0; i < 16; ++i)
- if (i < n)
- printf("%02X ", p[i]);
- else printf(" ");
- for (int i = 0; i < 16; ++i)
- if (i < n)
- putchar(p[i] >= ' ' && p[i] < 127 ? p[i] : '.');
- else putchar(' ');
- putchar('\n');
- p += 16;
- len -= 16;
- offset += 16;
- }
-}
-#endif
-
-// _______________________________________________________________________________________
-//
-void CAAudioFile::WritePacketsFromCallback(
- AudioConverterComplexInputDataProc inInputDataProc,
- void * inInputDataProcUserData)
-{
- while (true) {
- // keep writing until we exhaust the input (temporary stop), or produce no output (EOF)
- UInt32 numEncodedPackets = mIOBufferSizePackets;
- mIOBufferList.mBuffers[0].mDataByteSize = mIOBufferSizeBytes;
-#if CAAUDIOFILE_PROFILE
- mInConverter = true;
-#endif
- StartTiming(this, fill);
- OSStatus err = AudioConverterFillComplexBuffer(mConverter, inInputDataProc, inInputDataProcUserData,
- &numEncodedPackets, &mIOBufferList, mPacketDescs);
- ElapsedTime(this, fill, mTicksInConverter);
-#if CAAUDIOFILE_PROFILE
- mInConverter = false;
-#endif
- XThrowIf(err != 0 && err != kNoMoreInputRightNow, err, "convert audio packets (write)");
- if (numEncodedPackets == 0)
- break;
- Byte *buf = (Byte *)mIOBufferList.mBuffers[0].mData;
-#if VERBOSE_IO
- printf("CAAudioFile::WritePacketsFromCallback: wrote %ld packets, %ld bytes\n", numEncodedPackets, mIOBufferList.mBuffers[0].mDataByteSize);
- if (mPacketDescs) {
- for (UInt32 i = 0; i < numEncodedPackets; ++i) {
- printf(" write packet %qd : offset %qd, length %ld\n", mPacketMark + i, mPacketDescs[i].mStartOffset, mPacketDescs[i].mDataByteSize);
-#if VERBOSE_IO >= 2
- hexdump(buf + mPacketDescs[i].mStartOffset, mPacketDescs[i].mDataByteSize);
-#endif
- }
- }
-#endif
- StartTiming(this, write);
- XThrowIfError(AudioFileWritePackets(mAudioFile, mUseCache, mIOBufferList.mBuffers[0].mDataByteSize, mPacketDescs, mPacketMark, &numEncodedPackets, buf), "write audio file");
- ElapsedTime(this, write, mTicksInIO);
- mPacketMark += numEncodedPackets;
- //mNumberPackets += numEncodedPackets;
- if (mFileDataFormat.mFramesPerPacket > 0)
- mFrameMark += numEncodedPackets * mFileDataFormat.mFramesPerPacket;
- else {
- for (UInt32 i = 0; i < numEncodedPackets; ++i)
- mFrameMark += mPacketDescs[i].mVariableFramesInPacket;
- }
- if (err == kNoMoreInputRightNow)
- break;
- }
-}
-
-#endif // !CAAF_USE_EXTAUDIOFILE