sfxBuffer.h
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