D:/Programmation/Cpp/SFML/src/SFML/Audio/SoundStream.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Audio/SoundStream.hpp>
00029 #include <SFML/Audio/SoundBuffer.hpp>
00030 #include <SFML/Audio/OpenAL.hpp>
00031 #include <SFML/System/Sleep.hpp>
00032 
00033 
00037 sfSoundStream::sfSoundStream() :
00038 myIsStreaming  (false),
00039 myChannelsCount(0),
00040 myFrequency    (0)
00041 {
00042 
00043 }
00044 
00045 
00049 sfSoundStream::~sfSoundStream()
00050 {
00051     // Stop the sound if it was playing
00052     Stop();
00053 }
00054 
00055 
00059 void sfSoundStream::Initialize(unsigned int ChannelsCount, unsigned int Frequency)
00060 {
00061     myChannelsCount = ChannelsCount;
00062     myFrequency     = Frequency;
00063 }
00064 
00065 
00069 void sfSoundStream::Play()
00070 {
00071     // Check if the sound parameters have been set
00072     if ((myChannelsCount == 0) || (myFrequency == 0))
00073     {
00074         std::cerr << "Failed to play audio stream : sound parameters have not been initialized (call Initialize first)" << std::endl;
00075         return;
00076     }
00077 
00078     // If the sound is already playing (probably paused), just resume it
00079     if (myIsStreaming)
00080     {
00081         sfALCheck(alSourcePlay(mySource->Source));
00082         return;
00083     }
00084 
00085     // Create the sound source
00086     float Position[3] = {0.f, 0.f, 0.f};
00087     mySource = new sf_private::sfSoundImpl(false, 1.f, 100.f, Position);
00088 
00089     // Notify the derived class
00090     if (OnStart())
00091     {
00092         // Start updating the stream in a separate thread to avoid blocking the application
00093         myIsStreaming = true;
00094         Launch();
00095     }
00096 }
00097 
00098 
00102 void sfSoundStream::Pause()
00103 {
00104     sfALCheck(alSourcePause(mySource->Source));
00105 }
00106 
00107 
00111 void sfSoundStream::Stop()
00112 {
00113     // Wait for the thread to terminate
00114     myIsStreaming = false;
00115     Wait();
00116 }
00117 
00118 
00122 unsigned int sfSoundStream::GetChannelsCount() const
00123 {
00124     return myChannelsCount;
00125 }
00126 
00127 
00131 unsigned int sfSoundStream::GetFrequency() const
00132 {
00133     return myFrequency;
00134 }
00135 
00136 
00140 void sfSoundStream::SetPitch(float Pitch)
00141 {
00142     sfALCheck(alSourcef(mySource->Source, AL_PITCH, Pitch));
00143 }
00144 
00145 
00149 void sfSoundStream::SetVolume(float Volume)
00150 {
00151     sfALCheck(alSourcef(mySource->Source, AL_GAIN, Volume * 0.01f));
00152 }
00153 
00154 
00158 void sfSoundStream::SetPosition(float X, float Y, float Z)
00159 {
00160     sfALCheck(alSource3f(mySource->Source, AL_POSITION, X, Y, Z));
00161 }
00162 
00163 
00167 float sfSoundStream::GetPitch() const
00168 {
00169     ALfloat Pitch;
00170     sfALCheck(alGetSourcef(mySource->Source, AL_PITCH, &Pitch));
00171 
00172     return Pitch;
00173 }
00174 
00175 
00179 float sfSoundStream::GetVolume() const
00180 {
00181     ALfloat Gain;
00182     sfALCheck(alGetSourcef(mySource->Source, AL_GAIN, &Gain));
00183 
00184     return Gain * 100.f;
00185 }
00186 
00187 
00191 void sfSoundStream::GetPosition(float& X, float& Y, float& Z) const
00192 {
00193     sfALCheck(alGetSource3f(mySource->Source, AL_POSITION, &X, &Y, &Z));
00194 }
00195 
00196 
00200 sfSoundStatus sfSoundStream::GetStatus() const
00201 {
00202     ALint State;
00203     sfALCheck(alGetSourcei(mySource->Source, AL_SOURCE_STATE, &State));
00204 
00205     switch (State)
00206     {
00207         case AL_INITIAL :
00208         case AL_STOPPED : return myIsStreaming ? Playing : Stopped; // To compensate for the lag between Play() and alSourcePlay()
00209         case AL_PAUSED :  return Paused;
00210         case AL_PLAYING : return Playing;
00211     }
00212 
00213     return Stopped;
00214 }
00215 
00216 
00220 void sfSoundStream::Run()
00221 {
00222     // Enqueue the buffers
00223     for (int i = 0; i < BuffersCount; ++i)
00224     {
00225         // Acquire audio data
00226         Chunk Data = {NULL, 0};
00227         if (OnGetData(Data))
00228         {
00229             // Create and fill a buffer, and push it to the queue
00230             if (Data.Samples && Data.NbSamples)
00231             {
00232                 myBuffers[i] = new sf_private::sfSoundBufferImpl(Data.Samples, Data.NbSamples, myChannelsCount, myFrequency);
00233                 sfALCheck(alSourceQueueBuffers(mySource->Source, 1, &myBuffers[i]->Buffer));
00234             }
00235         }
00236     }
00237 
00238     // Play the sound
00239     sfALCheck(alSourcePlay(mySource->Source));
00240 
00241     while (myIsStreaming)
00242     {
00243         // If the stream has been interrupted the source is stopped, so we have to keep it on playing
00244         if (GetStatus() == Stopped)
00245             sfALCheck(alSourcePlay(mySource->Source));
00246 
00247         // Get the number of buffers that have been processed (ie. ready for reuse)
00248         ALint NbProcessed;
00249         sfALCheck(alGetSourcei(mySource->Source, AL_BUFFERS_PROCESSED, &NbProcessed));
00250 
00251         for (ALint i = 0; i < NbProcessed; ++i)
00252         {
00253             // Pop the first unused buffer from the queue
00254             ALuint Buffer;
00255             sfALCheck(alSourceUnqueueBuffers(mySource->Source, 1, &Buffer));
00256 
00257             // Acquire new data
00258             Chunk Data = {NULL, 0};
00259             if (OnGetData(Data))
00260             {
00261                 // Fill the buffer with the new data, and push it back to the queue
00262                 if (Data.Samples && Data.NbSamples)
00263                 {
00264                     for (int j = 0; j < BuffersCount; ++j)
00265                     {
00266                         if (myBuffers[j]->Buffer == Buffer)
00267                         {
00268                             myBuffers[j]->Fill(Data.Samples, Data.NbSamples, myChannelsCount, myFrequency);
00269                             sfALCheck(alSourceQueueBuffers(mySource->Source, 1, &Buffer));
00270                             break;
00271                         }
00272                     }
00273                 }
00274             }
00275             else
00276             {
00277                 // Oops... the user wants to stop the sound :(
00278                 myIsStreaming = false;
00279                 break;
00280             }
00281         }
00282 
00283         // Leave some time for the other threads
00284         sfSleep(0.1f);
00285     }
00286 
00287     // Streaming finished : clean up everything
00288     CleanUp();
00289 }
00290 
00291 
00295 void sfSoundStream::CleanUp()
00296 {
00297     // Stop the playback
00298     sfALCheck(alSourceStop(mySource->Source));
00299 
00300     // Unqueue any buffer left in the queue
00301     ALint  NbQueued;
00302     ALuint Buffer;
00303     sfALCheck(alGetSourcei(mySource->Source, AL_BUFFERS_QUEUED, &NbQueued));
00304     for (ALint i = 0; i < NbQueued; ++i)
00305         sfALCheck(alSourceUnqueueBuffers(mySource->Source, 1, &Buffer));
00306 }
00307 
00308 
00312 bool sfSoundStream::OnStart()
00313 {
00314     // Does nothing by default
00315 
00316     return true;
00317 }

Generated for SFML by  doxygen 1.5.2