Looping points are an important feature but I have to find a nice way to integrate them to the public API. Using specific metadata is not an option, since SFML supports many standard audio formats.
I've implemented the looping point feature myself in an "old" version of SFML 2.0. I think, I only did minor edits in SoundStream.
You're only able to set the loop start point, where to go when the stream ends and looping is enabled.
// SoundStream.hpp //
class SFML_API SoundStream : SoundSource
{
public:
...
////////////////////////////////////////////////////////////
/// \brief Set whether or not the stream should loop after reaching the end
///
/// If set, the stream will restart from beginning after
/// reaching the end and so on, until it is stopped or
/// SetLoop(false) is called.
/// The default looping state for streams is false.
///
/// \param loop True to play in loop, false to play once
/// \param start Offset of loop start, in milliseconds
///
/// \see GetLoop
///
////////////////////////////////////////////////////////////
void SetLoop(bool loop, Uint32 start=0);
...
private:
...
bool myLoop; ///< Loop flag (true to loop, false to play once)
Uint32 myLoopStart; ///< Start point of loop in milliseconds
...
};
// SoundSource.cpp //
SoundStream::SoundStream() :
myThread (&SoundStream::Stream, this),
myIsStreaming (false),
myChannelsCount (0),
mySampleRate (0),
myFormat (0),
myLoop (false),
myLoopStart (0),
mySamplesProcessed(0)
{
}
...
void SoundStream::SetLoop(bool loop, Uint32 start)
{
myLoop = loop;
myLoopStart = start;
}
...
bool SoundStream::FillAndPushBuffer(unsigned int bufferNum)
{
bool requestStop = false;
// Acquire audio data
Chunk data = {NULL, 0};
if (!OnGetData(data))
{
// Mark the buffer as the last one (so that we know when to reset the playing position)
myEndBuffers[bufferNum] = true;
// Check if the stream must loop or stop
if (myLoop)
{
// Return to the beginning of the stream source
OnSeek(myLoopStart);
// If we previously had no data, try to fill the buffer once again
if (!data.Samples || (data.NbSamples == 0))
{
return FillAndPushBuffer(bufferNum);
}
}
else
{
// Not looping: request stop
requestStop = true;
}
}
// Fill the buffer if some data was returned
if (data.Samples && data.NbSamples)
{
unsigned int buffer = myBuffers[bufferNum];
// Fill the buffer
ALsizei size = static_cast<ALsizei>(data.NbSamples) * sizeof(Int16);
ALCheck(alBufferData(buffer, myFormat, data.Samples, size, mySampleRate));
// Push it into the sound queue
ALCheck(alSourceQueueBuffers(mySource, 1, &buffer));
}
return requestStop;
}
Hope it might help.