Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #pragma once
00024
00025 #include "cinder/audio/Output.h"
00026 #include <CoreAudio/CoreAudioTypes.h>
00027 #include <AudioUnit/AudioUnit.h>
00028 #include <AudioToolbox/AUGraph.h>
00029 #include <boost/thread/mutex.hpp>
00030 #if defined( CINDER_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
00031 #include <CoreAudio/AudioHardware.h>
00032 #endif
00033 #include <stack>
00034
00035 namespace cinder { namespace audio {
00036
00037 class OutputImplAudioUnit;
00038
00039 class TargetOutputImplAudioUnit : public Target {
00040 public:
00041 static std::shared_ptr<TargetOutputImplAudioUnit> createRef( const OutputImplAudioUnit *aOutput ){ return std::shared_ptr<TargetOutputImplAudioUnit>( new TargetOutputImplAudioUnit( aOutput ) ); };
00042 ~TargetOutputImplAudioUnit() {}
00043 private:
00044 TargetOutputImplAudioUnit( const OutputImplAudioUnit *aOutput );
00045
00046
00047
00048 };
00049
00050 class OutputImplAudioUnit : public OutputImpl {
00051 public:
00052 OutputImplAudioUnit();
00053 ~OutputImplAudioUnit();
00054
00055 TrackRef addTrack( SourceRef source, bool autoplay );
00056 void removeTrack( TrackId trackId );
00057
00058 void setVolume( float aVolume );
00059 float getVolume() const;
00060
00061
00062 protected:
00063 TrackId availableTrackId() {
00064 if( mAvailableBuses.size() < 1 ) return -1;
00065 TrackId bus = mAvailableBuses.top();
00066 mAvailableBuses.pop(); return bus;
00067 }
00068 private:
00069
00070 static const uint32_t sDefaultNumberBuses;
00071 std::stack<TrackId> mAvailableBuses;
00072 uint32_t mNumberBuses;
00073 #if defined(CINDER_MAC)
00074 AudioDeviceID mOutputDeviceId;
00075 #endif
00076 AUGraph mGraph;
00077 AUNode mMixerNode;
00078 AUNode mOutputNode;
00079 AudioUnit mOutputUnit;
00080 AudioUnit mMixerUnit;
00081 AudioStreamBasicDescription * mPlayerDescription;
00082
00083 class Track : public cinder::audio::Track
00084 {
00085 public:
00086 Track( SourceRef source, OutputImplAudioUnit * output );
00087 ~Track();
00088 void play();
00089 void stop();
00090 bool isPlaying() const { return mIsPlaying; }
00091
00092 TrackId getTrackId() const { return mInputBus; }
00093
00094 void setVolume( float aVolume );
00095 float getVolume() const;
00096
00097 double getTime() const { return ( mLoader->getSampleOffset() / (double)mSource->getSampleRate() ); }
00098 void setTime( double aTime );
00099
00100 bool isLooping() const { return mIsLooping; }
00101 void setLooping( bool isLooping ) { mIsLooping = isLooping; }
00102
00103 void enablePcmBuffering( bool isBuffering ) { mIsPcmBuffering = isBuffering; }
00104 bool isPcmBuffering() { return mIsPcmBuffering; }
00105
00106 PcmBuffer32fRef getPcmBuffer();
00107 private:
00108 static OSStatus renderCallback( void * audioLoader, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData );
00109 static OSStatus renderNotifyCallback( void * audioTrack, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData );
00110
00111 void createPcmBuffer();
00112
00113 SourceRef mSource;
00114 std::shared_ptr<TargetOutputImplAudioUnit> mTarget;
00115 OutputImplAudioUnit * mOutput;
00116 TrackId mInputBus;
00117 LoaderRef mLoader;
00118 bool mIsPlaying;
00119 bool mIsLooping;
00120 bool mIsPcmBuffering;
00121
00122 PcmBuffer32fRef mLoadingPcmBuffer;
00123 PcmBuffer32fRef mLoadedPcmBuffer;
00124 boost::mutex mPcmBufferMutex;
00125 };
00126
00127 std::map<TrackId,std::shared_ptr<OutputImplAudioUnit::Track> > mTracks;
00128
00129 friend class TargetOutputImplAudioUnit;
00130 };
00131
00132 }}