sfxBuffer.h

Engine/source/sfx/sfxBuffer.h

More...

Classes:

class

The buffer interface hides the details of how the device holds sound data for playback.

class

Encapsulates the async I/O state of the sound buffer.

Namespaces:

namespace

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _SFXBUFFER_H_
 25#define _SFXBUFFER_H_
 26
 27#ifndef _REFBASE_H_
 28#include "core/util/refBase.h"
 29#endif
 30
 31#ifndef _TSIGNAL_H_
 32#include "core/util/tSignal.h"
 33#endif
 34
 35#ifndef _TSTREAM_H_
 36#include "core/stream/tStream.h"
 37#endif
 38
 39#ifndef _SFXCOMMON_H_
 40#include "sfx/sfxCommon.h"
 41#endif
 42
 43#ifndef _THREADSAFEREFCOUNT_H_
 44#include "platform/threads/threadSafeRefCount.h"
 45#endif
 46
 47
 48class SFXStream;
 49class SFXDescription;
 50class SFXVoice;
 51
 52namespace SFXInternal {
 53   class SFXStreamPacket;
 54   class SFXAsyncStream;
 55   class SFXAsyncQueue;
 56   void PurgeDeadBuffers();
 57}
 58
 59
 60/// The buffer interface hides the details of how the device holds sound data for playback.
 61///
 62/// A sound buffer may either be loaded once completely and then played as needed or it may
 63/// be progressively streamed from an SFXStream.  In the latter case, there can only be a single
 64/// voice tied to the buffer.
 65///
 66/// @note SFXDevice is the last instance when it comes to ownership
 67///   of SFXBuffers.  If the SFXDevice goes away, it will take all
 68///   SFXBuffers with it, regardless of whether there are still strong
 69///   refs to it.  Use StrongWeakRefPtrs to keep pointers to
 70///   SFXBuffers!
 71///
 72/// @see SFXStream
 73class SFXBuffer :    public StrongRefBase,
 74                     public IPolled, // SFXBuffers are periodically updated on the SFX thread.
 75                     public IOutputStream< SFXInternal::SFXStreamPacket* > // Interface for writing sound data to the buffer.
 76{
 77      friend class SFXVoice; // mUniqueVoice
 78      friend void SFXInternal::PurgeDeadBuffers(); // dtor
 79
 80   public:
 81
 82      typedef void Parent;
 83
 84      /// Status indicators for sound buffers.
 85      enum Status
 86      {
 87         STATUS_Null,      ///< Initial state.
 88         STATUS_Loading,   ///< Buffer has requested data and is waiting for queue to fill up.
 89         STATUS_Ready,     ///< Playback queue is fed and ready (non-stream buffers will stop at this state).
 90         STATUS_Blocked,   ///< Queue is starved and playback thus held until further data is available (streaming buffers only).
 91         STATUS_AtEnd,     ///< Buffer has read all its streaming data (streaming buffers only).
 92      };
 93
 94      /// This signal is triggered from SFXBuffer's destructor so the sound system
 95      /// can keep track of buffers being released on the device.
 96      static Signal< void( SFXBuffer* ) > smBufferDestroyedSignal;
 97
 98   protected:
 99
100      typedef ThreadSafeRef< SFXInternal::SFXAsyncStream> SFXAsyncStreamPtr;
101      typedef SFXInternal::SFXAsyncQueue* SFXAsyncQueuePtr;
102
103      /// Encapsulates the async I/O state of the sound buffer.
104      struct AsyncState : public ThreadSafeRefCount< AsyncState >
105      {
106         /// The sound packet stream.
107         SFXAsyncStreamPtr mStream;
108
109         /// The packet queue that feeds into the actual device buffer.
110         /// Only used for streaming buffers; non-streaming buffers directly receive
111         /// and upload sound packets without queuing.
112         SFXAsyncQueuePtr mQueue;
113
114         AsyncState();
115         AsyncState( SFXInternal::SFXAsyncStream* stream );
116         ~AsyncState();
117      };
118
119      typedef ThreadSafeRef< AsyncState> AsyncStatePtr;
120
121      /// Create a new buffer from @a stream using the parameters in @a description.
122      ///
123      /// @param stream Sound stream from which to read sound data into the buffer.
124      /// @param description Sound setup description.
125      /// @param createAsyncState If true, the asynchronous loading state for the buffer will be set up
126      ///   in the constructor.  This is mainly useful for the null device which creates dummy buffers that
127      ///   do not need the async state to be in place.  All other buffers do.
128      SFXBuffer( const ThreadSafeRef< SFXStream>& stream, SFXDescription* description, bool createAsyncState = true );
129      
130      /// Create a buffer with just a description.  This is used by devices who fully take over loading
131      /// and streaming.
132      SFXBuffer( SFXDescription* description );
133      
134      virtual ~SFXBuffer();
135
136      /// The buffer readiness status.
137      Status mStatus;
138      
139      /// The sound sample format used by the buffer.
140      SFXFormat mFormat;
141
142      /// Total playback time of the associated sound stream in milliseconds.
143      /// @note For streaming buffers, this will not correspond to the actual
144      ///   playtime of the device buffer.
145      U32 mDuration;
146
147      /// If true, this is a continuously streaming buffer.
148      bool mIsStreaming;
149      
150      /// For streaming buffers, tells whether the source stream loops.
151      bool mIsLooping;
152
153      /// If true, this buffer can only have a single SFXVoice attached.
154      bool mIsUnique;
155
156      /// If true, the buffer is dead and will be deleted.  Can't be in status
157      /// for synchronization reasons.
158      bool mIsDead;
159
160      /// Pointer to structure keeping the asynchronous I/O state of the buffer.
161      /// For non-streaming buffers, this is released as soon as all data is loaded.
162      ///
163      /// To allow seeking in streaming buffers even after playback has ended,
164      /// we do not release the async state of these buffers until the buffer is
165      /// actually released itself.  This allows to always access the associated
166      /// input stream.
167      ///
168      /// @note For devices that handle loading/streaming on their own, this will
169      ///   not be set.
170      AsyncStatePtr mAsyncState;
171
172      /// If this is a unique buffer (i.e. a streaming buffer), then this holds
173      /// the reference to the unique voice.
174      StrongWeakRefPtr< SFXVoice> mUniqueVoice;
175
176      /// Set the buffer status and trigger mOnStatusChange if the status changes.
177      /// @note Called on both the SFX update thread and the main thread.
178      void _setStatus( Status status );
179
180      /// Flush all queue state for this buffer on the device.
181      /// @note Called on the SFX update thread.
182      virtual void _flush() = 0;
183
184   public:
185
186      /// Signal that is triggered when the buffer status changes.
187      /// @note This signal is triggered on the same thread that the buffer update
188      ///   code runs on.
189      Signal< void( SFXBuffer* buffer, Status newStatus ) > mOnStatusChange;
190
191      /// @return The current buffer loading/queue status.
192      Status getStatus() const { return mStatus; }
193
194      /// @return The sound sample format used by the buffer.
195      const SFXFormat& getFormat() const { return mFormat; }
196
197      /// @return The total playback time of the buffer in milliseconds.
198      U32 getDuration() const { return mDuration; }
199
200      /// @return The total number of samples in the buffer.
201      U32 getNumSamples() const { return getFormat().getSampleCount( mDuration ); }
202
203      /// @return The number of bytes consumed by this sound buffer.
204      virtual U32 getMemoryUsed() const { return 0; }
205
206      /// @return True if the buffer does continuous sound streaming.
207      bool isStreaming() const { return mIsStreaming; }
208
209      /// @return True if the buffer is pending deletion.
210      bool isDead() const { return mIsDead; }
211
212      /// @return True if the buffer's packet queue is loaded and ready for playback.
213      bool isReady() const { return ( getStatus() == STATUS_Ready ); }
214
215      /// @return True if the buffer's packet queue is still loading.
216      bool isLoading() const { return ( getStatus() == STATUS_Loading ); }
217
218      /// @return True if the buffer's packet queue has been starved and is waiting for data.
219      bool isBlocked() const { return ( getStatus() == STATUS_Blocked ); }
220
221      /// @return True if the buffer has exhausted its source stream
222      bool isAtEnd() const { return ( getStatus() == STATUS_AtEnd ); }
223
224      /// @return True if the buffer can only have a single SFXVoice attached to it.
225      bool isUnique() const { return mIsUnique; }
226
227      /// Start the async request chain for the buffer.
228      void load();
229
230      // IPolled.
231      virtual bool update();
232
233      // WeakRefBase.
234      virtual void destroySelf();
235};
236
237#endif // _SFXBUFFER_H_
238