Added SetPlayingOffset to sf::SoundStream and sf::Music

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1076 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2009-04-10 22:50:08 +00:00
parent 364b0ae9b1
commit 22c225c64f
17 changed files with 202 additions and 166 deletions

View File

@ -24,6 +24,7 @@ EXPORTS
sfMusic_SetRelativeToListener sfMusic_SetRelativeToListener
sfMusic_SetMinDistance sfMusic_SetMinDistance
sfMusic_SetAttenuation sfMusic_SetAttenuation
sfMusic_SetPlayingOffset
sfMusic_GetPitch sfMusic_GetPitch
sfMusic_GetVolume sfMusic_GetVolume
sfMusic_GetPosition sfMusic_GetPosition
@ -91,6 +92,7 @@ EXPORTS
sfSoundStream_SetRelativeToListener sfSoundStream_SetRelativeToListener
sfSoundStream_SetMinDistance sfSoundStream_SetMinDistance
sfSoundStream_SetAttenuation sfSoundStream_SetAttenuation
sfSoundStream_SetPlayingOffset
sfSoundStream_SetLoop sfSoundStream_SetLoop
sfSoundStream_GetPitch sfSoundStream_GetPitch
sfSoundStream_GetVolume sfSoundStream_GetVolume

View File

@ -24,6 +24,7 @@ EXPORTS
sfMusic_SetRelativeToListener sfMusic_SetRelativeToListener
sfMusic_SetMinDistance sfMusic_SetMinDistance
sfMusic_SetAttenuation sfMusic_SetAttenuation
sfMusic_SetPlayingOffset
sfMusic_GetPitch sfMusic_GetPitch
sfMusic_GetVolume sfMusic_GetVolume
sfMusic_GetPosition sfMusic_GetPosition
@ -91,6 +92,7 @@ EXPORTS
sfSoundStream_SetRelativeToListener sfSoundStream_SetRelativeToListener
sfSoundStream_SetMinDistance sfSoundStream_SetMinDistance
sfSoundStream_SetAttenuation sfSoundStream_SetAttenuation
sfSoundStream_SetPlayingOffset
sfSoundStream_SetLoop sfSoundStream_SetLoop
sfSoundStream_GetPitch sfSoundStream_GetPitch
sfSoundStream_GetVolume sfSoundStream_GetVolume

View File

@ -24,6 +24,7 @@ EXPORTS
sfMusic_SetRelativeToListener sfMusic_SetRelativeToListener
sfMusic_SetMinDistance sfMusic_SetMinDistance
sfMusic_SetAttenuation sfMusic_SetAttenuation
sfMusic_SetPlayingOffset
sfMusic_GetPitch sfMusic_GetPitch
sfMusic_GetVolume sfMusic_GetVolume
sfMusic_GetPosition sfMusic_GetPosition
@ -91,6 +92,7 @@ EXPORTS
sfSoundStream_SetRelativeToListener sfSoundStream_SetRelativeToListener
sfSoundStream_SetMinDistance sfSoundStream_SetMinDistance
sfSoundStream_SetAttenuation sfSoundStream_SetAttenuation
sfSoundStream_SetPlayingOffset
sfSoundStream_SetLoop sfSoundStream_SetLoop
sfSoundStream_GetPitch sfSoundStream_GetPitch
sfSoundStream_GetVolume sfSoundStream_GetVolume

View File

@ -24,6 +24,7 @@ EXPORTS
sfMusic_SetRelativeToListener sfMusic_SetRelativeToListener
sfMusic_SetMinDistance sfMusic_SetMinDistance
sfMusic_SetAttenuation sfMusic_SetAttenuation
sfMusic_SetPlayingOffset
sfMusic_GetPitch sfMusic_GetPitch
sfMusic_GetVolume sfMusic_GetVolume
sfMusic_GetPosition sfMusic_GetPosition
@ -91,6 +92,7 @@ EXPORTS
sfSoundStream_SetRelativeToListener sfSoundStream_SetRelativeToListener
sfSoundStream_SetMinDistance sfSoundStream_SetMinDistance
sfSoundStream_SetAttenuation sfSoundStream_SetAttenuation
sfSoundStream_SetPlayingOffset
sfSoundStream_SetLoop sfSoundStream_SetLoop
sfSoundStream_GetPitch sfSoundStream_GetPitch
sfSoundStream_GetVolume sfSoundStream_GetVolume

