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 
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 { /*TODO*/ return 0.0; }
00059 
00060     //TargetRef getTarget();
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         //static ::HRESULT              dataInputCallback( void * audioData, uint32_t dataSize, void * theTrack, uint64_t sampleTime, uint32_t sampleDuration );
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             //HANDLE                            mBufferEndEvent;
00123             OutputImplXAudio::Track             * mTrack;
00124                 
00125             SourceCallback()
00126                 /*: mBufferEndEvent( CreateEvent( NULL, FALSE, FALSE, NULL ) )*/{}
00127             ~SourceCallback(){ /*CloseHandle( mBufferEndEvent );*/ }
00128             void STDMETHODCALLTYPE OnBufferEnd( void* pvContext ) {
00129                 SetEvent( mTrack->mBufferEndEvent );
00130             }
00131 
00132             //Unused methods are stubs
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 }} //namespaces