Use saturating_add for the samples, and fix the mixer

This commit is contained in:
Pierre Krieger 2017-02-08 17:08:31 +01:00
parent b1a560eb41
commit e06f1f84e7
3 changed files with 23 additions and 9 deletions

View file

@ -1,6 +1,4 @@
use std::marker::PhantomData;
use std::ops::Add;
use std::ops::AddAssign;
use cpal;
/// Converts the samples data type to `O`.
@ -65,16 +63,18 @@ impl<I, O> ExactSizeIterator for DataConverter<I, O>
///
/// You can implement this trait on your own type as well if you wish so.
///
pub trait Sample: cpal::Sample + Add + AddAssign {
pub trait Sample: cpal::Sample {
/// Linear interpolation between two samples.
///
/// The result should be equal to
/// `first * numerator / denominator + second * (1 - numerator / denominator)`.
// TODO: remove ; not necessary
fn lerp(first: Self, second: Self, numerator: u32, denominator: u32) -> Self;
/// Multiplies the value of this sample by the given amount.
fn amplify(self, value: f32) -> Self;
/// Calls `saturating_add` on the sample.
fn saturating_add(self, other: Self) -> Self;
/// Returns the value corresponding to the absence of sound.
fn zero_value() -> Self;
@ -100,6 +100,11 @@ impl Sample for u16 {
self.to_i16().amplify(value).to_u16()
}
#[inline]
fn saturating_add(self, other: u16) -> u16 {
self.saturating_add(other)
}
#[inline]
fn zero_value() -> u16 {
32768
@ -144,6 +149,11 @@ impl Sample for i16 {
((self as f32) * value) as i16
}
#[inline]
fn saturating_add(self, other: i16) -> i16 {
self.saturating_add(other)
}
#[inline]
fn zero_value() -> i16 {
0
@ -191,6 +201,11 @@ impl Sample for f32 {
self * value
}
#[inline]
fn saturating_add(self, other: f32) -> f32 {
self + other
}
#[inline]
fn zero_value() -> f32 {
0.0

View file

@ -106,7 +106,7 @@ impl<S> Iterator for DynamicMixer<S> where S: Sample + Send + 'static {
let mut sum = S::zero_value();
for (num, src) in self.current_sources.iter_mut().enumerate() {
if let Some(val) = src.next() {
sum += val;
sum = sum.saturating_add(val);
} else {
to_drop.push(num);
}

View file

@ -47,11 +47,10 @@ impl<I1, I2> Iterator for Mix<I1, I2>
let s1 = self.input1.next();
let s2 = self.input2.next();
// FIXME: shouldn't lerp, this is wrong
match (s1, s2) {
(Some(s1), Some(s2)) => Some(Sample::lerp(s1, s2, 1, 2)),
(Some(s1), None) => Some(Sample::lerp(s1, Sample::zero_value(), 1, 2)),
(None, Some(s2)) => Some(Sample::lerp(s2, Sample::zero_value(), 1, 2)),
(Some(s1), Some(s2)) => Some(s1.saturating_add(s2)),
(Some(s1), None) => Some(s1),
(None, Some(s2)) => Some(s2),
(None, None) => None,
}
}