mirror of
https://github.com/RustAudio/rodio
synced 2025-03-04 06:57:16 +00:00
Renamed TestWaveform to SignalGenerator
This commit is contained in:
parent
44cb217d48
commit
8899e6709f
4 changed files with 11 additions and 196 deletions
|
@ -1,7 +1,7 @@
|
|||
//! Test signal generator example.
|
||||
|
||||
fn main() {
|
||||
use rodio::source::{chirp, Function, Source, TestWaveform};
|
||||
use rodio::source::{chirp, Function, Source, SignalGenerator};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -13,7 +13,7 @@ fn main() {
|
|||
println!("Playing 1000 Hz tone");
|
||||
stream_handle
|
||||
.play_raw(
|
||||
TestWaveform::new(cpal::SampleRate(48000), 1000.0, Function::Sine)
|
||||
SignalGenerator::new(cpal::SampleRate(48000), 1000.0, Function::Sine)
|
||||
.amplify(0.1)
|
||||
.take_duration(test_signal_duration),
|
||||
)
|
||||
|
@ -24,7 +24,7 @@ fn main() {
|
|||
println!("Playing 10,000 Hz tone");
|
||||
stream_handle
|
||||
.play_raw(
|
||||
TestWaveform::new(cpal::SampleRate(48000), 10000.0, Function::Sine)
|
||||
SignalGenerator::new(cpal::SampleRate(48000), 10000.0, Function::Sine)
|
||||
.amplify(0.1)
|
||||
.take_duration(test_signal_duration),
|
||||
)
|
||||
|
@ -35,7 +35,7 @@ fn main() {
|
|||
println!("Playing 440 Hz Triangle Wave");
|
||||
stream_handle
|
||||
.play_raw(
|
||||
TestWaveform::new(cpal::SampleRate(48000), 440.0, Function::Triangle)
|
||||
SignalGenerator::new(cpal::SampleRate(48000), 440.0, Function::Triangle)
|
||||
.amplify(0.1)
|
||||
.take_duration(test_signal_duration),
|
||||
)
|
||||
|
@ -46,7 +46,7 @@ fn main() {
|
|||
println!("Playing 440 Hz Sawtooth Wave");
|
||||
stream_handle
|
||||
.play_raw(
|
||||
TestWaveform::new(cpal::SampleRate(48000), 440.0, Function::Sawtooth)
|
||||
SignalGenerator::new(cpal::SampleRate(48000), 440.0, Function::Sawtooth)
|
||||
.amplify(0.1)
|
||||
.take_duration(test_signal_duration),
|
||||
)
|
||||
|
@ -57,7 +57,7 @@ fn main() {
|
|||
println!("Playing 440 Hz Square Wave");
|
||||
stream_handle
|
||||
.play_raw(
|
||||
TestWaveform::new(cpal::SampleRate(48000), 440.0, Function::Square)
|
||||
SignalGenerator::new(cpal::SampleRate(48000), 440.0, Function::Square)
|
||||
.amplify(0.1)
|
||||
.take_duration(test_signal_duration),
|
||||
)
|
||||
|
|
|
@ -34,7 +34,7 @@ pub use self::spatial::Spatial;
|
|||
pub use self::speed::Speed;
|
||||
pub use self::stoppable::Stoppable;
|
||||
pub use self::take::TakeDuration;
|
||||
pub use self::test_waveform::{Function, TestWaveform};
|
||||
pub use self::signal_generator::{Function, SignalGenerator};
|
||||
pub use self::uniform::UniformSourceIterator;
|
||||
pub use self::zero::Zero;
|
||||
|
||||
|
@ -66,7 +66,7 @@ mod spatial;
|
|||
mod speed;
|
||||
mod stoppable;
|
||||
mod take;
|
||||
mod test_waveform;
|
||||
mod signal_generator;
|
||||
mod uniform;
|
||||
mod zero;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::source::{Function, TestWaveform};
|
||||
use crate::source::{Function, SignalGenerator};
|
||||
use crate::Source;
|
||||
|
||||
use super::SeekError;
|
||||
|
@ -10,7 +10,7 @@ use super::SeekError;
|
|||
/// Always has a rate of 48kHz and one channel.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SineWave {
|
||||
test_sine: TestWaveform,
|
||||
test_sine: SignalGenerator,
|
||||
}
|
||||
|
||||
impl SineWave {
|
||||
|
@ -21,7 +21,7 @@ impl SineWave {
|
|||
pub fn new(freq: f32) -> SineWave {
|
||||
let sr = cpal::SampleRate(Self::SAMPLE_RATE);
|
||||
SineWave {
|
||||
test_sine: TestWaveform::new(sr, freq, Function::Sine),
|
||||
test_sine: SignalGenerator::new(sr, freq, Function::Sine),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
//! Generator sources for various periodic test waveforms.
|
||||
//!
|
||||
//! This module provides several periodic, deterministic waveforms for testing other sources and
|
||||
//! for simple additive sound synthesis. Every source is monoaural and in the codomain [-1.0f32,
|
||||
//! 1.0f32].
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! use rodio::source::{TestWaveform,Function};
|
||||
//!
|
||||
//! let tone = TestWaveform::new(cpal::SampleRate(48000), 440.0, Function::Sine);
|
||||
//! ```
|
||||
use std::f32::consts::TAU;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::SeekError;
|
||||
use crate::Source;
|
||||
|
||||
/// Waveform functions.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Function {
|
||||
/// A sinusoidal waveform.
|
||||
Sine,
|
||||
/// A triangle waveform.
|
||||
Triangle,
|
||||
/// A square wave, rising edge at t=0.
|
||||
Square,
|
||||
/// A rising sawtooth wave.
|
||||
Sawtooth,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
/// Create a single sample for the given waveform
|
||||
#[inline]
|
||||
fn render(&self, i: u64, period: f32) -> f32 {
|
||||
let cycle_pos: f32 = i as f32 / period;
|
||||
|
||||
match self {
|
||||
Self::Sine => (TAU * cycle_pos).sin(),
|
||||
Self::Triangle => 4.0f32 * (cycle_pos - (cycle_pos + 0.5f32).floor()).abs() - 1f32,
|
||||
Self::Square => {
|
||||
if cycle_pos % 1.0f32 < 0.5f32 {
|
||||
1.0f32
|
||||
} else {
|
||||
-1.0f32
|
||||
}
|
||||
}
|
||||
Self::Sawtooth => 2.0f32 * (cycle_pos - (cycle_pos + 0.5f32).floor()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An infinite source that produces one of a selection of test waveforms.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TestWaveform {
|
||||
sample_rate: cpal::SampleRate,
|
||||
period: f32,
|
||||
function: Function,
|
||||
i: u64,
|
||||
}
|
||||
|
||||
impl TestWaveform {
|
||||
/// Create a new `TestWaveform` object that generates an endless waveform
|
||||
/// `f`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Will panic if `frequency` is equal to zero.
|
||||
#[inline]
|
||||
pub fn new(sample_rate: cpal::SampleRate, frequency: f32, f: Function) -> TestWaveform {
|
||||
assert!(frequency != 0.0, "frequency must be greater than zero");
|
||||
let period = sample_rate.0 as f32 / frequency;
|
||||
TestWaveform {
|
||||
sample_rate,
|
||||
period,
|
||||
function: f,
|
||||
i: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for TestWaveform {
|
||||
type Item = f32;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<f32> {
|
||||
let val = Some(self.function.render(self.i, self.period));
|
||||
self.i += 1;
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for TestWaveform {
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn channels(&self) -> u16 {
|
||||
1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_rate(&self) -> u32 {
|
||||
self.sample_rate.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn total_duration(&self) -> Option<Duration> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_seek(&mut self, duration: Duration) -> Result<(), SeekError> {
|
||||
self.i = (self.sample_rate.0 as f32 * duration.as_secs_f32()) as u64;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::source::{Function, TestWaveform};
|
||||
use approx::assert_abs_diff_eq;
|
||||
|
||||
#[test]
|
||||
fn square() {
|
||||
let mut wf = TestWaveform::new(cpal::SampleRate(2000), 500.0f32, Function::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));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn triangle() {
|
||||
let mut wf = TestWaveform::new(cpal::SampleRate(8000), 1000.0f32, Function::Triangle);
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
assert_eq!(wf.next(), Some(-0.5f32));
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(1.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(-0.5f32));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
assert_eq!(wf.next(), Some(-0.5f32));
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(1.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(-0.5f32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn saw() {
|
||||
let mut wf = TestWaveform::new(cpal::SampleRate(200), 50.0f32, Function::Sawtooth);
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
assert_eq!(wf.next(), Some(-0.5f32));
|
||||
assert_eq!(wf.next(), Some(0.0f32));
|
||||
assert_eq!(wf.next(), Some(0.5f32));
|
||||
assert_eq!(wf.next(), Some(-1.0f32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sine() {
|
||||
let mut wf = TestWaveform::new(cpal::SampleRate(1000), 100f32, Function::Sine);
|
||||
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), 0.0f32);
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525f32);
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), 0.95105652f32);
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), 0.95105652f32);
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525f32);
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), 0.0f32);
|
||||
assert_abs_diff_eq!(wf.next().unwrap(), -0.58778554f32);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue