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/Buffer.h" 00028 00029 #include <map> 00030 #include <string> 00031 00032 #if defined(CINDER_MAC) 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 Loader> LoaderRef; 00043 00044 class Io { 00045 public: 00046 typedef enum DataType { UINT8, INT8, UINT16, INT16, UINT32, INT32, FLOAT32, DATA_UNKNOWN } DataType; 00047 00049 int32_t getSampleRate() const { return mSampleRate; } 00051 int16_t getChannelCount() const { return mChannelCount; } 00053 int16_t getBitsPerSample() const { return mBitsPerSample; } 00055 int16_t getBlockAlign() const { return mBlockAlign; } 00057 DataType getDataType() const { return mDataType; } 00059 bool isInterleaved() const { return mIsInterleaved; } 00061 bool isPcm() const { return mIsPcm; } 00063 bool isFloat() const { return ( mDataType == FLOAT32 ); } 00065 bool isBigEndian() const { return mIsBigEndian; } 00066 00067 protected: 00068 #if defined(CINDER_COCOA) 00069 static void loadFromCaAudioStreamBasicDescription( Io * anIo, const AudioStreamBasicDescription * audioDescription ); 00070 #endif 00071 Io() 00072 : mSampleRate( 0 ), mChannelCount( 0 ), mBitsPerSample( 0 ), mBlockAlign( 0 ), mDataType( DATA_UNKNOWN ), 00073 mIsInterleaved( true ), mIsPcm( false ), mIsBigEndian( false ) 00074 {} 00075 00076 int32_t mSampleRate; 00077 int16_t mChannelCount; 00078 int16_t mBitsPerSample; //Significant Bits Per Sample 00079 int16_t mBlockAlign; //BytesPerSample 00080 DataType mDataType; 00081 bool mIsInterleaved; 00082 bool mIsPcm; 00083 bool mIsBigEndian; 00084 00085 #if defined(CINDER_COCOA) 00086 //TODO: fix this 00087 uint32_t mNativeFormatId; 00088 uint32_t mNativeFormatFlags; 00089 uint32_t mBytesPerPacket; 00090 uint32_t mFramesPerPacket; 00091 uint32_t mBytesPerFrame; 00092 #endif 00093 }; 00094 00095 class Target : public Io { 00096 public: 00097 virtual ~Target() {} 00098 protected: 00099 Target() {} 00100 }; 00101 00102 class Source : public Io { 00103 public: 00104 virtual ~Source() {} 00105 virtual LoaderRef getLoader( Target *target ) { return LoaderRef(); } 00106 00107 virtual double getDuration() const = 0; 00108 protected: 00109 00110 }; 00111 00112 #if defined(CINDER_MSW) 00113 typedef HRESULT (*LoaderDataCallback)( void * audioData, uint32_t dataSize, void * track, uint64_t sampleTime, uint32_t sampleDuration ); 00114 #endif 00115 00116 class Loader { 00117 public: 00118 virtual ~Loader() {} 00119 virtual uint32_t getOptimalBufferSize() const { return 0; }; 00120 00121 virtual void loadData( uint32_t *ioSampleCount, BufferList *ioData ) = 0; 00122 virtual uint64_t getSampleOffset() const = 0; 00123 virtual void setSampleOffset( uint64_t anOffset ) = 0; 00124 protected: 00125 #if defined(CINDER_COCOA) 00126 static void fillBufferListFromCaBufferList( BufferList * aBufferList, const AudioBufferList * caBufferList ); 00127 static shared_ptr<AudioBufferList> createCaBufferList( const BufferList * caBufferList ); 00128 #endif 00129 00130 Loader() {} 00131 }; 00132 00133 struct IoRegistrar { 00134 typedef SourceRef (*SourceCreationFunc)( DataSourceRef ); 00135 00136 static SourceRef createSource( DataSourceRef dataSource, std::string extension ); 00137 00138 static void registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority = 2 ); 00139 00140 private: 00141 00142 struct Inst { 00143 void registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority ); 00144 00145 SourceRef createSource( DataSourceRef dataSource, std::string extension ); 00146 00147 std::map<std::string, std::multimap<int32_t,SourceCreationFunc> > mSources; 00148 std::map<int32_t, SourceCreationFunc> mGenericSources; 00149 }; 00150 00151 static IoRegistrar::Inst* instance(); 00152 00153 friend class Io; 00154 }; 00155 00157 SourceRef load( const std::string &path, std::string extension = "" ); 00159 SourceRef load( DataSourceRef dataSource, std::string extension = "" ); 00160 00161 template<typename T> 00162 struct IoRegistrant { 00163 IoRegistrant() { 00164 (void) register_object; 00165 } 00166 private: 00167 struct exec_register { 00168 exec_register() { 00169 T::registerSelf(); 00170 } 00171 }; 00172 00173 static exec_register register_object; 00174 }; 00175 00176 template<typename D> typename IoRegistrant<D>::exec_register IoRegistrant<D>::register_object; 00177 00178 #define REGISTER_AUDIOIO( TYPE ) \ 00179 struct IoRegisterT##TYPE : public IoRegistrant<TYPE> { \ 00180 IoRegisterT##TYPE() : IoRegistrant<TYPE>() {} \ 00181 }; 00182 00183 }} // namespace 00184