Add a concept of a restart point

This commit is contained in:
Gwilym Inzani 2023-07-16 22:57:12 +01:00
parent a0be2a333e
commit 1dd4c9fb83
2 changed files with 20 additions and 3 deletions

View file

@ -226,6 +226,7 @@ pub struct SoundChannel {
data: &'static [u8],
pos: Num<u32, 8>,
should_loop: bool,
restart_point: Num<u32, 8>,
playback_speed: Num<u32, 8>,
volume: Num<i16, 4>, // between 0 and 1
@ -276,6 +277,7 @@ impl SoundChannel {
priority: SoundPriority::Low,
volume: 1.into(),
is_stereo: false,
restart_point: 0.into(),
}
}
@ -319,6 +321,7 @@ impl SoundChannel {
priority: SoundPriority::High,
volume: 1.into(),
is_stereo: false,
restart_point: 0.into(),
}
}
@ -330,6 +333,20 @@ impl SoundChannel {
self
}
/// Sets the point at which the sample should restart once it loops. Does nothing
/// unless you also call [`should_loop()`].
///
/// Useful if your song has an introduction or similar.
#[inline(always)]
pub fn restart_point(&mut self, restart_point: impl Into<Num<u32, 8>>) -> &mut Self {
self.restart_point = restart_point.into();
assert!(
self.restart_point.floor() as usize <= self.data.len(),
"restart point must be shorter than the length of the sample"
);
self
}
/// Sets the speed at which this should channel should be played. Defaults
/// to 1 with values between 0 and 1 being slower above 1 being faster.
///

View file

@ -441,7 +441,7 @@ impl MixerBuffer {
>= channel.data.len() as u32
{
if channel.should_loop {
channel.pos = 0.into();
channel.pos = channel.restart_point * 2;
} else {
channel.is_done = true;
return;
@ -466,7 +466,7 @@ impl MixerBuffer {
let channel_len = Num::<u32, 8>::new(channel.data.len() as u32);
let mut playback_speed = channel.playback_speed;
while playback_speed >= channel_len {
while playback_speed >= channel_len - channel.restart_point {
playback_speed -= channel_len;
}
@ -484,7 +484,7 @@ impl MixerBuffer {
for i in 0..self.frequency.buffer_size() {
if channel.pos >= channel_len {
if channel.should_loop {
channel.pos -= channel_len;
channel.pos -= channel_len + channel.restart_point;
} else {
channel.is_done = true;
break;