audio: Add support for setting the loop start time of sounds
Closes #1347
This commit is contained in:
parent
d1d0dab990
commit
c28bd047b3
|
|
@ -42,6 +42,10 @@ PUBLISHED:
|
|||
virtual void set_loop_count(unsigned long loop_count=1) = 0;
|
||||
virtual unsigned long get_loop_count() const = 0;
|
||||
|
||||
// loop_start: 0 = beginning. expressed in seconds. inits to 0.
|
||||
virtual void set_loop_start(PN_stdfloat loop_start=0) = 0;
|
||||
virtual PN_stdfloat get_loop_start() const = 0;
|
||||
|
||||
/**
|
||||
* Control time position within the sound, in seconds. This is similar (in
|
||||
* concept) to the seek position within a file. The value starts at 0.0 (the
|
||||
|
|
|
|||
|
|
@ -58,6 +58,14 @@ unsigned long NullAudioSound::get_loop_count() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void NullAudioSound::set_loop_start(PN_stdfloat) {
|
||||
// Intentionally blank.
|
||||
}
|
||||
|
||||
PN_stdfloat NullAudioSound::get_loop_start() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NullAudioSound::set_time(PN_stdfloat) {
|
||||
// Intentionally blank.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ public:
|
|||
void set_loop_count(unsigned long);
|
||||
unsigned long get_loop_count() const;
|
||||
|
||||
void set_loop_start(PN_stdfloat);
|
||||
PN_stdfloat get_loop_start() const;
|
||||
|
||||
void set_time(PN_stdfloat);
|
||||
PN_stdfloat get_time() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -339,6 +339,49 @@ get_loop_count() const {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time at which subsequent loops will begin.
|
||||
* A value of 0 indicates the beginning of the audio.
|
||||
*/
|
||||
void FmodAudioSound::
|
||||
set_loop_start(PN_stdfloat loop_start) {
|
||||
ReMutexHolder holder(FmodAudioManager::_lock);
|
||||
audio_debug("FmodAudioSound::set_loop_start() Setting the sound's loop start to: " << loop_start);
|
||||
|
||||
FMOD_RESULT result;
|
||||
unsigned int length;
|
||||
|
||||
result = _sound->getLength(&length, FMOD_TIMEUNIT_MS);
|
||||
fmod_audio_errcheck("_sound->getLength()", result);
|
||||
|
||||
unsigned int loop_start_int = (unsigned int) (loop_start * 1000.0);
|
||||
|
||||
if (loop_start_int >= length) {
|
||||
audio_debug("FmodAudioSound::set_loop_start() Would loop after end of track, setting start to 0");
|
||||
loop_start_int = 0;
|
||||
}
|
||||
|
||||
result = _sound->setLoopPoints(loop_start_int, FMOD_TIMEUNIT_MS, length, FMOD_TIMEUNIT_MS);
|
||||
fmod_audio_errcheck("_sound->setLoopPoints()", result);
|
||||
audio_debug("FmodAudioSound::set_loop_start() Sound's loop start should be set to: " << loop_start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time at which subsequent loops will begin.
|
||||
* A value of 0 indicates the beginning of the audio.
|
||||
*/
|
||||
PN_stdfloat FmodAudioSound::
|
||||
get_loop_start() const {
|
||||
ReMutexHolder holder(FmodAudioManager::_lock);
|
||||
FMOD_RESULT result;
|
||||
unsigned int loop_start;
|
||||
|
||||
result = _sound->getLoopPoints(&loop_start, FMOD_TIMEUNIT_MS, nullptr, FMOD_TIMEUNIT_MS);
|
||||
fmod_audio_errcheck("_sound->getLoopPoints()", result);
|
||||
|
||||
return ((double)loop_start) / 1000.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time at which the next play() operation will begin. If we are
|
||||
* already playing, skips to that time immediatey.
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ public:
|
|||
void set_loop_count(unsigned long loop_count=1);
|
||||
unsigned long get_loop_count() const;
|
||||
|
||||
// loop_start: 0 = beginning. expressed in seconds. inits to 0.
|
||||
void set_loop_start(PN_stdfloat loop_start=0);
|
||||
PN_stdfloat get_loop_start() const;
|
||||
|
||||
// 0 = beginning; length() = end. inits to 0.0.
|
||||
void set_time(PN_stdfloat start_time=0.0);
|
||||
PN_stdfloat get_time() const;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ OpenALAudioSound(OpenALAudioManager* manager,
|
|||
_drop_off_factor(1.0f),
|
||||
_length(0.0),
|
||||
_loop_count(1),
|
||||
_loop_start(0),
|
||||
_desired_mode(mode),
|
||||
_start_time(0.0),
|
||||
_current_time(0.0),
|
||||
|
|
@ -279,6 +280,36 @@ get_loop_count() const {
|
|||
return _loop_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time at which subsequent loops will begin.
|
||||
* A value of 0 indicates the beginning of the audio.
|
||||
*/
|
||||
void OpenALAudioSound::
|
||||
set_loop_start(PN_stdfloat loop_start) {
|
||||
ReMutexHolder holder(OpenALAudioManager::_lock);
|
||||
|
||||
if (!is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loop_start >= _length) {
|
||||
// This loop would begin after the song ends.
|
||||
// Not a good idea.
|
||||
loop_start = 0;
|
||||
}
|
||||
|
||||
_loop_start = loop_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time at which subsequent loops will begin.
|
||||
* A value of 0 indicates the beginning of the audio.
|
||||
*/
|
||||
PN_stdfloat OpenALAudioSound::
|
||||
get_loop_start() const {
|
||||
return _loop_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* When streaming audio, the computer is supposed to keep OpenAL's queue full.
|
||||
* However, there are times when the computer is running slow and the queue
|
||||
|
|
@ -389,7 +420,7 @@ read_stream_data(int bytelen, unsigned char *buffer) {
|
|||
int samples = (int)(remain * rate);
|
||||
if (samples <= 0) {
|
||||
_loops_completed += 1;
|
||||
cursor->seek(0.0);
|
||||
cursor->seek(_loop_start);
|
||||
continue;
|
||||
}
|
||||
if (_sd->_stream->ready() == 0) {
|
||||
|
|
@ -411,7 +442,7 @@ read_stream_data(int bytelen, unsigned char *buffer) {
|
|||
}
|
||||
if (samples == 0) {
|
||||
_loops_completed += 1;
|
||||
cursor->seek(0.0);
|
||||
cursor->seek(_loop_start);
|
||||
if (_playing_loops >= 1000000000) {
|
||||
// Prevent infinite loop if endlessly looping empty sound
|
||||
return fill;
|
||||
|
|
@ -535,7 +566,7 @@ push_fresh_buffers() {
|
|||
if (_sd->_sample) {
|
||||
while ((_loops_completed < _playing_loops) &&
|
||||
(_stream_queued.size() < 100)) {
|
||||
queue_buffer(_sd->_sample, 0,_loops_completed, 0.0);
|
||||
queue_buffer(_sd->_sample, 0,_loops_completed, _loop_start);
|
||||
_loops_completed += 1;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ public:
|
|||
void set_loop_count(unsigned long loop_count=1);
|
||||
unsigned long get_loop_count() const;
|
||||
|
||||
// loop_start: 0 = beginning. expressed in seconds. inits to 0.
|
||||
void set_loop_start(PN_stdfloat loop_start=0);
|
||||
PN_stdfloat get_loop_start() const;
|
||||
|
||||
// 0 = beginning; length() = end. inits to 0.0.
|
||||
void set_time(PN_stdfloat time=0.0);
|
||||
PN_stdfloat get_time() const;
|
||||
|
|
@ -156,10 +160,11 @@ private:
|
|||
PN_stdfloat _max_dist;
|
||||
PN_stdfloat _drop_off_factor;
|
||||
|
||||
double _length;
|
||||
int _loop_count;
|
||||
double _length;
|
||||
int _loop_count;
|
||||
PN_stdfloat _loop_start;
|
||||
|
||||
int _desired_mode;
|
||||
int _desired_mode;
|
||||
|
||||
// The calibrated clock is initialized when the sound starts playing, and is
|
||||
// periodically corrected thereafter.
|
||||
|
|
|
|||
Loading…
Reference in New Issue