diff --git a/agb-fixnum/src/lib.rs b/agb-fixnum/src/lib.rs index f9df1f38..a4196b24 100644 --- a/agb-fixnum/src/lib.rs +++ b/agb-fixnum/src/lib.rs @@ -79,6 +79,8 @@ pub trait FixedWidthUnsignedInteger: fn ten() -> Self; /// Converts an i32 to it's own representation, panics on failure fn from_as_i32(v: i32) -> Self; + /// Returns (a * b) >> N + fn upcast_multiply(a: Self, b: Self, n: usize) -> Self; } /// Trait for an integer that includes negation @@ -89,7 +91,7 @@ pub trait FixedWidthSignedInteger: FixedWidthUnsignedInteger + Neg { + ($T: ty, $Upcast: ty) => { impl FixedWidthUnsignedInteger for $T { #[inline(always)] fn zero() -> Self { @@ -107,6 +109,10 @@ macro_rules! fixed_width_unsigned_integer_impl { fn from_as_i32(v: i32) -> Self { v as $T } + #[inline(always)] + fn upcast_multiply(a: Self, b: Self, n: usize) -> Self { + (((a as $Upcast) * (b as $Upcast)) >> n) as $T + } } }; } @@ -122,12 +128,11 @@ macro_rules! fixed_width_signed_integer_impl { }; } -fixed_width_unsigned_integer_impl!(u8); -fixed_width_unsigned_integer_impl!(i16); -fixed_width_unsigned_integer_impl!(u16); -fixed_width_unsigned_integer_impl!(i32); -fixed_width_unsigned_integer_impl!(u32); -fixed_width_unsigned_integer_impl!(usize); +fixed_width_unsigned_integer_impl!(u8, u32); +fixed_width_unsigned_integer_impl!(i16, i32); +fixed_width_unsigned_integer_impl!(u16, u32); +fixed_width_unsigned_integer_impl!(i32, i64); +fixed_width_unsigned_integer_impl!(u32, u64); fixed_width_signed_integer_impl!(i16); fixed_width_signed_integer_impl!(i32); @@ -204,9 +209,7 @@ where { type Output = Self; fn mul(self, rhs: Num) -> Self::Output { - Num(((self.floor() * rhs.floor()) << N) - + (self.floor() * rhs.frac() + rhs.floor() * self.frac()) - + ((self.frac() * rhs.frac()) >> N)) + Num(I::upcast_multiply(self.0, rhs.0, N)) } } diff --git a/agb/examples/mixer_basic.rs b/agb/examples/mixer_basic.rs index 80375d77..97403e8b 100644 --- a/agb/examples/mixer_basic.rs +++ b/agb/examples/mixer_basic.rs @@ -26,7 +26,7 @@ fn main(mut gba: Gba) -> ! { { if let Some(channel) = mixer.channel(&channel_id) { let half: Num = num!(0.5); - let half_usize: Num = num!(0.5); + let half_usize: Num = num!(0.5); match input.x_tri() { Tri::Negative => channel.panning(-half), Tri::Zero => channel.panning(0), diff --git a/agb/src/sound/mixer/mod.rs b/agb/src/sound/mixer/mod.rs index ca2a36ab..0bff6c50 100644 --- a/agb/src/sound/mixer/mod.rs +++ b/agb/src/sound/mixer/mod.rs @@ -224,10 +224,10 @@ impl Frequency { /// ``` pub struct SoundChannel { data: &'static [u8], - pos: Num, + pos: Num, should_loop: bool, - playback_speed: Num, + playback_speed: Num, volume: Num, // between 0 and 1 panning: Num, // between -1 and 1 @@ -336,7 +336,7 @@ impl SoundChannel { /// Note that this only works for mono sounds. Stereo sounds will not change /// how fast they play. #[inline(always)] - pub fn playback(&mut self, playback_speed: impl Into>) -> &mut Self { + pub fn playback(&mut self, playback_speed: impl Into>) -> &mut Self { self.playback_speed = playback_speed.into(); self } @@ -392,13 +392,13 @@ impl SoundChannel { /// Gets how far along the sound has played. #[inline] #[must_use] - pub fn pos(&self) -> Num { + pub fn pos(&self) -> Num { self.pos } /// Sets the playback position #[inline] - pub fn set_pos(&mut self, pos: impl Into>) -> &mut Self { + pub fn set_pos(&mut self, pos: impl Into>) -> &mut Self { self.pos = pos.into(); self } diff --git a/agb/src/sound/mixer/sw_mixer.rs b/agb/src/sound/mixer/sw_mixer.rs index 8984f842..1962fef9 100644 --- a/agb/src/sound/mixer/sw_mixer.rs +++ b/agb/src/sound/mixer/sw_mixer.rs @@ -24,7 +24,7 @@ extern "C" { fn agb_rs__mixer_add( sound_data: *const u8, sound_buffer: *mut Num, - playback_speed: Num, + playback_speed: Num, left_amount: Num, right_amount: Num, ); @@ -415,8 +415,8 @@ impl MixerBuffer { channel.playback_speed }; - if (channel.pos + playback_speed * self.frequency.buffer_size()).floor() - >= channel.data.len() + if (channel.pos + playback_speed * self.frequency.buffer_size() as u32).floor() + >= channel.data.len() as u32 { // TODO: This should probably play what's left rather than skip the last bit if channel.should_loop { @@ -431,7 +431,7 @@ impl MixerBuffer { if channel.is_stereo { unsafe { agb_rs__mixer_add_stereo( - channel.data.as_ptr().add(channel.pos.floor()), + channel.data.as_ptr().add(channel.pos.floor() as usize), working_buffer.as_mut_ptr(), channel.volume, ); @@ -442,7 +442,7 @@ impl MixerBuffer { unsafe { agb_rs__mixer_add( - channel.data.as_ptr().add(channel.pos.floor()), + channel.data.as_ptr().add(channel.pos.floor() as usize), working_buffer.as_mut_ptr(), playback_speed, left_amount, @@ -452,7 +452,7 @@ impl MixerBuffer { } } - channel.pos += playback_speed * self.frequency.buffer_size(); + channel.pos += playback_speed * self.frequency.buffer_size() as u32; } let write_buffer = free(|cs| self.state.borrow(cs).borrow_mut().active_advanced());