Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#164 channels for visualization #184

Merged
merged 11 commits into from
Jan 23, 2023
94 changes: 85 additions & 9 deletions Apps/generator/src/sample_generator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use dasp_signal::{self as signal, Signal};
use rand::Rng;
use rand::thread_rng;
const RANDOM_DIFF: f64 = 0.01;

pub struct TenChannelSampleGenerator {
pub sine_signal: signal::Sine<signal::ConstHz>,
Expand All @@ -8,6 +10,12 @@ pub struct TenChannelSampleGenerator {
pub rng: rand::rngs::ThreadRng,
pub amplitude: f64,
pub add_noise: bool,
pub prev_rand_value: f64,
pub sine_amplitude_iterator: Box<dyn Iterator<Item=f64>>,
pub sine_amplitude_signal: signal::Sine<signal::ConstHz>,
pub sine_signal_no_noise: signal::Sine<signal::ConstHz>,
pub saw_signal_no_noise: signal::Saw<signal::ConstHz>,
pub square_signal_no_noise: signal::Square<signal::ConstHz>,
}

impl TenChannelSampleGenerator {
Expand All @@ -17,10 +25,19 @@ impl TenChannelSampleGenerator {
amplitude: f64,
add_noise: bool,
) -> TenChannelSampleGenerator {
fn oscillate(rate: f64) -> impl Iterator<Item=f64> {
(0..).map(move |x| ((x as f64 * std::f64::consts::PI / rate).sin() + 1.0) / 2.0)
}
let sine_signal = signal::rate(sampling_rate).const_hz(frequency).sine();
let saw_signal = signal::rate(sampling_rate).const_hz(frequency).saw();
let square_signal = signal::rate(sampling_rate).const_hz(frequency).square();
let rng = rand::thread_rng();
let rng = thread_rng();
let prev_rand_value = 0.0;
let sine_amplitude_iterator = Box::new(oscillate(sampling_rate * 10.0));
let sine_amplitude_signal = signal::rate(sampling_rate).const_hz(frequency).sine();
let sine_signal_no_noise = signal::rate(sampling_rate).const_hz(frequency).sine();
let saw_signal_no_noise = signal::rate(sampling_rate).const_hz(frequency).saw();
let square_signal_no_noise = signal::rate(sampling_rate).const_hz(frequency).square();

TenChannelSampleGenerator {
sine_signal,
Expand All @@ -29,6 +46,12 @@ impl TenChannelSampleGenerator {
rng,
amplitude,
add_noise,
prev_rand_value,
sine_amplitude_iterator,
sine_amplitude_signal,
sine_signal_no_noise,
saw_signal_no_noise,
square_signal_no_noise,
}
}

Expand All @@ -45,17 +68,29 @@ impl TenChannelSampleGenerator {
samples.push(self.amplitude * self.square_signal.next() + noise);
samples.push(self.amplitude * self.sine_signal.next() + noise);
samples.push(self.amplitude * self.saw_signal.next() + noise);
samples.push(self.amplitude * self.random_bounded_values());
samples.push(self.rng.gen_range(-1.0..1.0));
samples.push(self.amplitude * self.sine_amplitude_signal.next() * self.sine_amplitude_iterator.next().unwrap());
samples.push(self.amplitude * self.sine_signal_no_noise.next());
samples.push(self.amplitude * self.saw_signal_no_noise.next());
samples.push(self.amplitude * self.square_signal_no_noise.next());

// remaining channels are set to a constant 0-Signal
samples.push(0.0);
samples.push(0.0);
samples.push(0.0);
samples.push(0.0);
samples.push(0.0);
samples.push(0.0);
samples.push(0.0);
samples
}

fn random_bounded_values(self: &mut TenChannelSampleGenerator) -> f64 {
let mut rng = thread_rng();
let prev_value = self.prev_rand_value;
loop {
let value = rng.gen_range(-1.0..1.0);
if (prev_value - value).abs() <= RANDOM_DIFF {
self.prev_rand_value = value;
return value;
}
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -109,7 +144,48 @@ mod tests {
let second: Vec<f64> = generator.next();
let third: Vec<f64> = generator.next();

assert_eq!(first, second);
assert_eq!(second, third);
assert_eq!(first[0..3], second[0..3]);
assert_eq!(second[0..3], third[0..3]);
}

#[test]
fn test_random_bounded_values() {
const SAMPLING_RATE: f64 = 50.0;
const FREQUENCY: f64 = 1.0;
const AMPLITUDE: f64 = 10.0;
let mut generator = TenChannelSampleGenerator::new(SAMPLING_RATE, FREQUENCY, AMPLITUDE, false);
let first_value = generator.random_bounded_values();

let second_value = generator.random_bounded_values();
assert!((first_value - second_value).abs() <= RANDOM_DIFF);

let third_value = generator.random_bounded_values();
assert!((first_value - third_value).abs() <= RANDOM_DIFF * 2.0);
assert!((second_value - third_value).abs() <= RANDOM_DIFF);

let fourth_value = generator.random_bounded_values();
assert!((first_value - fourth_value).abs() <= 3.0 * RANDOM_DIFF);
assert!((second_value - fourth_value).abs() <= 2.0 * RANDOM_DIFF);
assert!((third_value - fourth_value).abs() <= RANDOM_DIFF);
}

#[test]
fn test_random_bounded_values_min_max() {
let mut min: f64 = 10000.0;
let mut max: f64 = -100000.0;

const SAMPLING_RATE: f64 = 50.0;
const FREQUENCY: f64 = 1.0;
const AMPLITUDE: f64 = 10.0;
let mut generator = TenChannelSampleGenerator::new(SAMPLING_RATE, FREQUENCY, AMPLITUDE, false);

for _ in 0..1000 {
let value = generator.random_bounded_values();
min = min.min(value);
max = max.max(value);
}

assert!(min > -1.0);
assert!(max < 1.0);
}
}