mirror of
https://github.com/RustAudio/rodio
synced 2024-12-12 13:12:30 +00:00
More synth work, but think I'm going to startover
This commit is contained in:
parent
fc22b37f1b
commit
128fa74554
2 changed files with 57 additions and 34 deletions
|
@ -30,7 +30,7 @@ pub use self::skippable::Skippable;
|
|||
pub use self::spatial::Spatial;
|
||||
pub use self::speed::Speed;
|
||||
pub use self::stoppable::Stoppable;
|
||||
pub use self::synth_waveforms::SynthWaveform;
|
||||
pub use self::synth_waveforms::{BufferedSynthWaveform, SynthWaveformFunction};
|
||||
pub use self::take::TakeDuration;
|
||||
pub use self::uniform::UniformSourceIterator;
|
||||
pub use self::zero::Zero;
|
||||
|
|
|
@ -4,6 +4,16 @@ use std::time::Duration;
|
|||
use super::SeekError;
|
||||
use crate::{buffer::SamplesBuffer, source::Repeat, Source};
|
||||
|
||||
|
||||
/// Express a frequency as a rational number.
|
||||
/// .0 Cycles per time quanta
|
||||
/// .1 Time quanta per second
|
||||
///
|
||||
/// Examples:
|
||||
/// 1000,1 1000 Hz
|
||||
/// 12345,100 123.45 Hz
|
||||
pub struct RationalFrequency(u32, u32);
|
||||
|
||||
/// Syntheizer waveform functions. All of the synth waveforms are in the
|
||||
/// codomain [-1.0, 1.0].
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -15,60 +25,67 @@ pub enum SynthWaveformFunction {
|
|||
}
|
||||
|
||||
impl SynthWaveformFunction {
|
||||
/// Create a `SamplesBuffer` containing one period of `self` with the given
|
||||
/// sample rate and frequency.
|
||||
pub fn create_buffer(&self, sample_rate: u32, frequency: u32) -> SamplesBuffer<f32> {
|
||||
let p: usize = (sample_rate / frequency) as usize;
|
||||
let mut samples_vec = vec![0.0f32; p];
|
||||
/// Create a single sample for the given waveform
|
||||
#[inline]
|
||||
pub fn render(&self, sample: u32, period: u32) -> f32 {
|
||||
let i_div_p: f32 = sample as f32 / period as f32;
|
||||
|
||||
fn _pwm_impl(duty: f32, t: f32) -> f32 {
|
||||
if t < duty.abs() {
|
||||
1f32
|
||||
} else {
|
||||
-1f32
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..p {
|
||||
let i_div_p: f32 = i as f32 / p as f32;
|
||||
samples_vec[i] = match self {
|
||||
Self::Sine => (TAU * i_div_p).sin(),
|
||||
Self::Triangle => 4.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()).abs() - 1f32,
|
||||
Self::Square => {
|
||||
match self {
|
||||
Self::Sine => (TAU * i_div_p).sin(),
|
||||
Self::Triangle => 04.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()).abs() - 1f32,
|
||||
Self::Square => {
|
||||
if i_div_p < 0.5f32 {
|
||||
1.0f32
|
||||
} else {
|
||||
-1.0f32
|
||||
}
|
||||
}
|
||||
Self::Sawtooth => 2.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()),
|
||||
}
|
||||
},
|
||||
Self::Sawtooth => 2.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `SamplesBuffer` containing one period of `self` with the given
|
||||
/// sample rate and frequency.
|
||||
pub fn create_buffer(
|
||||
&self,
|
||||
sample_rate: cpal::SampleRate,
|
||||
frequency: u32,
|
||||
) -> SamplesBuffer<f32> {
|
||||
let period: usize = (sample_rate.0 / frequency) as usize;
|
||||
let mut samples_vec = vec![0.0f32; period];
|
||||
|
||||
for i in 0..period {
|
||||
samples_vec[i] = self.render(i as u32, period as u32);
|
||||
}
|
||||
|
||||
SamplesBuffer::new(1, sample_rate, samples_vec)
|
||||
SamplesBuffer::new(1, sample_rate.0, samples_vec)
|
||||
}
|
||||
}
|
||||
|
||||
/// An infinite source that produces one of a selection of synthesizer
|
||||
/// waveforms from a buffered source.
|
||||
#[derive(Clone)]
|
||||
pub struct SynthWaveform {
|
||||
pub struct BufferedSynthWaveform {
|
||||
input: Repeat<SamplesBuffer<f32>>,
|
||||
}
|
||||
|
||||
impl SynthWaveform {
|
||||
impl BufferedSynthWaveform {
|
||||
/// Create a new `SynthWaveform` object that generates an endless waveform
|
||||
/// `f`.
|
||||
#[inline]
|
||||
pub fn new(sample_rate: u32, frequency: u32, f: SynthWaveformFunction) -> SynthWaveform {
|
||||
pub fn new(
|
||||
sample_rate: cpal::SampleRate,
|
||||
frequency: u32,
|
||||
f: SynthWaveformFunction,
|
||||
) -> BufferedSynthWaveform {
|
||||
let buffer = f.create_buffer(sample_rate, frequency);
|
||||
SynthWaveform {
|
||||
BufferedSynthWaveform {
|
||||
input: buffer.repeat_infinite(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for SynthWaveform {
|
||||
impl Iterator for BufferedSynthWaveform {
|
||||
type Item = f32;
|
||||
|
||||
#[inline]
|
||||
|
@ -77,7 +94,7 @@ impl Iterator for SynthWaveform {
|
|||
}
|
||||
}
|
||||
|
||||
impl Source for SynthWaveform {
|
||||
impl Source for BufferedSynthWaveform {
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
self.input.current_frame_len()
|
||||
|
@ -110,7 +127,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn square() {
|
||||
let mut wf = SynthWaveform::new(1000, 250, SynthWaveformFunction::Square);
|
||||
let mut wf =
|
||||
BufferedSynthWaveform::new(cpal::SampleRate(1000), 250, SynthWaveformFunction::Square);
|
||||
assert_eq!(wf.next(), Some(1.0f32));
|
||||
assert_eq!(wf.next(), Some(1.0f32));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
|
@ -123,7 +141,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn triangle() {
|
||||
let mut wf = SynthWaveform::new(8000, 1000, SynthWaveformFunction::Triangle);
|
||||
let mut wf = BufferedSynthWaveform::new(
|
||||
cpal::SampleRate(8000),
|
||||
1000,
|
||||
SynthWaveformFunction::Triangle,
|
||||
);
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
assert_eq!(wf.next(), Some(-0.5f32));
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
|
@ -144,7 +166,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn saw() {
|
||||
let mut wf = SynthWaveform::new(200, 50, SynthWaveformFunction::Sawtooth);
|
||||
let mut wf =
|
||||
BufferedSynthWaveform::new(cpal::SampleRate(200), 50, SynthWaveformFunction::Sawtooth);
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
|
|
Loading…
Reference in a new issue