include/cinder/audio/OutputImplXAudio.h
Go to the documentation of this file.
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/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 { /*TODO*/ return 0.0; }
00058 
00059     //TargetRef getTarget();
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         //static ::HRESULT              dataInputCallback( void * audioData, uint32_t dataSize, void * theTrack, uint64_t sampleTime, uint32_t sampleDuration );
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             //HANDLE                            mBufferEndEvent;
00122             OutputImplXAudio::Track             * mTrack;
00123                 
00124             SourceCallback()
00125                 /*: mBufferEndEvent( CreateEvent( NULL, FALSE, FALSE, NULL ) )*/{}
00126             ~SourceCallback(){ /*CloseHandle( mBufferEndEvent );*/ }
00127             void STDMETHODCALLTYPE OnBufferEnd( void* pvContext ) {
00128                 SetEvent( mTrack->mBufferEndEvent );
00129             }
00130 
00131             //Unused methods are stubs
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 }} //namespaces