|
|
|||
File indexing completed on 2026-06-02 08:58:13
0001 //////////////////////////////////////////////////////////// 0002 // 0003 // SFML - Simple and Fast Multimedia Library 0004 // Copyright (C) 2007-2023 Laurent Gomila (laurent@sfml-dev.org) 0005 // 0006 // This software is provided 'as-is', without any express or implied warranty. 0007 // In no event will the authors be held liable for any damages arising from the use of this software. 0008 // 0009 // Permission is granted to anyone to use this software for any purpose, 0010 // including commercial applications, and to alter it and redistribute it freely, 0011 // subject to the following restrictions: 0012 // 0013 // 1. The origin of this software must not be misrepresented; 0014 // you must not claim that you wrote the original software. 0015 // If you use this software in a product, an acknowledgment 0016 // in the product documentation would be appreciated but is not required. 0017 // 0018 // 2. Altered source versions must be plainly marked as such, 0019 // and must not be misrepresented as being the original software. 0020 // 0021 // 3. This notice may not be removed or altered from any source distribution. 0022 // 0023 //////////////////////////////////////////////////////////// 0024 0025 #ifndef SFML_SOUNDSTREAM_HPP 0026 #define SFML_SOUNDSTREAM_HPP 0027 0028 //////////////////////////////////////////////////////////// 0029 // Headers 0030 //////////////////////////////////////////////////////////// 0031 #include <SFML/Audio/Export.hpp> 0032 #include <SFML/Audio/SoundSource.hpp> 0033 #include <SFML/System/Thread.hpp> 0034 #include <SFML/System/Time.hpp> 0035 #include <SFML/System/Mutex.hpp> 0036 #include <cstdlib> 0037 0038 0039 namespace sf 0040 { 0041 //////////////////////////////////////////////////////////// 0042 /// \brief Abstract base class for streamed audio sources 0043 /// 0044 //////////////////////////////////////////////////////////// 0045 class SFML_AUDIO_API SoundStream : public SoundSource 0046 { 0047 public: 0048 0049 //////////////////////////////////////////////////////////// 0050 /// \brief Structure defining a chunk of audio data to stream 0051 /// 0052 //////////////////////////////////////////////////////////// 0053 struct Chunk 0054 { 0055 const Int16* samples; //!< Pointer to the audio samples 0056 std::size_t sampleCount; //!< Number of samples pointed by Samples 0057 }; 0058 0059 //////////////////////////////////////////////////////////// 0060 /// \brief Destructor 0061 /// 0062 //////////////////////////////////////////////////////////// 0063 virtual ~SoundStream(); 0064 0065 //////////////////////////////////////////////////////////// 0066 /// \brief Start or resume playing the audio stream 0067 /// 0068 /// This function starts the stream if it was stopped, resumes 0069 /// it if it was paused, and restarts it from the beginning if 0070 /// it was already playing. 0071 /// This function uses its own thread so that it doesn't block 0072 /// the rest of the program while the stream is played. 0073 /// 0074 /// \see pause, stop 0075 /// 0076 //////////////////////////////////////////////////////////// 0077 void play(); 0078 0079 //////////////////////////////////////////////////////////// 0080 /// \brief Pause the audio stream 0081 /// 0082 /// This function pauses the stream if it was playing, 0083 /// otherwise (stream already paused or stopped) it has no effect. 0084 /// 0085 /// \see play, stop 0086 /// 0087 //////////////////////////////////////////////////////////// 0088 void pause(); 0089 0090 //////////////////////////////////////////////////////////// 0091 /// \brief Stop playing the audio stream 0092 /// 0093 /// This function stops the stream if it was playing or paused, 0094 /// and does nothing if it was already stopped. 0095 /// It also resets the playing position (unlike pause()). 0096 /// 0097 /// \see play, pause 0098 /// 0099 //////////////////////////////////////////////////////////// 0100 void stop(); 0101 0102 //////////////////////////////////////////////////////////// 0103 /// \brief Return the number of channels of the stream 0104 /// 0105 /// 1 channel means a mono sound, 2 means stereo, etc. 0106 /// 0107 /// \return Number of channels 0108 /// 0109 //////////////////////////////////////////////////////////// 0110 unsigned int getChannelCount() const; 0111 0112 //////////////////////////////////////////////////////////// 0113 /// \brief Get the stream sample rate of the stream 0114 /// 0115 /// The sample rate is the number of audio samples played per 0116 /// second. The higher, the better the quality. 0117 /// 0118 /// \return Sample rate, in number of samples per second 0119 /// 0120 //////////////////////////////////////////////////////////// 0121 unsigned int getSampleRate() const; 0122 0123 //////////////////////////////////////////////////////////// 0124 /// \brief Get the current status of the stream (stopped, paused, playing) 0125 /// 0126 /// \return Current status 0127 /// 0128 //////////////////////////////////////////////////////////// 0129 Status getStatus() const; 0130 0131 //////////////////////////////////////////////////////////// 0132 /// \brief Change the current playing position of the stream 0133 /// 0134 /// The playing position can be changed when the stream is 0135 /// either paused or playing. Changing the playing position 0136 /// when the stream is stopped has no effect, since playing 0137 /// the stream would reset its position. 0138 /// 0139 /// \param timeOffset New playing position, from the beginning of the stream 0140 /// 0141 /// \see getPlayingOffset 0142 /// 0143 //////////////////////////////////////////////////////////// 0144 void setPlayingOffset(Time timeOffset); 0145 0146 //////////////////////////////////////////////////////////// 0147 /// \brief Get the current playing position of the stream 0148 /// 0149 /// \return Current playing position, from the beginning of the stream 0150 /// 0151 /// \see setPlayingOffset 0152 /// 0153 //////////////////////////////////////////////////////////// 0154 Time getPlayingOffset() const; 0155 0156 //////////////////////////////////////////////////////////// 0157 /// \brief Set whether or not the stream should loop after reaching the end 0158 /// 0159 /// If set, the stream will restart from beginning after 0160 /// reaching the end and so on, until it is stopped or 0161 /// setLoop(false) is called. 0162 /// The default looping state for streams is false. 0163 /// 0164 /// \param loop True to play in loop, false to play once 0165 /// 0166 /// \see getLoop 0167 /// 0168 //////////////////////////////////////////////////////////// 0169 void setLoop(bool loop); 0170 0171 //////////////////////////////////////////////////////////// 0172 /// \brief Tell whether or not the stream is in loop mode 0173 /// 0174 /// \return True if the stream is looping, false otherwise 0175 /// 0176 /// \see setLoop 0177 /// 0178 //////////////////////////////////////////////////////////// 0179 bool getLoop() const; 0180 0181 protected: 0182 0183 enum 0184 { 0185 NoLoop = -1 //!< "Invalid" endSeeks value, telling us to continue uninterrupted 0186 }; 0187 0188 //////////////////////////////////////////////////////////// 0189 /// \brief Default constructor 0190 /// 0191 /// This constructor is only meant to be called by derived classes. 0192 /// 0193 //////////////////////////////////////////////////////////// 0194 SoundStream(); 0195 0196 //////////////////////////////////////////////////////////// 0197 /// \brief Define the audio stream parameters 0198 /// 0199 /// This function must be called by derived classes as soon 0200 /// as they know the audio settings of the stream to play. 0201 /// Any attempt to manipulate the stream (play(), ...) before 0202 /// calling this function will fail. 0203 /// It can be called multiple times if the settings of the 0204 /// audio stream change, but only when the stream is stopped. 0205 /// 0206 /// \param channelCount Number of channels of the stream 0207 /// \param sampleRate Sample rate, in samples per second 0208 /// 0209 //////////////////////////////////////////////////////////// 0210 void initialize(unsigned int channelCount, unsigned int sampleRate); 0211 0212 //////////////////////////////////////////////////////////// 0213 /// \brief Request a new chunk of audio samples from the stream source 0214 /// 0215 /// This function must be overridden by derived classes to provide 0216 /// the audio samples to play. It is called continuously by the 0217 /// streaming loop, in a separate thread. 0218 /// The source can choose to stop the streaming loop at any time, by 0219 /// returning false to the caller. 0220 /// If you return true (i.e. continue streaming) it is important that 0221 /// the returned array of samples is not empty; this would stop the stream 0222 /// due to an internal limitation. 0223 /// 0224 /// \param data Chunk of data to fill 0225 /// 0226 /// \return True to continue playback, false to stop 0227 /// 0228 //////////////////////////////////////////////////////////// 0229 virtual bool onGetData(Chunk& data) = 0; 0230 0231 //////////////////////////////////////////////////////////// 0232 /// \brief Change the current playing position in the stream source 0233 /// 0234 /// This function must be overridden by derived classes to 0235 /// allow random seeking into the stream source. 0236 /// 0237 /// \param timeOffset New playing position, relative to the beginning of the stream 0238 /// 0239 //////////////////////////////////////////////////////////// 0240 virtual void onSeek(Time timeOffset) = 0; 0241 0242 //////////////////////////////////////////////////////////// 0243 /// \brief Change the current playing position in the stream source to the beginning of the loop 0244 /// 0245 /// This function can be overridden by derived classes to 0246 /// allow implementation of custom loop points. Otherwise, 0247 /// it just calls onSeek(Time::Zero) and returns 0. 0248 /// 0249 /// \return The seek position after looping (or -1 if there's no loop) 0250 /// 0251 //////////////////////////////////////////////////////////// 0252 virtual Int64 onLoop(); 0253 0254 //////////////////////////////////////////////////////////// 0255 /// \brief Set the processing interval 0256 /// 0257 /// The processing interval controls the period at which the 0258 /// audio buffers are filled by calls to onGetData. A smaller 0259 /// interval may be useful for low-latency streams. Note that 0260 /// the given period is only a hint and the actual period may 0261 /// vary. The default processing interval is 10 ms. 0262 /// 0263 /// \param interval Processing interval 0264 /// 0265 //////////////////////////////////////////////////////////// 0266 void setProcessingInterval(Time interval); 0267 0268 private: 0269 0270 //////////////////////////////////////////////////////////// 0271 /// \brief Function called as the entry point of the thread 0272 /// 0273 /// This function starts the streaming loop, and returns 0274 /// only when the sound is stopped. 0275 /// 0276 //////////////////////////////////////////////////////////// 0277 void streamData(); 0278 0279 //////////////////////////////////////////////////////////// 0280 /// \brief Fill a new buffer with audio samples, and append 0281 /// it to the playing queue 0282 /// 0283 /// This function is called as soon as a buffer has been fully 0284 /// consumed; it fills it again and inserts it back into the 0285 /// playing queue. 0286 /// 0287 /// \param bufferNum Number of the buffer to fill (in [0, BufferCount]) 0288 /// \param immediateLoop Treat empty buffers as spent, and act on loops immediately 0289 /// 0290 /// \return True if the stream source has requested to stop, false otherwise 0291 /// 0292 //////////////////////////////////////////////////////////// 0293 bool fillAndPushBuffer(unsigned int bufferNum, bool immediateLoop = false); 0294 0295 //////////////////////////////////////////////////////////// 0296 /// \brief Fill the audio buffers and put them all into the playing queue 0297 /// 0298 /// This function is called when playing starts and the 0299 /// playing queue is empty. 0300 /// 0301 /// \return True if the derived class has requested to stop, false otherwise 0302 /// 0303 //////////////////////////////////////////////////////////// 0304 bool fillQueue(); 0305 0306 //////////////////////////////////////////////////////////// 0307 /// \brief Clear all the audio buffers and empty the playing queue 0308 /// 0309 /// This function is called when the stream is stopped. 0310 /// 0311 //////////////////////////////////////////////////////////// 0312 void clearQueue(); 0313 0314 enum 0315 { 0316 BufferCount = 3, //!< Number of audio buffers used by the streaming loop 0317 BufferRetries = 2 //!< Number of retries (excluding initial try) for onGetData() 0318 }; 0319 0320 //////////////////////////////////////////////////////////// 0321 // Member data 0322 //////////////////////////////////////////////////////////// 0323 Thread m_thread; //!< Thread running the background tasks 0324 mutable Mutex m_threadMutex; //!< Thread mutex 0325 Status m_threadStartState; //!< State the thread starts in (Playing, Paused, Stopped) 0326 bool m_isStreaming; //!< Streaming state (true = playing, false = stopped) 0327 unsigned int m_buffers[BufferCount]; //!< Sound buffers used to store temporary audio data 0328 unsigned int m_channelCount; //!< Number of channels (1 = mono, 2 = stereo, ...) 0329 unsigned int m_sampleRate; //!< Frequency (samples / second) 0330 Int32 m_format; //!< Format of the internal sound buffers 0331 bool m_loop; //!< Loop flag (true to loop, false to play once) 0332 Uint64 m_samplesProcessed; //!< Number of samples processed since beginning of the stream 0333 Int64 m_bufferSeeks[BufferCount]; //!< If buffer is an "end buffer", holds next seek position, else NoLoop. For play offset calculation. 0334 Time m_processingInterval; //!< Interval for checking and filling the internal sound buffers. 0335 }; 0336 0337 } // namespace sf 0338 0339 0340 #endif // SFML_SOUNDSTREAM_HPP 0341 0342 0343 //////////////////////////////////////////////////////////// 0344 /// \class sf::SoundStream 0345 /// \ingroup audio 0346 /// 0347 /// Unlike audio buffers (see sf::SoundBuffer), audio streams 0348 /// are never completely loaded in memory. Instead, the audio 0349 /// data is acquired continuously while the stream is playing. 0350 /// This behavior allows to play a sound with no loading delay, 0351 /// and keeps the memory consumption very low. 0352 /// 0353 /// Sound sources that need to be streamed are usually big files 0354 /// (compressed audio musics that would eat hundreds of MB in memory) 0355 /// or files that would take a lot of time to be received 0356 /// (sounds played over the network). 0357 /// 0358 /// sf::SoundStream is a base class that doesn't care about the 0359 /// stream source, which is left to the derived class. SFML provides 0360 /// a built-in specialization for big files (see sf::Music). 0361 /// No network stream source is provided, but you can write your own 0362 /// by combining this class with the network module. 0363 /// 0364 /// A derived class has to override two virtual functions: 0365 /// \li onGetData fills a new chunk of audio data to be played 0366 /// \li onSeek changes the current playing position in the source 0367 /// 0368 /// It is important to note that each SoundStream is played in its 0369 /// own separate thread, so that the streaming loop doesn't block the 0370 /// rest of the program. In particular, the OnGetData and OnSeek 0371 /// virtual functions may sometimes be called from this separate thread. 0372 /// It is important to keep this in mind, because you may have to take 0373 /// care of synchronization issues if you share data between threads. 0374 /// 0375 /// Usage example: 0376 /// \code 0377 /// class CustomStream : public sf::SoundStream 0378 /// { 0379 /// public: 0380 /// 0381 /// bool open(const std::string& location) 0382 /// { 0383 /// // Open the source and get audio settings 0384 /// ... 0385 /// unsigned int channelCount = ...; 0386 /// unsigned int sampleRate = ...; 0387 /// 0388 /// // Initialize the stream -- important! 0389 /// initialize(channelCount, sampleRate); 0390 /// } 0391 /// 0392 /// private: 0393 /// 0394 /// virtual bool onGetData(Chunk& data) 0395 /// { 0396 /// // Fill the chunk with audio data from the stream source 0397 /// // (note: must not be empty if you want to continue playing) 0398 /// data.samples = ...; 0399 /// data.sampleCount = ...; 0400 /// 0401 /// // Return true to continue playing 0402 /// return true; 0403 /// } 0404 /// 0405 /// virtual void onSeek(sf::Time timeOffset) 0406 /// { 0407 /// // Change the current position in the stream source 0408 /// ... 0409 /// } 0410 /// }; 0411 /// 0412 /// // Usage 0413 /// CustomStream stream; 0414 /// stream.open("path/to/stream"); 0415 /// stream.play(); 0416 /// \endcode 0417 /// 0418 /// \see sf::Music 0419 /// 0420 ////////////////////////////////////////////////////////////
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|