00001 /* 00002 Copyright (c) 2009, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include "cinder/Cinder.h" 00026 #include "cinder/DataSource.h" 00027 #include "cinder/audio/PcmBuffer.h" 00028 00029 #include <map> 00030 #include <string> 00031 00032 #if defined(CINDER_COCOA) 00033 #include <AudioToolbox/AudioFile.h> 00034 #elif defined(CINDER_MSW) 00035 #include <windows.h> 00036 #include <mmsystem.h> 00037 #endif 00038 00039 namespace cinder { namespace audio { 00040 00041 typedef shared_ptr<class Source> SourceRef; 00042 typedef shared_ptr<class Target> TargetRef; 00043 typedef shared_ptr<class Loader> LoaderRef; 00044 00045 class Io { 00046 public: 00047 typedef enum DataType { UINT8, INT8, UINT16, INT16, UINT32, INT32, FLOAT32, DATA_UNKNOWN } DataType; 00048 00050 int32_t getSampleRate() const { return mSampleRate; } 00052 int16_t getChannelCount() const { return mChannelCount; } 00054 int16_t getBitsPerSample() const { return mBitsPerSample; } 00056 int16_t getBlockAlign() const { return mBlockAlign; } 00058 DataType getDataType() const { return mDataType; } 00060 bool isInterleaved() const { return mIsInterleaved; } 00062 bool isPcm() const { return mIsPcm; } 00064 bool isFloat() const { return ( mDataType == FLOAT32 ); } 00066 bool isBigEndian() const { return mIsBigEndian; } 00067 00068 protected: 00069 #if defined(CINDER_COCOA) 00070 static void loadFromCaAudioStreamBasicDescription( Io * anIo, const AudioStreamBasicDescription * audioDescription ); 00071 #endif 00072 Io() 00073 : mSampleRate( 0 ), mChannelCount( 0 ), mBitsPerSample( 0 ), mBlockAlign( 0 ), mDataType( DATA_UNKNOWN ), 00074 mIsInterleaved( true ), mIsPcm( false ), mIsBigEndian( false ) 00075 {} 00076 00077 int32_t mSampleRate; 00078 int16_t mChannelCount; 00079 int16_t mBitsPerSample; //Significant Bits Per Sample 00080 int16_t mBlockAlign; //BytesPerSample 00081 DataType mDataType; 00082 bool mIsInterleaved; 00083 bool mIsPcm; 00084 bool mIsBigEndian; 00085 00086 #if defined(CINDER_COCOA) 00087 //TODO: fix this 00088 uint32_t mNativeFormatId; 00089 uint32_t mNativeFormatFlags; 00090 uint32_t mBytesPerPacket; 00091 uint32_t mFramesPerPacket; 00092 uint32_t mBytesPerFrame; 00093 #endif 00094 }; 00095 00096 class Target : public Io { 00097 public: 00098 virtual ~Target() {} 00099 protected: 00100 Target() {} 00101 }; 00102 00103 class Source : public Io { 00104 public: 00105 virtual ~Source() {} 00106 virtual LoaderRef createLoader( Target *target ) { return LoaderRef(); } 00107 00108 virtual double getDuration() const = 0; 00109 protected: 00110 00111 }; 00112 00113 #if defined(CINDER_MSW) 00114 typedef HRESULT (*LoaderDataCallback)( void * audioData, uint32_t dataSize, void * track, uint64_t sampleTime, uint32_t sampleDuration ); 00115 #endif 00116 00117 class Loader { 00118 public: 00119 virtual ~Loader() {} 00120 virtual uint32_t getOptimalBufferSize() const { return 0; }; 00121 00122 virtual void loadData( BufferList *ioData ) = 0; 00123 virtual uint64_t getSampleOffset() const = 0; 00124 virtual void setSampleOffset( uint64_t anOffset ) = 0; 00125 protected: 00126 #if defined(CINDER_COCOA) 00127 static void fillBufferListFromCaBufferList( BufferList * aBufferList, const AudioBufferList * caBufferList ); 00128 static shared_ptr<AudioBufferList> createCaBufferList( const BufferList * caBufferList ); 00129 #endif 00130 00131 Loader() {} 00132 }; 00133 00134 class IoException : public Exception { 00135 }; 00136 00137 class IoExceptionFailedLoad : public IoException { 00138 }; 00139 00140 class IoExceptionSourceNotFound : public IoExceptionFailedLoad { 00141 }; 00142 00143 class IoExceptionUnsupportedDataType : public IoException { 00144 }; 00145 00146 class IoExceptionUnsupportedDataFormat : public IoException { 00147 }; 00148 00149 struct IoRegistrar { 00150 typedef SourceRef (*SourceCreationFunc)( DataSourceRef ); 00151 00152 static SourceRef createSource( DataSourceRef dataSource, std::string extension ); 00153 00154 static void registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority = 2 ); 00155 static void registerSourceGeneric( SourceCreationFunc func, int32_t priority = 2 ); 00156 00157 private: 00158 00159 struct Inst { 00160 void registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority ); 00161 void registerSourceGeneric( SourceCreationFunc func, int32_t priority ); 00162 00163 SourceRef createSource( DataSourceRef dataSource, std::string extension ); 00164 00165 std::map<std::string, std::multimap<int32_t,SourceCreationFunc> > mSources; 00166 std::map<int32_t, SourceCreationFunc> mGenericSources; 00167 }; 00168 00169 static IoRegistrar::Inst* instance(); 00170 00171 friend class Io; 00172 }; 00173 00175 SourceRef load( const std::string &path, std::string extension = "" ); 00177 SourceRef load( DataSourceRef dataSource, std::string extension = "" ); 00178 00179 template<typename T> 00180 struct IoRegistrant { 00181 IoRegistrant() { 00182 (void) register_object; 00183 } 00184 private: 00185 struct exec_register { 00186 exec_register() { 00187 T::registerSelf(); 00188 } 00189 }; 00190 00191 static exec_register register_object; 00192 }; 00193 00194 template<typename D> typename IoRegistrant<D>::exec_register IoRegistrant<D>::register_object; 00195 00196 #define REGISTER_AUDIOIO( TYPE ) \ 00197 struct IoRegisterT##TYPE : public IoRegistrant<TYPE> { \ 00198 IoRegisterT##TYPE() : IoRegistrant<TYPE>() {} \ 00199 }; 00200 00201 }} // namespace 00202