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 #undef min 00037 #undef max 00038 #include <mmsystem.h> 00039 #endif 00040 00041 namespace cinder { namespace audio { 00042 00043 typedef std::shared_ptr<class Source> SourceRef; 00044 typedef std::shared_ptr<class Target> TargetRef; 00045 typedef std::shared_ptr<class Loader> LoaderRef; 00046 00047 class Io { 00048 public: 00049 typedef enum DataType { UINT8, INT8, UINT16, INT16, UINT32, INT32, FLOAT32, DATA_UNKNOWN } DataType; 00050 00052 int32_t getSampleRate() const { return mSampleRate; } 00054 int16_t getChannelCount() const { return mChannelCount; } 00056 int16_t getBitsPerSample() const { return mBitsPerSample; } 00058 int16_t getBlockAlign() const { return mBlockAlign; } 00060 DataType getDataType() const { return mDataType; } 00062 bool isInterleaved() const { return mIsInterleaved; } 00064 bool isPcm() const { return mIsPcm; } 00066 bool isFloat() const { return ( mDataType == FLOAT32 ); } 00068 bool isBigEndian() const { return mIsBigEndian; } 00069 00070 protected: 00071 #if defined(CINDER_COCOA) 00072 static void loadFromCaAudioStreamBasicDescription( Io * anIo, const AudioStreamBasicDescription * audioDescription ); 00073 #endif 00074 Io() 00075 : mSampleRate( 0 ), mChannelCount( 0 ), mBitsPerSample( 0 ), mBlockAlign( 0 ), mDataType( DATA_UNKNOWN ), 00076 mIsInterleaved( true ), mIsPcm( false ), mIsBigEndian( false ) 00077 {} 00078 00079 int32_t mSampleRate; 00080 int16_t mChannelCount; 00081 int16_t mBitsPerSample; //Significant Bits Per Sample 00082 int16_t mBlockAlign; //BytesPerSample 00083 DataType mDataType; 00084 bool mIsInterleaved; 00085 bool mIsPcm; 00086 bool mIsBigEndian; 00087 00088 #if defined(CINDER_COCOA) 00089 //TODO: fix this 00090 uint32_t mNativeFormatId; 00091 uint32_t mNativeFormatFlags; 00092 uint32_t mBytesPerPacket; 00093 uint32_t mFramesPerPacket; 00094 uint32_t mBytesPerFrame; 00095 #endif 00096 }; 00097 00098 class Target : public Io { 00099 public: 00100 virtual ~Target() {} 00101 protected: 00102 Target() {} 00103 }; 00104 00105 class Source : public Io { 00106 public: 00107 virtual ~Source() {} 00108 virtual LoaderRef createLoader( Target *target ) { return LoaderRef(); } 00109 00110 virtual double getDuration() const = 0; 00111 protected: 00112 00113 }; 00114 00115 #if defined(CINDER_MSW) 00116 typedef HRESULT (*LoaderDataCallback)( void * audioData, uint32_t dataSize, void * track, uint64_t sampleTime, uint32_t sampleDuration ); 00117 #endif 00118 00119 class Loader { 00120 public: 00121 virtual ~Loader() {} 00122 virtual uint32_t getOptimalBufferSize() const { return 0; }; 00123 00124 virtual void loadData( BufferList *ioData ) = 0; 00125 virtual uint64_t getSampleOffset() const = 0; 00126 virtual void setSampleOffset( uint64_t anOffset ) = 0; 00127 protected: 00128 #if defined(CINDER_COCOA) 00129 static void fillBufferListFromCaBufferList( BufferList * aBufferList, const AudioBufferList * caBufferList ); 00130 static std::shared_ptr<AudioBufferList> createCaBufferList( const BufferList * caBufferList ); 00131 #endif 00132 00133 Loader() {} 00134 }; 00135 00136 class IoException : public Exception { 00137 }; 00138 00139 class IoExceptionFailedLoad : public IoException { 00140 }; 00141 00142 class IoExceptionSourceNotFound : public IoExceptionFailedLoad { 00143 }; 00144 00145 class IoExceptionUnsupportedDataType : public IoException { 00146 }; 00147 00148 class IoExceptionUnsupportedDataFormat : public IoException { 00149 }; 00150 00151 struct IoRegistrar { 00152 typedef SourceRef (*SourceCreationFunc)( DataSourceRef ); 00153 00154 static SourceRef createSource( DataSourceRef dataSource, std::string extension ); 00155 00156 static void registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority = 2 ); 00157 static void registerSourceGeneric( SourceCreationFunc func, int32_t priority = 2 ); 00158 00159 private: 00160 00161 struct Inst { 00162 void registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority ); 00163 void registerSourceGeneric( SourceCreationFunc func, int32_t priority ); 00164 00165 SourceRef createSource( DataSourceRef dataSource, std::string extension ); 00166 00167 std::map<std::string, std::multimap<int32_t,SourceCreationFunc> > mSources; 00168 std::map<int32_t, SourceCreationFunc> mGenericSources; 00169 }; 00170 00171 static IoRegistrar::Inst* instance(); 00172 00173 friend class Io; 00174 }; 00175 00177 SourceRef load( const std::string &path, std::string extension = "" ); 00179 SourceRef load( DataSourceRef dataSource, std::string extension = "" ); 00180 00181 template<typename T> 00182 struct IoRegistrant { 00183 IoRegistrant() { 00184 (void) register_object; 00185 } 00186 private: 00187 struct exec_register { 00188 exec_register() { 00189 T::registerSelf(); 00190 } 00191 }; 00192 00193 static exec_register register_object; 00194 }; 00195 00196 template<typename D> typename IoRegistrant<D>::exec_register IoRegistrant<D>::register_object; 00197 00198 #define REGISTER_AUDIOIO( TYPE ) \ 00199 struct IoRegisterT##TYPE : public IoRegistrant<TYPE> { \ 00200 IoRegisterT##TYPE() : IoRegistrant<TYPE>() {} \ 00201 }; 00202 00203 }} // namespace 00204