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 "cinder/msw/CinderMSW.h"
00027 #include "cinder/CinderMath.h"
00028 #include "cinder/audio/FftProcessor.h"
00029
00030 #include <windows.h>
00031 #undef min
00032 #undef max
00033 #include <xaudio2.h>
00034 #include <boost/thread/thread.hpp>
00035 #include <boost/thread/mutex.hpp>
00036
00037 namespace cinder { namespace audio {
00038
00039 class OutputImplXAudio;
00040
00041 class TargetOutputImplXAudio : public Target {
00042 public:
00043 static std::shared_ptr<TargetOutputImplXAudio> createRef( const WAVEFORMATEX *aOutDescription ){ return std::shared_ptr<TargetOutputImplXAudio>( new TargetOutputImplXAudio( aOutDescription ) ); }
00044 ~TargetOutputImplXAudio() {}
00045 private:
00046 TargetOutputImplXAudio( const WAVEFORMATEX *aOutDescription );
00047 };
00048
00049 class OutputImplXAudio : public OutputImpl
00050 {
00051 public:
00052 OutputImplXAudio();
00053 ~OutputImplXAudio();
00054 TrackRef addTrack( SourceRef aSource, bool autoplay );
00055 void removeTrack( TrackId );
00056
00057 void setVolume( float aVolume ) {}
00058 float getVolume() const { return 0.0; }
00059
00060
00061 protected:
00062 ::IXAudio2 * mXAudio;
00063 ::IXAudio2MasteringVoice * mMasterVoice;
00064
00065 class Track : public cinder::audio::Track
00066 {
00067 public:
00068 Track( SourceRef source, OutputImplXAudio * output );
00069 ~Track();
00070 void play();
00071 void stop();
00072 bool isPlaying() const { return mIsPlaying; }
00073
00074 TrackId getTrackId() const { return mTrackId; }
00075
00076 void setVolume( float aVolume );
00077 float getVolume() const;
00078
00079 double getTime() const { return mLoader->getSampleOffset() / mVoiceDescription.nChannels / (double)mVoiceDescription.nSamplesPerSec; }
00080 void setTime( double aTime ) { mLoader->setSampleOffset( aTime * mVoiceDescription.nSamplesPerSec * mVoiceDescription.nChannels ); }
00081
00082 void setLooping( bool isLooping ) { mIsLooping = isLooping; }
00083 bool isLooping() const { return mIsLooping; }
00084
00085 void enablePcmBuffering( bool isBuffering ) { mIsPcmBuffering = isBuffering; }
00086 bool isPcmBuffering() { return mIsPcmBuffering; }
00087
00088 PcmBuffer32fRef getPcmBuffer();
00089 private:
00090
00091 void fillBuffer();
00092
00093 static const int sMaxBufferCount = 3;
00094
00095 bool mIsLooping;
00096 bool mIsPlaying;
00097 TrackId mTrackId;
00098 SourceRef mSource;
00099 LoaderRef mLoader;
00100 OutputImplXAudio * mOutput;
00101
00102 IXAudio2SourceVoice * mSourceVoice;
00103 WAVEFORMATEX mVoiceDescription;
00104 uint8_t * mDecodedBuffers;
00105
00106 uint32_t mBufferSize;
00107 uint32_t mSamplesPerBuffer;
00108 uint32_t mCurrentBuffer;
00109 uint64_t mCurrentTime;
00110
00111 HANDLE mBufferEndEvent;
00112 std::shared_ptr<boost::thread> mQueueThread;
00113
00114 bool mIsPcmBuffering;
00115 PcmBuffer32fRef mLoadingPcmBuffer;
00116 PcmBuffer32fRef mLoadedPcmBuffer;
00117 boost::mutex mPcmBufferMutex;
00118
00119 class SourceCallback : public IXAudio2VoiceCallback
00120 {
00121 public:
00122
00123 OutputImplXAudio::Track * mTrack;
00124
00125 SourceCallback()
00126 {}
00127 ~SourceCallback(){ }
00128 void STDMETHODCALLTYPE OnBufferEnd( void* pvContext ) {
00129 SetEvent( mTrack->mBufferEndEvent );
00130 }
00131
00132
00133 void STDMETHODCALLTYPE OnStreamEnd() {}
00134 void STDMETHODCALLTYPE OnVoiceProcessingPassEnd() { }
00135 void STDMETHODCALLTYPE OnVoiceProcessingPassStart(UINT32 SamplesRequired) { }
00136 void STDMETHODCALLTYPE OnBufferStart(void * pBufferContext) { }
00137 void STDMETHODCALLTYPE OnLoopEnd(void * pBufferContext) { }
00138 void STDMETHODCALLTYPE OnVoiceError(void * pBufferContext, HRESULT Error) { }
00139 };
00140
00141 SourceCallback mVoiceCallback;
00142 };
00143
00144 std::map<TrackId,std::shared_ptr<OutputImplXAudio::Track> > mTracks;
00145 };
00146
00147 }}