fixes, etc.

This commit is contained in:
Glenn Maynard
2002-12-18 06:44:56 +00:00
parent cb10e7ece2
commit 06853d3663
2 changed files with 110 additions and 81 deletions
+92 -76
View File
@@ -74,8 +74,11 @@ RageSound::RageSound()
position = 0; position = 0;
playing = false; playing = false;
Loop = false; Loop = false;
AutoStop = true;
speed = 1.0f; speed = 1.0f;
stream.buf.reserve(internal_buffer_size); stream.buf.reserve(internal_buffer_size);
m_StartSeconds = 0;
m_LengthSeconds = -1;
/* Register ourselves, so we receive Update()s. */ /* Register ourselves, so we receive Update()s. */
SOUNDMAN->all_sounds.insert(this); SOUNDMAN->all_sounds.insert(this);
@@ -100,6 +103,7 @@ RageSound::RageSound(const RageSound &cpy)
Loop = false; Loop = false;
speed = 1.0f; speed = 1.0f;
stream.buf.reserve(internal_buffer_size); stream.buf.reserve(internal_buffer_size);
AutoStop = cpy.AutoStop;
/* Copy some of it; don't copy the playing state. */ /* Copy some of it; don't copy the playing state. */
big = cpy.big; big = cpy.big;
@@ -205,22 +209,26 @@ void RageSound::Load(CString sSoundFilePath, bool cache)
position = 0; position = 0;
} }
void RageSound::Play( bool bLoop, float fStartSeconds, float fLengthSeconds ) void RageSound::SetStartSeconds( float secs )
{
m_StartSeconds = secs;
}
void RageSound::SetLengthSeconds(float secs)
{
m_LengthSeconds = secs;
}
/* Start playing from m_StartSeconds. TODO: a way to start playing
* from the current pos (unpause) */
void RageSound::Play()
{ {
LockMutex L(SOUNDMAN->lock); LockMutex L(SOUNDMAN->lock);
if(playing) Stop(); if(playing) Stop();
playing = true; playing = true;
Loop = bLoop; SetPositionSeconds(m_StartSeconds);
if(fStartSeconds != -1000)
{
m_StartSeconds = fStartSeconds;
SetPositionSeconds(m_StartSeconds);
} else m_StartSeconds = 0;
m_LengthSeconds = fLengthSeconds;
// Tell the sound manager to start mixing us // Tell the sound manager to start mixing us
SOUNDMAN->StartMixing(this); SOUNDMAN->StartMixing(this);
@@ -307,7 +315,7 @@ int RageSound::GetPCM(char *buffer, int size, int sampleno)
int got; int got;
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, size);
memset(buffer, 0, got); memset(buffer, 0, got);
@@ -325,78 +333,84 @@ int RageSound::GetPCM(char *buffer, int size, int sampleno)
memcpy(buffer, full_buf.data()+byte_pos, got); memcpy(buffer, full_buf.data()+byte_pos, got);
} }
if(got) { if(!got)
/* Save this sampleno/position map. */ {
pos_map[3].push_back(pos_map_t(sampleno, position, got/samplesize)); /* We need more data. Find out if we've hit EOF. */
bool HitEOF = true;
int got_samples = got / samplesize; /* bytes -> samples */ if(big) {
/* If we don't have any data left buffered, fill the buffer by up to
/* This block goes from position to position+got_samples. */ * as much as we need. */
const float FADE_TIME = 1.5f; if(stream.buf.size() || stream.FillBuf(size))
HitEOF = false; /* we have more */
/* XXX: Loop shouldn't set fading; add a Fade_Time member? } else {
* unsigned byte_pos = position * samplesize; /* samples -> bytes */
* We want to fade when there's FADE_TIME seconds left, but if if(byte_pos < full_buf.size())
* m_LengthSeconds is -1, we don't know the length we're playing. HitEOF = false; /* we have more */
* (m_LengthSeconds is the length to play, not the length of the
* source.) If we don't know the length, don't fade. */
if(Loop) {
Sint16 *p = (Sint16 *) buffer;
int this_position = position;
for(int samp = 0; samp < got_samples; ++samp)
{
float fSecsUntilSilent = (m_StartSeconds + m_LengthSeconds) - float(this_position)/samplerate;
float fVolPercent = fSecsUntilSilent / FADE_TIME;
fVolPercent = clamp(fVolPercent, 0.f, 1.f);
for(int i = 0; i < channels; ++i) {
*p = short(*p * fVolPercent);
p++;
}
this_position++;
}
} }
/* If we've passed the stop point (m_StartSeconds+m_LengthSeconds), pretend
* we've hit EOF. */
if(m_LengthSeconds != -1 &&
float(position)/samplerate > m_StartSeconds+m_LengthSeconds)
HitEOF = true;
bytes_stored += got; if(!HitEOF)
position += got_samples; continue;
size -= got;
buffer += got; /* We're at EOF. If we're not looping, just stop. */
sampleno += got_samples; if(Loop)
{
/* Rewind and start over. */
SetPositionSeconds(m_StartSeconds);
continue;
}
if(AutoStop)
break;
/* We're out of data, but we're not going to stop, so fill in the
* rest with silence. */
memset(buffer, 0, size);
got = size;
} }
/* If we've filled the buffer, we're done. */ /* Save this sampleno/position map. */
if(!size) break; pos_map[3].push_back(pos_map_t(sampleno, position, got/samplesize));
/* We need more data. Find out if we've hit EOF. */ int got_samples = got / samplesize; /* bytes -> samples */
bool HitEOF = true;
if(big) { /* This block goes from position to position+got_samples. */
/* If we don't have any data left buffered, fill the buffer by up to const float FADE_TIME = 1.5f;
* as much as we need. */
if(stream.buf.size() || stream.FillBuf(size)) /* XXX: Loop shouldn't set fading; add a Fade_Time member?
HitEOF = false; /* we have more */ *
} else { * We want to fade when there's FADE_TIME seconds left, but if
unsigned byte_pos = position * samplesize; /* samples -> bytes */ * m_LengthSeconds is -1, we don't know the length we're playing.
if(byte_pos < full_buf.size()) * (m_LengthSeconds is the length to play, not the length of the
HitEOF = false; /* we have more */ * source.) If we don't know the length, don't fade. */
if(Loop && m_LengthSeconds != -1) {
Sint16 *p = (Sint16 *) buffer;
int this_position = position;
for(int samp = 0; samp < got_samples; ++samp)
{
float fSecsUntilSilent = (m_StartSeconds + m_LengthSeconds) - float(this_position)/samplerate;
float fVolPercent = fSecsUntilSilent / FADE_TIME;
fVolPercent = clamp(fVolPercent, 0.f, 1.f);
for(int i = 0; i < channels; ++i) {
*p = short(*p * fVolPercent);
p++;
}
this_position++;
}
} }
/* If we've passed the stop point (m_StartSeconds+m_LengthSeconds), pretend
* we've hit EOF. */
if(m_LengthSeconds != -1 &&
float(position)/samplerate > m_StartSeconds+m_LengthSeconds)
HitEOF = true;
if(!HitEOF) bytes_stored += got;
continue; position += got_samples;
size -= got;
/* We're at EOF. If we're not looping, just stop. */ buffer += got;
if(!Loop) sampleno += got_samples;
break;
/* Rewind and start over. */
SetPositionSeconds(m_StartSeconds);
} }
return bytes_stored; return bytes_stored;
@@ -460,7 +474,7 @@ float RageSound::GetLengthSeconds()
} }
} }
float RageSound::GetPositionSeconds() float RageSound::GetPositionSeconds() const
{ {
LockMutex L(SOUNDMAN->lock); LockMutex L(SOUNDMAN->lock);
@@ -556,6 +570,7 @@ void RageSound::SetPlaybackRate( float fScale )
speed = fScale; speed = fScale;
} }
/* This is used to start music. It probably belongs in RageSoundManager. */
void RageSound::LoadAndPlayIfNotAlready( CString sSoundFilePath ) void RageSound::LoadAndPlayIfNotAlready( CString sSoundFilePath )
{ {
SOUNDMAN->lock.Lock(); SOUNDMAN->lock.Lock();
@@ -564,7 +579,8 @@ void RageSound::LoadAndPlayIfNotAlready( CString sSoundFilePath )
SOUNDMAN->lock.Unlock(); SOUNDMAN->lock.Unlock();
Load( sSoundFilePath ); Load( sSoundFilePath );
Play( true ); SetLooping();
Play();
} }
void CircBuf::reserve(unsigned n) void CircBuf::reserve(unsigned n)
+17 -4
View File
@@ -57,7 +57,7 @@ class RageSound
CString m_sFilePath; CString m_sFilePath;
// float m_Rate; // float m_Rate;
/* If looping, the range to loop: */ /* The amount of data to play (or loop): */
float m_StartSeconds, m_LengthSeconds; float m_StartSeconds, m_LengthSeconds;
bool Loop; bool Loop;
@@ -68,6 +68,13 @@ class RageSound
float speed; float speed;
/* If true, the sound will stop when it reaches the end; otherwise it'll
* continue to move forward, feeding silence, which is useful to continue
* timing longer than the actual sound. (However, if this is false, the
* sound will never stop on its own unless destructed; it must be explitly
* stopped, and PlayCopy can't be used.) Default is true. Ignored when looping. */
bool AutoStop;
public: public:
RageSound(); RageSound();
~RageSound(); ~RageSound();
@@ -82,16 +89,22 @@ public:
void LoadAndPlayIfNotAlready( CString sSoundFilePath ); void LoadAndPlayIfNotAlready( CString sSoundFilePath );
void Unload(); void Unload();
void Play( bool bLoop = false, float fStartSeconds = -1000, float fLengthSeconds = -1 ); void SetAutoStop(bool yes=true) { AutoStop=yes; }
bool GetAutoStop() const { return AutoStop; }
void SetStartSeconds(float secs = 0); /* default = beginning */
void SetLengthSeconds(float secs = -1); /* default = no length limit */
void Play();
void Pause(); void Pause();
void Stop(); void Stop();
float GetLengthSeconds(); float GetLengthSeconds();
float GetPositionSeconds(); float GetPositionSeconds() const;
void SetPositionSeconds( float fSeconds ); void SetPositionSeconds( float fSeconds );
void SetPlaybackRate( float fScale ); void SetPlaybackRate( float fScale );
float GetPlaybackRate() const { return speed; } float GetPlaybackRate() const { return speed; }
bool IsPlaying() const { return playing; } bool IsPlaying() const { return playing; }
CString GetLoadedFilePath() const { return m_sFilePath; }; CString GetLoadedFilePath() const { return m_sFilePath; }
void SetLooping(bool yes=true) { Loop=yes; }
bool GetLooping() const { return Loop; }
/* Called only by the sound drivers: */ /* Called only by the sound drivers: */
/* This function should return the number of bytes actually put into buffer. /* This function should return the number of bytes actually put into buffer.