sfxBuffer.h 9.1 KB

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