diff options
Diffstat (limited to 'libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h')
-rw-r--r-- | libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h new file mode 100644 index 0000000000..f1aa56fb5e --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h @@ -0,0 +1,300 @@ +/* + File: CAExtAudioFile.h + Abstract: Part of CoreAudio Utility Classes + Version: 1.1 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2014 Apple Inc. All Rights Reserved. + +*/ +#ifndef __CAExtAudioFile_h__ +#define __CAExtAudioFile_h__ + +#include <TargetConditionals.h> + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioToolbox/ExtendedAudioFile.h> + #include <AudioToolbox/AudioConverter.h> +#else + #include "ExtendedAudioFile.h" + #include "AudioConverter.h" +#endif +#include "CAXException.h" +//#include "CAAutoDisposer.h" +#include "CAStreamBasicDescription.h" +#include "CAAudioChannelLayout.h" +#include "CACFObject.h" + +// A C++ wrapper for ExtAudioFile +// Error returns throw CAXExceptions. +class CAExtAudioFile { +public: + // instances are not automatically associated with open files. + CAExtAudioFile() : + mExtAudioFile(NULL) { } + + virtual ~CAExtAudioFile() + { + Close(); + } + + bool IsValid() const { return mExtAudioFile != NULL; } + + void Open(const char* filename) + { + Close(); + CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)filename, strlen(filename), false); + XThrowIf(!url, -1, "couldn't convert path to CFURLRef"); + OSStatus res = ExtAudioFileOpenURL(url, &mExtAudioFile); + if (res) + CFRelease(url); + Check(res, "ExtAudioFileOpenURL"); + CFRelease (url); + } + + // this group of methods maps directly to the API other than OSStatus results translating into exceptions. + // you must explicitly open, wrap or create a file. + void OpenURL(CFURLRef url) + { + Close(); + Check(ExtAudioFileOpenURL(url, &mExtAudioFile), "ExtAudioFileOpenURL"); + } + + void WrapAudioFileID(AudioFileID inFileID, Boolean forWriting) + { + Close(); + Check(ExtAudioFileWrapAudioFileID(inFileID, forWriting, &mExtAudioFile), "ExtAudioFileWrapAudioFileID"); + } + + void Create(const char *filePath, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags) + { + CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)filePath, strlen(filePath), false); + XThrowIf(!url, -1, "couldn't convert path to CFURLRef"); + Close(); + OSStatus res = ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile); + if (res) + CFRelease(url); + Check(res, "ExtAudioFileCreateWithURL"); + CFRelease(url); + } + + void CreateWithURL(CFURLRef url, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags) + { + Close(); + Check(ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile), "ExtAudioFileCreateWithURL"); + } + + // you may explicitly close a file, or have it closed automatically by the destructor. + void Close() + { + if (mExtAudioFile != NULL) { + Check(ExtAudioFileDispose(mExtAudioFile), "ExtAudioFileClose"); + mExtAudioFile = NULL; + } + } + + void Read(UInt32 &ioNumberFrames, AudioBufferList *ioData) + { + Check(ExtAudioFileRead(mExtAudioFile, &ioNumberFrames, ioData), "ExtAudioFileRead"); + } + + OSStatus Write(UInt32 inNumberFrames, const AudioBufferList *ioData) + { + OSStatus err = ExtAudioFileWrite(mExtAudioFile, inNumberFrames, ioData); + switch (err) { + // noErr and certain special errors are returned without an exception + case noErr: + break; + #if TARGET_OS_IPHONE + case kExtAudioFileError_CodecUnavailableInputConsumed: + case kExtAudioFileError_CodecUnavailableInputNotConsumed: + break; + #endif + default: + // throw an exception + Check(err, "ExtAudioFileWrite"); + break; + } + return err; + } + + void WriteAsync(UInt32 inNumberFrames, const AudioBufferList *ioData) + { + Check(ExtAudioFileWriteAsync(mExtAudioFile, inNumberFrames, ioData), "ExtAudioFileWriteAsync"); + } + + void Seek(SInt64 inFrameOffset) + { + Check(ExtAudioFileSeek(mExtAudioFile, inFrameOffset), "ExtAudioFileSeek"); + } + + SInt64 Tell() const + { + SInt64 pos; + Check(ExtAudioFileTell(mExtAudioFile, &pos), "ExtAudioFileTell"); + return pos; + } + + UInt32 GetPropertyInfo(ExtAudioFilePropertyID propid, Boolean *outWritable) const + { + UInt32 size; + CheckProperty(ExtAudioFileGetPropertyInfo(mExtAudioFile, propid, &size, outWritable), "ExtAudioFileGetPropertyInfo", propid); + return size; + } + + void GetProperty(ExtAudioFilePropertyID propid, UInt32 &ioSize, void *outData) const + { + CheckProperty(ExtAudioFileGetProperty(mExtAudioFile, propid, &ioSize, outData), "ExtAudioFileGetProperty", propid); + } + + void SetProperty(ExtAudioFilePropertyID propid, UInt32 size, const void *inData) + { + CheckProperty(ExtAudioFileSetProperty(mExtAudioFile, propid, size, inData), "ExtAudioFileSetProperty", propid); + } + + const CAAudioChannelLayout &GetFileChannelLayout() + { + return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout); + } + + void SetFileChannelLayout(const CAAudioChannelLayout &layout) { + SetProperty(kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()); + } + + const CAStreamBasicDescription &GetFileDataFormat() + { + UInt32 size = sizeof(mFileDataFormat); + GetProperty(kExtAudioFileProperty_FileDataFormat, size, &mFileDataFormat); + return mFileDataFormat; + } + + const CAStreamBasicDescription &GetClientDataFormat() { + UInt32 size = sizeof(mClientDataFormat); + GetProperty(kExtAudioFileProperty_ClientDataFormat, size, &mClientDataFormat); + return mClientDataFormat; + } + + + void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL, UInt32 codecManuf=0) { + if (codecManuf != 0) + SetProperty('cman' /*kExtAudioFileProperty_CodecManufacturer*/, sizeof(codecManuf), &codecManuf); + SetProperty(kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat); + if (layout) + SetClientChannelLayout(*layout); + } + + void SetClientChannelLayout(const CAAudioChannelLayout &layout) { + SetProperty(kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()); + } + + AudioConverterRef GetConverter() const { + UInt32 size = sizeof(AudioConverterRef); + AudioConverterRef converter = NULL; + GetProperty(kExtAudioFileProperty_AudioConverter, size, &converter); + return converter; + } + + bool HasConverter() const { return GetConverter() != NULL; } + + OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false) + { + OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData); + if (!inCanFail) + XThrowIfError(err, "Couldn't set audio converter property"); + if (!err) { + // must tell the file that we have changed the converter; a NULL converter config is sufficient + CFPropertyListRef config = NULL; + SetProperty(kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config); + } + return err; + } + + SInt64 GetNumberFrames() { + SInt64 length; + UInt32 size = sizeof(SInt64); + GetProperty(kExtAudioFileProperty_FileLengthFrames, size, &length); + return length; + } + + +protected: + virtual void Check(OSStatus err, const char *func) const + { + if (err) { + char txt[128]; + snprintf(txt, sizeof(txt), "%s failed", func); + throw CAXException(txt, err); + } + } + + virtual void CheckProperty(OSStatus err, const char *func, UInt32 propid) const + { + if (err) { + char txt[128]; + char propstr[] = CA4CCToCString(propid); + snprintf(txt, sizeof(txt), "%s ('%s') failed", func, propstr); + throw CAXException(txt, err); + } + } + + const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) { + UInt32 size = GetPropertyInfo(propID, NULL); + CAAutoFree<AudioChannelLayout> layout; + layout.allocBytes(size); + GetProperty(propID, size, layout); + layoutObj = layout; + return layoutObj; + } + +private: + CAExtAudioFile(const CAExtAudioFile &) { } // prohibit + CAExtAudioFile & operator = (const CAExtAudioFile &) { return *this; } // prohibit + +private: + ExtAudioFileRef mExtAudioFile; + + // for convenience to the client, it helps if we hold onto some storage for these + CAStreamBasicDescription mFileDataFormat; + CAAudioChannelLayout mFileChannelLayout; + CAStreamBasicDescription mClientDataFormat; +}; + + +#endif // __CAExtAudioFile_h__ |