Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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