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