mirror of
https://github.com/RustAudio/rodio
synced 2024-12-13 13:42:34 +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::spatial::Spatial;
|
||||||
pub use self::speed::Speed;
|
pub use self::speed::Speed;
|
||||||
pub use self::stoppable::Stoppable;
|
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::take::TakeDuration;
|
||||||
pub use self::uniform::UniformSourceIterator;
|
pub use self::uniform::UniformSourceIterator;
|
||||||
pub use self::zero::Zero;
|
pub use self::zero::Zero;
|
||||||
|
|
|
@ -4,6 +4,16 @@ use std::time::Duration;
|
||||||
use super::SeekError;
|
use super::SeekError;
|
||||||
use crate::{buffer::SamplesBuffer, source::Repeat, Source};
|
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
|
/// Syntheizer waveform functions. All of the synth waveforms are in the
|
||||||
/// codomain [-1.0, 1.0].
|
/// codomain [-1.0, 1.0].
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -15,60 +25,67 @@ pub enum SynthWaveformFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SynthWaveformFunction {
|
impl SynthWaveformFunction {
|
||||||
/// Create a `SamplesBuffer` containing one period of `self` with the given
|
/// Create a single sample for the given waveform
|
||||||
/// sample rate and frequency.
|
#[inline]
|
||||||
pub fn create_buffer(&self, sample_rate: u32, frequency: u32) -> SamplesBuffer<f32> {
|
pub fn render(&self, sample: u32, period: u32) -> f32 {
|
||||||
let p: usize = (sample_rate / frequency) as usize;
|
let i_div_p: f32 = sample as f32 / period as f32;
|
||||||
let mut samples_vec = vec![0.0f32; p];
|
|
||||||
|
|
||||||
fn _pwm_impl(duty: f32, t: f32) -> f32 {
|
match self {
|
||||||
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::Sine => (TAU * i_div_p).sin(),
|
||||||
Self::Triangle => 4.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()).abs() - 1f32,
|
Self::Triangle => 04.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()).abs() - 1f32,
|
||||||
Self::Square => {
|
Self::Square => {
|
||||||
if i_div_p < 0.5f32 {
|
if i_div_p < 0.5f32 {
|
||||||
1.0f32
|
1.0f32
|
||||||
} else {
|
} else {
|
||||||
-1.0f32
|
-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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplesBuffer::new(1, sample_rate, samples_vec)
|
/// 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.0, samples_vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An infinite source that produces one of a selection of synthesizer
|
/// An infinite source that produces one of a selection of synthesizer
|
||||||
/// waveforms from a buffered source.
|
/// waveforms from a buffered source.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SynthWaveform {
|
pub struct BufferedSynthWaveform {
|
||||||
input: Repeat<SamplesBuffer<f32>>,
|
input: Repeat<SamplesBuffer<f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SynthWaveform {
|
impl BufferedSynthWaveform {
|
||||||
/// Create a new `SynthWaveform` object that generates an endless waveform
|
/// Create a new `SynthWaveform` object that generates an endless waveform
|
||||||
/// `f`.
|
/// `f`.
|
||||||
#[inline]
|
#[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);
|
let buffer = f.create_buffer(sample_rate, frequency);
|
||||||
SynthWaveform {
|
BufferedSynthWaveform {
|
||||||
input: buffer.repeat_infinite(),
|
input: buffer.repeat_infinite(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for SynthWaveform {
|
impl Iterator for BufferedSynthWaveform {
|
||||||
type Item = f32;
|
type Item = f32;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -77,7 +94,7 @@ impl Iterator for SynthWaveform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source for SynthWaveform {
|
impl Source for BufferedSynthWaveform {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_frame_len(&self) -> Option<usize> {
|
fn current_frame_len(&self) -> Option<usize> {
|
||||||
self.input.current_frame_len()
|
self.input.current_frame_len()
|
||||||
|
@ -110,7 +127,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn square() {
|
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));
|
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]
|
#[test]
|
||||||
fn triangle() {
|
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(-1.0f32));
|
||||||
assert_eq!(wf.next(), Some(-0.5f32));
|
assert_eq!(wf.next(), Some(-0.5f32));
|
||||||
assert_eq!(wf.next(), Some(0.0f32));
|
assert_eq!(wf.next(), Some(0.0f32));
|
||||||
|
@ -144,7 +166,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn saw() {
|
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.0f32));
|
||||||
assert_eq!(wf.next(), Some(0.5f32));
|
assert_eq!(wf.next(), Some(0.5f32));
|
||||||
assert_eq!(wf.next(), Some(-1.0f32));
|
assert_eq!(wf.next(), Some(-1.0f32));
|
||||||
|
|
Loading…
Reference in a new issue