View File

@ -211,12 +211,21 @@ CSFML_API void sfMusic_SetMinDistance(sfMusic* Music, float MinDistance);
/// more the sound will be attenuated with distance from listener. /// more the sound will be attenuated with distance from listener.
/// The default attenuation factor 1.0 /// The default attenuation factor 1.0
/// ///
/// \param Sound : Sound to modify /// \param Music : Music to modify
/// \param Attenuation : New attenuation factor for the sound /// \param Attenuation : New attenuation factor for the sound
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
CSFML_API void sfMusic_SetAttenuation(sfMusic* Music, float Attenuation); CSFML_API void sfMusic_SetAttenuation(sfMusic* Music, float Attenuation);
////////////////////////////////////////////////////////////
/// Set the current playing position of a music
///
/// \param Music : Music to modify
/// \param TimeOffset : New playing position, expressed in seconds
///
////////////////////////////////////////////////////////////
CSFML_API void sfMusic_SetPlayingOffset(sfMusic* Music, float TimeOffset);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the pitch of a music /// Get the pitch of a music
/// ///

View File

@ -43,15 +43,15 @@ typedef struct
unsigned int NbSamples; ///< Number of samples pointed by Samples unsigned int NbSamples; ///< Number of samples pointed by Samples
} sfSoundStreamChunk; } sfSoundStreamChunk;
typedef sfBool (*sfSoundStreamStartCallback)(void*); ///< Type of the callback used to start a sound stream
typedef sfBool (*sfSoundStreamGetDataCallback)(sfSoundStreamChunk*, void*); ///< Type of the callback used to get a sound stream data typedef sfBool (*sfSoundStreamGetDataCallback)(sfSoundStreamChunk*, void*); ///< Type of the callback used to get a sound stream data
typedef void (*sfSoundStreamSeekCallback)(float, void*); ///< Type of the callback used to seek in a sound stream
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Construct a new sound stream /// Construct a new sound stream
/// ///
/// \param OnStart : Function called when the stream starts (can be NULL)
/// \param OnGetData : Function called when the stream needs more data (can't be NULL) /// \param OnGetData : Function called when the stream needs more data (can't be NULL)
/// \param OnSeek : Function called when the stream seeks (can't be NULL)
/// \param ChannelsCount : Number of channels to use (1 = mono, 2 = stereo) /// \param ChannelsCount : Number of channels to use (1 = mono, 2 = stereo)
/// \param SampleRate : Sample rate of the sound (44100 = CD quality) /// \param SampleRate : Sample rate of the sound (44100 = CD quality)
/// \param UserData : Data to pass to the callback functions /// \param UserData : Data to pass to the callback functions
@ -59,8 +59,8 @@ typedef sfBool (*sfSoundStreamGetDataCallback)(sfSoundStreamChunk*, void*); ///<
/// \return A new sfSoundStream object (NULL if failed) /// \return A new sfSoundStream object (NULL if failed)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
CSFML_API sfSoundStream* sfSoundStream_Create(sfSoundStreamStartCallback OnStart, CSFML_API sfSoundStream* sfSoundStream_Create(sfSoundStreamGetDataCallback OnGetData,
sfSoundStreamGetDataCallback OnGetData, sfSoundStreamSeekCallback OnSeek,
unsigned int ChannelsCount, unsigned int ChannelsCount,
unsigned int SampleRate, unsigned int SampleRate,
void* UserData); void* UserData);
@ -190,6 +190,15 @@ CSFML_API void sfSoundStream_SetMinDistance(sfSoundStream* SoundStream, float Mi
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
CSFML_API void sfSoundStream_SetAttenuation(sfSoundStream* SoundStream, float Attenuation); CSFML_API void sfSoundStream_SetAttenuation(sfSoundStream* SoundStream, float Attenuation);
////////////////////////////////////////////////////////////
/// Set the current playing position of a stream
///
/// \param SoundStream : Sound stream to modify
/// \param TimeOffset : New playing position, expressed in seconds
///
////////////////////////////////////////////////////////////
CSFML_API void sfSoundStream_SetPlayingOffset(sfSoundStream* SoundStream, float TimeOffset);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set a stream loop state /// Set a stream loop state
/// ///

View File

@ -231,6 +231,15 @@ void sfMusic_SetAttenuation(sfMusic* Music, float Attenuation)
} }
////////////////////////////////////////////////////////////
/// Set the current playing position of a stream
////////////////////////////////////////////////////////////
void sfMusic_SetPlayingOffset(sfMusic* Music, float TimeOffset)
{
CSFML_CALL(Music, SetPlayingOffset(TimeOffset));
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the pitch of a music /// Get the pitch of a music
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -34,13 +34,13 @@ class sfSoundStreamImpl : public sf::SoundStream
{ {
public : public :
sfSoundStreamImpl(sfSoundStreamStartCallback OnStart, sfSoundStreamImpl(sfSoundStreamGetDataCallback OnGetData,
sfSoundStreamGetDataCallback OnGetData, sfSoundStreamSeekCallback OnSeek,
unsigned int ChannelsCount, unsigned int ChannelsCount,
unsigned int SampleRate, unsigned int SampleRate,
void* UserData) : void* UserData) :
myStartCallback (OnStart),
myGetDataCallback(OnGetData), myGetDataCallback(OnGetData),
mySeekCallback (OnSeek),
myUserData (UserData) myUserData (UserData)
{ {
Initialize(ChannelsCount, SampleRate); Initialize(ChannelsCount, SampleRate);
@ -48,14 +48,6 @@ public :
private : private :
virtual bool OnStart()
{
if (myStartCallback)
return myStartCallback(myUserData) == sfTrue;
else
return true;
}
virtual bool OnGetData(Chunk& Data) virtual bool OnGetData(Chunk& Data)
{ {
sfSoundStreamChunk Chunk = {NULL, 0}; sfSoundStreamChunk Chunk = {NULL, 0};
@ -67,21 +59,26 @@ private :
return Continue; return Continue;
} }
sfSoundStreamStartCallback myStartCallback; virtual void OnSeek(float TimeOffset)
{
if (mySeekCallback)
mySeekCallback(TimeOffset, myUserData);
}
sfSoundStreamGetDataCallback myGetDataCallback; sfSoundStreamGetDataCallback myGetDataCallback;
sfSoundStreamSeekCallback mySeekCallback;
void* myUserData; void* myUserData;
}; };
struct sfSoundStream struct sfSoundStream
{ {
sfSoundStream(sfSoundStreamGetDataCallback OnGetData,
sfSoundStream(sfSoundStreamStartCallback OnStart, sfSoundStreamSeekCallback OnSeek,
sfSoundStreamGetDataCallback OnGetData,
unsigned int ChannelsCount, unsigned int ChannelsCount,
unsigned int SampleRate, unsigned int SampleRate,
void* UserData) : void* UserData) :
This(OnStart, OnGetData, ChannelsCount, SampleRate, UserData) This(OnGetData, OnSeek, ChannelsCount, SampleRate, UserData)
{ {
} }
@ -92,13 +89,13 @@ struct sfSoundStream
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Construct a new sound stream /// Construct a new sound stream
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sfSoundStream* sfSoundStream_Create(sfSoundStreamStartCallback OnStart, sfSoundStream* sfSoundStream_Create(sfSoundStreamGetDataCallback OnGetData,
sfSoundStreamGetDataCallback OnGetData, sfSoundStreamSeekCallback OnSeek,
unsigned int ChannelsCount, unsigned int ChannelsCount,
unsigned int SampleRate, unsigned int SampleRate,
void* UserData) void* UserData)
{ {
return new sfSoundStream(OnStart, OnGetData, ChannelsCount, SampleRate, UserData); return new sfSoundStream(OnGetData, OnSeek, ChannelsCount, SampleRate, UserData);
} }
@ -228,6 +225,15 @@ void sfSoundStream_SetAttenuation(sfSoundStream* SoundStream, float Attenuation)
} }
////////////////////////////////////////////////////////////
/// Set the current playing position of a stream
////////////////////////////////////////////////////////////
void sfSoundStream_SetPlayingOffset(sfSoundStream* SoundStream, float TimeOffset)
{
CSFML_CALL(SoundStream, SetPlayingOffset(TimeOffset));
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set a stream loop state /// Set a stream loop state
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -212,6 +212,7 @@ namespace SFML
public float PlayingOffset public float PlayingOffset
{ {
get {return sfMusic_GetPlayingOffset(This);} get {return sfMusic_GetPlayingOffset(This);}
set {sfMusic_SetPlayingOffset(This, value);}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -277,6 +278,9 @@ namespace SFML
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern void sfMusic_SetAttenuation(IntPtr Music, float Attenuation); static extern void sfMusic_SetAttenuation(IntPtr Music, float Attenuation);
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern void sfMusic_SetPlayingOffset(IntPtr Music, float TimeOffset);
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern bool sfMusic_GetLoop(IntPtr Music); static extern bool sfMusic_GetLoop(IntPtr Music);

View File

@ -177,6 +177,7 @@ namespace SFML
public float PlayingOffset public float PlayingOffset
{ {
get {return sfSoundStream_GetPlayingOffset(This);} get {return sfSoundStream_GetPlayingOffset(This);}
set {sfSoundStream_SetPlayingOffset(This, value);}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -188,21 +189,9 @@ namespace SFML
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
protected void Initialize(uint channelsCount, uint sampleRate) protected void Initialize(uint channelsCount, uint sampleRate)
{ {
myStartCallback = new StartCallbackType(Start);
myGetDataCallback = new GetDataCallbackType(GetData); myGetDataCallback = new GetDataCallbackType(GetData);
SetThis(sfSoundStream_Create(myStartCallback, myGetDataCallback, channelsCount, sampleRate, IntPtr.Zero)); mySeekCallback = new SeekCallbackType(Seek);
} SetThis(sfSoundStream_Create(myGetDataCallback, mySeekCallback, channelsCount, sampleRate, IntPtr.Zero));
////////////////////////////////////////////////////////////
/// <summary>
/// Virtual function called when the stream restarts
/// </summary>
/// <returns>If false is returned, the playback is aborted</returns>
////////////////////////////////////////////////////////////
protected virtual bool OnStart()
{
// Does nothing by default
return true;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -214,6 +203,14 @@ namespace SFML
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
protected abstract bool OnGetData(out short[] samples); protected abstract bool OnGetData(out short[] samples);
////////////////////////////////////////////////////////////
/// <summary>
/// Virtual function called to seek into the stream
/// </summary>
/// <param name="timeOffset">New position, expressed in seconds</param>
////////////////////////////////////////////////////////////
protected abstract void OnSeek(float timeOffset);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// <summary> /// <summary>
/// Handle the destruction of the object /// Handle the destruction of the object
@ -237,18 +234,6 @@ namespace SFML
public uint samplesCount; public uint samplesCount;
} }
////////////////////////////////////////////////////////////
/// <summary>
/// Called when the stream restarts
/// </summary>
/// <param name="userData">User data -- unused</param>
/// <returns>If false is returned, the playback is aborted</returns>
////////////////////////////////////////////////////////////
private bool Start(IntPtr userData)
{
return OnStart();
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// <summary> /// <summary>
/// Called each time new audio data is needed to feed the stream /// Called each time new audio data is needed to feed the stream
@ -277,19 +262,33 @@ namespace SFML
return false; return false;
} }
} }
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool StartCallbackType(IntPtr UserData); ////////////////////////////////////////////////////////////
/// <summary>
/// Called to seek in the stream
/// </summary>
/// <param name="timeOffset">New position, expressed in seconds</param>
/// <param name="userData">User data -- unused</param>
/// <returns>If false is returned, the playback is aborted</returns>
////////////////////////////////////////////////////////////
private void Seek(float timeOffset, IntPtr userData)
{
OnSeek(timeOffset);
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool GetDataCallbackType(ref Chunk dataChunk, IntPtr UserData); private delegate bool GetDataCallbackType(ref Chunk dataChunk, IntPtr UserData);
private StartCallbackType myStartCallback; [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SeekCallbackType(float timeOffset, IntPtr UserData);
private GetDataCallbackType myGetDataCallback; private GetDataCallbackType myGetDataCallback;
private SeekCallbackType mySeekCallback;
private short[] myTempBuffer; private short[] myTempBuffer;
#region Imports #region Imports
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern IntPtr sfSoundStream_Create(StartCallbackType OnStart, GetDataCallbackType OnGetData, uint ChannelsCount, uint SampleRate, IntPtr UserData); static extern IntPtr sfSoundStream_Create(GetDataCallbackType OnGetData, SeekCallbackType OnSeek, uint ChannelsCount, uint SampleRate, IntPtr UserData);
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern void sfSoundStream_Destroy(IntPtr SoundStreamStream); static extern void sfSoundStream_Destroy(IntPtr SoundStreamStream);
@ -333,6 +332,9 @@ namespace SFML
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern void sfSoundStream_SetAttenuation(IntPtr SoundStream, float Attenuation); static extern void sfSoundStream_SetAttenuation(IntPtr SoundStream, float Attenuation);
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern void sfSoundStream_SetPlayingOffset(IntPtr SoundStream, float TimeOffset);
[DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity]
static extern bool sfSoundStream_GetLoop(IntPtr SoundStream); static extern bool sfSoundStream_GetLoop(IntPtr SoundStream);

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundStream.hpp> #include <SFML/Audio/SoundStream.hpp>
#include <SFML/System/Mutex.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
@ -94,24 +95,25 @@ public :
private : private :
////////////////////////////////////////////////////////////
/// /see SoundStream::OnStart
///
////////////////////////////////////////////////////////////
virtual bool OnStart();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see SoundStream::OnGetData /// /see SoundStream::OnGetData
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool OnGetData(Chunk& Data); virtual bool OnGetData(Chunk& Data);
////////////////////////////////////////////////////////////
/// /see SoundStream::OnSeek
///
////////////////////////////////////////////////////////////
virtual void OnSeek(float TimeOffset);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::SoundFile* myFile; ///< Sound file priv::SoundFile* myFile; ///< Sound file
float myDuration; ///< Music duration, in seconds float myDuration; ///< Music duration, in seconds
std::vector<Int16> mySamples; ///< Temporary buffer of samples std::vector<Int16> mySamples; ///< Temporary buffer of samples
Mutex myMutex; ///< Mutex protecting the data
}; };
} // namespace sf } // namespace sf

View File

@ -114,6 +114,14 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Status GetStatus() const; Status GetStatus() const;
////////////////////////////////////////////////////////////
/// Set the current playing position of the stream
///
/// \param TimeOffset : New playing position, expressed in seconds
///
////////////////////////////////////////////////////////////
void SetPlayingOffset(float TimeOffset);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the current playing position of the stream /// Get the current playing position of the stream
/// ///
@ -164,14 +172,6 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual void Run(); virtual void Run();
////////////////////////////////////////////////////////////
/// Called when the sound restarts
///
/// \return If false is returned, the playback is aborted
///
////////////////////////////////////////////////////////////
virtual bool OnStart();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Called each time new audio data is needed to feed the stream /// Called each time new audio data is needed to feed the stream
/// ///
@ -182,6 +182,14 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool OnGetData(Chunk& Data) = 0; virtual bool OnGetData(Chunk& Data) = 0;
////////////////////////////////////////////////////////////
/// Called to move the current reading position
///
/// \param TimeOffset : New read position, expressed in seconds
///
////////////////////////////////////////////////////////////
virtual void OnSeek(float TimeOffset) = 0;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Fill a new buffer with audio data, and push it to the /// Fill a new buffer with audio data, and push it to the
/// playing queue /// playing queue

View File

@ -76,18 +76,6 @@ public :
private : private :
////////////////////////////////////////////////////////////
/// /see SoundStream::OnStart
///
////////////////////////////////////////////////////////////
virtual bool OnStart()
{
// Reset the playing offset
myOffset = 0;
return true;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see SoundStream::OnGetData /// /see SoundStream::OnGetData
/// ///
@ -95,11 +83,11 @@ private :
virtual bool OnGetData(sf::SoundStream::Chunk& Data) virtual bool OnGetData(sf::SoundStream::Chunk& Data)
{ {
// We have reached the end of the buffer and all audio data have been played : we can stop playback // We have reached the end of the buffer and all audio data have been played : we can stop playback
if ((myOffset == mySamples.size()) && myHasFinished) if ((myOffset >= mySamples.size()) && myHasFinished)
return false; return false;
// No new data has arrived since last update : wait until we get some // No new data has arrived since last update : wait until we get some
while ((myOffset == mySamples.size()) && !myHasFinished) while ((myOffset >= mySamples.size()) && !myHasFinished)
sf::Sleep(0.01f); sf::Sleep(0.01f);
// Copy samples into a local buffer to avoid synchronization problems // Copy samples into a local buffer to avoid synchronization problems
@ -119,6 +107,15 @@ private :
return true; return true;
} }
////////////////////////////////////////////////////////////
/// /see SoundStream::OnSeek
///
////////////////////////////////////////////////////////////
virtual void OnSeek(float TimeOffset)
{
myOffset = static_cast<std::size_t>(TimeOffset * GetSampleRate() * GetChannelsCount());
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get audio data from the client until playback is stopped /// Get audio data from the client until playback is stopped
/// ///

View File

@ -28,6 +28,7 @@
#include <SFML/Audio/Music.hpp> #include <SFML/Audio/Music.hpp>
#include <SFML/Audio/OpenAL.hpp> #include <SFML/Audio/OpenAL.hpp>
#include <SFML/Audio/SoundFile.hpp> #include <SFML/Audio/SoundFile.hpp>
#include <SFML/System/Lock.hpp>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -109,11 +110,11 @@ bool Music::OpenFromMemory(const char* Data, std::size_t SizeInBytes)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see SoundStream::OnStart /// Get the sound duration
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Music::OnStart() float Music::GetDuration() const
{ {
return myFile && myFile->Restart(); return myDuration;
} }
@ -122,28 +123,25 @@ bool Music::OnStart()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Music::OnGetData(SoundStream::Chunk& Data) bool Music::OnGetData(SoundStream::Chunk& Data)
{ {
if (myFile) sf::Lock Lock(myMutex);
{
// Fill the chunk parameters
Data.Samples = &mySamples[0];
Data.NbSamples = myFile->Read(&mySamples[0], mySamples.size());
// Check if we have reached the end of the audio file // Fill the chunk parameters
return Data.NbSamples == mySamples.size(); Data.Samples = &mySamples[0];
} Data.NbSamples = myFile->Read(&mySamples[0], mySamples.size());
else
{ // Check if we have reached the end of the audio file
return false; return Data.NbSamples == mySamples.size();
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the sound duration /// /see SoundStream::OnSeek
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
float Music::GetDuration() const void Music::OnSeek(float TimeOffset)
{ {
return myDuration; sf::Lock Lock(myMutex);
myFile->Seek(TimeOffset);
} }
} // namespace sf } // namespace sf

View File

@ -84,30 +84,6 @@ unsigned int SoundFile::GetSampleRate() const
} }
////////////////////////////////////////////////////////////
/// Restart the sound from the beginning
////////////////////////////////////////////////////////////
bool SoundFile::Restart()
{
if (myData)
{
// Reopen from memory
return OpenRead(myData, mySize);
}
else if (myFilename != "")
{
// Reopen from file
return OpenRead(myFilename);
}
else
{
// Trying to reopen a file opened in write mode... error
std::cerr << "Warning : trying to restart a sound opened in write mode, which is not allowed" << std::endl;
return false;
}
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Open the sound file for reading /// Open the sound file for reading
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -130,9 +106,6 @@ bool SoundFile::OpenRead(const std::string& Filename)
myChannelsCount = FileInfos.channels; myChannelsCount = FileInfos.channels;
mySampleRate = FileInfos.samplerate; mySampleRate = FileInfos.samplerate;
myNbSamples = static_cast<std::size_t>(FileInfos.frames) * myChannelsCount; myNbSamples = static_cast<std::size_t>(FileInfos.frames) * myChannelsCount;
myFilename = Filename;
myData = NULL;
mySize = 0;
return true; return true;
} }
@ -173,9 +146,6 @@ bool SoundFile::OpenRead(const char* Data, std::size_t SizeInBytes)
myChannelsCount = FileInfos.channels; myChannelsCount = FileInfos.channels;
mySampleRate = FileInfos.samplerate; mySampleRate = FileInfos.samplerate;
myNbSamples = static_cast<std::size_t>(FileInfos.frames) * myChannelsCount; myNbSamples = static_cast<std::size_t>(FileInfos.frames) * myChannelsCount;
myFilename = "";
myData = Data;
mySize = SizeInBytes;
return true; return true;
} }
@ -217,9 +187,6 @@ bool SoundFile::OpenWrite(const std::string& Filename, unsigned int ChannelsCoun
myChannelsCount = ChannelsCount; myChannelsCount = ChannelsCount;
mySampleRate = SampleRate; mySampleRate = SampleRate;
myNbSamples = 0; myNbSamples = 0;
myFilename = "";
myData = NULL;
mySize = 0;
return true; return true;
} }
@ -257,6 +224,19 @@ void SoundFile::Write(const Int16* Data, std::size_t NbSamples)
} }
////////////////////////////////////////////////////////////
/// Move the current reading position in the file
////////////////////////////////////////////////////////////
void SoundFile::Seek(float TimeOffset)
{
if (myFile)
{
sf_count_t FrameOffset = static_cast<sf_count_t>(TimeOffset * mySampleRate);
sf_seek(myFile, FrameOffset, SEEK_SET);
}
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the internal format of an audio file according to /// Get the internal format of an audio file according to
/// its filename extension /// its filename extension

View File

@ -81,14 +81,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int GetSampleRate() const; unsigned int GetSampleRate() const;
////////////////////////////////////////////////////////////
/// Restart the sound from the beginning
///
/// \return True if restart was successful
///
////////////////////////////////////////////////////////////
bool Restart();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Open the sound file for reading /// Open the sound file for reading
/// ///
@ -142,6 +134,14 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Write(const Int16* Data, std::size_t NbSamples); void Write(const Int16* Data, std::size_t NbSamples);
////////////////////////////////////////////////////////////
/// Move the current reading position in the file
///
/// \param TimeOffset : New position, expressed in seconds
///
////////////////////////////////////////////////////////////
void Seek(float TimeOffset);
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -183,9 +183,6 @@ private :
std::size_t myNbSamples; ///< Total number of samples in the file std::size_t myNbSamples; ///< Total number of samples in the file
unsigned int myChannelsCount; ///< Number of channels used by the sound unsigned int myChannelsCount; ///< Number of channels used by the sound
unsigned int mySampleRate; ///< Number of samples per second unsigned int mySampleRate; ///< Number of samples per second
std::string myFilename; ///< Path of the file (valid if loaded from a file)
const char* myData; ///< Pointer to the file in memory (valid if loaded from memory)
std::size_t mySize; ///< Size of the file in memory (valid if loaded from memory)
}; };
} // namespace priv } // namespace priv

