better length handling
This commit is contained in:
+36
-16
@@ -222,8 +222,8 @@ void RageSound::SetLengthSeconds(float secs)
|
|||||||
m_LengthSeconds = secs;
|
m_LengthSeconds = secs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start playing from m_StartSeconds. TODO: a way to start playing
|
/* Start playing from the current position. If the sound is already
|
||||||
* from the current pos (unpause) */
|
* playing, Stop is called. */
|
||||||
void RageSound::Play()
|
void RageSound::Play()
|
||||||
{
|
{
|
||||||
LockMutex L(SOUNDMAN->lock);
|
LockMutex L(SOUNDMAN->lock);
|
||||||
@@ -231,8 +231,6 @@ void RageSound::Play()
|
|||||||
if(playing) Stop();
|
if(playing) Stop();
|
||||||
playing = true;
|
playing = true;
|
||||||
|
|
||||||
SetPositionSeconds(m_StartSeconds);
|
|
||||||
|
|
||||||
// Tell the sound manager to start mixing us
|
// Tell the sound manager to start mixing us
|
||||||
SOUNDMAN->StartMixing(this);
|
SOUNDMAN->StartMixing(this);
|
||||||
}
|
}
|
||||||
@@ -316,21 +314,40 @@ int RageSound::GetPCM(char *buffer, int size, int sampleno)
|
|||||||
while(size)
|
while(size)
|
||||||
{
|
{
|
||||||
int got;
|
int got;
|
||||||
|
int MaxBytes;
|
||||||
|
if(m_LengthSeconds != -1)
|
||||||
|
{
|
||||||
|
/* We have a length; only read up to the end. MaxPosition is the
|
||||||
|
* sample position of the end. */
|
||||||
|
int MaxPosition = int((m_StartSeconds + m_LengthSeconds) * samplerate);
|
||||||
|
|
||||||
|
/* Number of bytes until MaxPosition. */
|
||||||
|
MaxBytes = (MaxPosition - position) * samplesize;
|
||||||
|
|
||||||
|
/* If it's negative, we're past the end, so cap it at 0. */
|
||||||
|
MaxBytes = max(0, MaxBytes);
|
||||||
|
|
||||||
|
/* Don't read more than size. */
|
||||||
|
MaxBytes = min(MaxBytes, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MaxBytes = size;
|
||||||
|
|
||||||
if(position < 0) {
|
if(position < 0) {
|
||||||
/* We havn't *really* started playing yet, so just feed silence. How
|
/* We havn't *really* started playing yet, so just feed silence. How
|
||||||
* many more bytes of silence do we need? */
|
* many more bytes of silence do we need? */
|
||||||
got = -position * samplesize;
|
got = -position * samplesize;
|
||||||
got = min(got, size);
|
got = min(got, MaxBytes);
|
||||||
memset(buffer, 0, got);
|
memset(buffer, 0, got);
|
||||||
} else if(big) {
|
} else if(big) {
|
||||||
/* Feed data out of our streaming buffer. */
|
/* Feed data out of our streaming buffer. */
|
||||||
ASSERT(stream.Sample);
|
ASSERT(stream.Sample);
|
||||||
got = min(int(stream.buf.size()), size);
|
got = min(int(stream.buf.size()), MaxBytes);
|
||||||
stream.buf.read(buffer, got);
|
stream.buf.read(buffer, got);
|
||||||
} else {
|
} else {
|
||||||
/* Feed data out of our full buffer. */
|
/* Feed data out of our full buffer. */
|
||||||
int byte_pos = position * samplesize;
|
int byte_pos = position * samplesize;
|
||||||
got = min(int(full_buf.size())-byte_pos, size);
|
got = min(int(full_buf.size())-byte_pos, MaxBytes);
|
||||||
got = max(got, 0);
|
got = max(got, 0);
|
||||||
if(got)
|
if(got)
|
||||||
memcpy(buffer, full_buf.data()+byte_pos, got);
|
memcpy(buffer, full_buf.data()+byte_pos, got);
|
||||||
@@ -354,14 +371,22 @@ int RageSound::GetPCM(char *buffer, int size, int sampleno)
|
|||||||
/* If we've passed the stop point (m_StartSeconds+m_LengthSeconds), pretend
|
/* If we've passed the stop point (m_StartSeconds+m_LengthSeconds), pretend
|
||||||
* we've hit EOF. */
|
* we've hit EOF. */
|
||||||
if(m_LengthSeconds != -1 &&
|
if(m_LengthSeconds != -1 &&
|
||||||
float(position)/samplerate > m_StartSeconds+m_LengthSeconds)
|
float(position)/samplerate >= m_StartSeconds+m_LengthSeconds)
|
||||||
HitEOF = true;
|
HitEOF = true;
|
||||||
|
|
||||||
if(!HitEOF)
|
if(!HitEOF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(Loop && m_LengthSeconds == 0)
|
||||||
|
{
|
||||||
|
/* Oops. Looping with seconds == 0 doesn't make much sense.
|
||||||
|
* It might happen if we're given an empty sound file as input,
|
||||||
|
* though. Let's just stop. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* We're at EOF. If we're not looping, just stop. */
|
/* We're at EOF. If we're not looping, just stop. */
|
||||||
if(Loop)
|
if(Loop && m_LengthSeconds != 0)
|
||||||
{
|
{
|
||||||
/* Rewind and start over. */
|
/* Rewind and start over. */
|
||||||
SetPositionSeconds(m_StartSeconds);
|
SetPositionSeconds(m_StartSeconds);
|
||||||
@@ -443,14 +468,9 @@ void RageSound::Stop()
|
|||||||
/* Tell the sound manager to stop mixing this sound. */
|
/* Tell the sound manager to stop mixing this sound. */
|
||||||
SOUNDMAN->StopMixing(this);
|
SOUNDMAN->StopMixing(this);
|
||||||
|
|
||||||
if(big) {
|
SetPositionSeconds(m_StartSeconds);
|
||||||
ASSERT(stream.Sample);
|
|
||||||
Sound_Rewind(stream.Sample);
|
|
||||||
stream.buf.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
playing = false;
|
playing = false;
|
||||||
position = 0;
|
|
||||||
for(int i = 0; i < 4; ++i)
|
for(int i = 0; i < 4; ++i)
|
||||||
pos_map[i].clear();
|
pos_map[i].clear();
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-13
@@ -82,6 +82,22 @@ public:
|
|||||||
~RageSound();
|
~RageSound();
|
||||||
RageSound(const RageSound &cpy);
|
RageSound(const RageSound &cpy);
|
||||||
|
|
||||||
|
|
||||||
|
/* Called only by the sound drivers: */
|
||||||
|
/* This function should return the number of bytes actually put into buffer.
|
||||||
|
* If less than size is returned, it signals the stream to stop; once it's
|
||||||
|
* flushed, SoundStopped will be called. Until then, SOUNDMAN->GetPosition
|
||||||
|
* can still be called (the sound is still playing). */
|
||||||
|
int GetPCM(char *buffer, int size, int sampleno);
|
||||||
|
|
||||||
|
/* Called by the sound driver when a sound has actually finished stopping
|
||||||
|
* normally. Not called when Stop() is called to stop the sound prematurely. */
|
||||||
|
void SoundStopped();
|
||||||
|
|
||||||
|
void Update(float delta);
|
||||||
|
|
||||||
|
/* User API from here on: */
|
||||||
|
|
||||||
/* If cache is true, we'll preload the entire file into memory if it's
|
/* If cache is true, we'll preload the entire file into memory if it's
|
||||||
* small enough. False is only generally used when we're going to do
|
* small enough. False is only generally used when we're going to do
|
||||||
* operations on a file but not actually play it (eg. to find out
|
* operations on a file but not actually play it (eg. to find out
|
||||||
@@ -91,8 +107,11 @@ public:
|
|||||||
void LoadAndPlayIfNotAlready( CString sSoundFilePath );
|
void LoadAndPlayIfNotAlready( CString sSoundFilePath );
|
||||||
void Unload();
|
void Unload();
|
||||||
|
|
||||||
|
/* If enabled, then the sound will automatically stop when it reaches
|
||||||
|
* the end; otherwise it'll feed silence until Stop() is called. */
|
||||||
void SetAutoStop(bool yes=true) { AutoStop=yes; }
|
void SetAutoStop(bool yes=true) { AutoStop=yes; }
|
||||||
bool GetAutoStop() const { return AutoStop; }
|
bool GetAutoStop() const { return AutoStop; }
|
||||||
|
|
||||||
void SetStartSeconds(float secs = 0); /* default = beginning */
|
void SetStartSeconds(float secs = 0); /* default = beginning */
|
||||||
void SetLengthSeconds(float secs = -1); /* default = no length limit */
|
void SetLengthSeconds(float secs = -1); /* default = no length limit */
|
||||||
void Play();
|
void Play();
|
||||||
@@ -111,19 +130,6 @@ public:
|
|||||||
|
|
||||||
/* Query only: */
|
/* Query only: */
|
||||||
bool IsStreaming() const { return big; }
|
bool IsStreaming() const { return big; }
|
||||||
|
|
||||||
/* Called only by the sound drivers: */
|
|
||||||
/* This function should return the number of bytes actually put into buffer.
|
|
||||||
* If less than size is returned, it signals the stream to stop; once it's
|
|
||||||
* flushed, SoundStopped will be called. Until then, SOUNDMAN->GetPosition
|
|
||||||
* can still be called (the sound is still playing). */
|
|
||||||
int GetPCM(char *buffer, int size, int sampleno);
|
|
||||||
|
|
||||||
/* Called by the sound driver when a sound has actually finished stopping
|
|
||||||
* normally. Not called when Stop() is called to stop the sound prematurely. */
|
|
||||||
void SoundStopped();
|
|
||||||
|
|
||||||
void Update(float delta);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user