View File

@ -98,14 +98,13 @@ void SoundStream::Play()
return; return;
} }
// Notify the derived class // Move to the beginning
if (OnStart()) OnSeek(0);
{
// Start updating the stream in a separate thread to avoid blocking the application // Start updating the stream in a separate thread to avoid blocking the application
mySamplesProcessed = 0; mySamplesProcessed = 0;
myIsStreaming = true; myIsStreaming = true;
Launch(); Launch();
}
} }
@ -153,6 +152,24 @@ Sound::Status SoundStream::GetStatus() const
} }
////////////////////////////////////////////////////////////
/// Set the current playing position of the stream
////////////////////////////////////////////////////////////
void SoundStream::SetPlayingOffset(float TimeOffset)
{
// Stop the stream
Stop();
// Let the derived class update the current position
OnSeek(TimeOffset);
// Restart streaming
mySamplesProcessed = static_cast<unsigned int>(TimeOffset * mySampleRate * myChannelsCount);
myIsStreaming = true;
Launch();
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the current playing position of the stream /// Get the current playing position of the stream
/// ///
@ -245,15 +262,16 @@ void SoundStream::Run()
if (FillAndPushBuffer(Buffer)) if (FillAndPushBuffer(Buffer))
{ {
// User requested to stop: check if we must loop or really stop // User requested to stop: check if we must loop or really stop
if (myLoop && OnStart()) if (myLoop)
{ {
// Looping: mark the current buffer as the last one // Looping: restart and mark the current buffer as the last one
// (to know when to reset the sample count) // (to know when to reset the sample count)
OnSeek(0);
EndBuffer = Buffer; EndBuffer = Buffer;
} }
else else
{ {
// Not looping or restart failed: request stop // Not looping: request stop
RequestStop = true; RequestStop = true;
} }
} }
@ -337,15 +355,4 @@ void SoundStream::ClearQueue()
ALCheck(alSourceUnqueueBuffers(Sound::mySource, 1, &Buffer)); ALCheck(alSourceUnqueueBuffers(Sound::mySource, 1, &Buffer));
} }
////////////////////////////////////////////////////////////
/// Called when the sound restarts
////////////////////////////////////////////////////////////
bool SoundStream::OnStart()
{
// Does nothing by default
return true;
}
} // namespace sf } // namespace sf