summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2016-11-26 09:42:25 +0200
committerJustin Worthe <justin.worthe@gmail.com>2016-11-26 09:42:25 +0200
commitfba482b5545a6c02bf32d9dc4f261f6fc5556064 (patch)
treed5c54382fbcd82515d41dc899391b47b2aaa1a54 /src
parent14d8545f0c905ea94556919693c08fb887a3ce59 (diff)
Updated name of crate everywhere
Diffstat (limited to 'src')
-rw-r--r--src/audio.rs6
-rw-r--r--src/main.rs4
-rw-r--r--src/transforms.rs86
3 files changed, 71 insertions, 25 deletions
diff --git a/src/audio.rs b/src/audio.rs
index e418e94..bcee400 100644
--- a/src/audio.rs
+++ b/src/audio.rs
@@ -24,7 +24,8 @@ pub fn get_device_list(pa: &pa::PortAudio) -> Result<Vec<(u32, String)>, pa::Err
Ok(list)
}
-//#[test]
+#[test]
+#[ignore]
fn get_device_list_returns_devices() {
let pa = init().expect("Could not init portaudio");
let devices = get_device_list(&pa).expect("Getting devices had an error");
@@ -61,7 +62,8 @@ pub fn start_listening(pa: &pa::PortAudio, device_index: u32,
Ok(stream)
}
-//#[test]
+#[test]
+#[ignore]
fn start_listening_returns_successfully() {
let pa = init().expect("Could not init portaudio");
let devices = get_device_list(&pa).expect("Getting devices had an error");
diff --git a/src/main.rs b/src/main.rs
index 0eea7f3..91befca 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
-extern crate musician_training;
+extern crate rusty_microphone;
-use musician_training::*;
+use rusty_microphone::*;
fn main() {
let gui_result = gui::start_gui();
diff --git a/src/transforms.rs b/src/transforms.rs
index 371379d..4d0e224 100644
--- a/src/transforms.rs
+++ b/src/transforms.rs
@@ -7,10 +7,18 @@ pub struct FrequencyBucket {
pub intensity: f64
}
+impl FrequencyBucket {
+ pub fn ave_freq(&self) -> f64 {
+ (self.min_freq + self.max_freq) / 2.0
+ }
+}
+
pub fn fft(input: Vec<f64>, sample_rate: f64) -> Vec<FrequencyBucket> {
let frames = input.len();
+ let mean_input = input.iter().sum::<f64>()/input.len() as f64;
+
+ let mut intensities = input.iter().map(|x|x-mean_input).collect::<Vec<_>>();
let plan = dft::Plan::new(dft::Operation::Forward, frames);
- let mut intensities = input.clone();
dft::transform(&mut intensities, &plan);
let frequency_resolution = sample_rate / 2.0 / frames as f64;
@@ -28,35 +36,71 @@ pub fn fft(input: Vec<f64>, sample_rate: f64) -> Vec<FrequencyBucket> {
pub fn find_fundamental_frequency(frequency_domain: &Vec<FrequencyBucket>) -> Option<f64> {
//TODO look at all significant frequencies, find fundamental
//TODO return None is none of them are significant
+ let positive_buckets = frequency_domain.iter().filter(|x| x.intensity > 0.0).cloned().collect::<Vec<_>>();
+ let average_intensity = positive_buckets.iter().map(|x| x.intensity).sum::<f64>() / frequency_domain.len() as f64;
+ let significant_buckets = positive_buckets.iter().filter(|x| x.intensity > average_intensity).cloned().collect::<Vec<_>>();
+ for bucket in significant_buckets.iter() {
+ //println!("{:?}", bucket);
+ }
- let max_frequency = frequency_domain.iter()
+ let max_bucket = significant_buckets.iter()
.fold(None as Option<::transforms::FrequencyBucket>, |max, next|
if max.is_none() || max.clone().unwrap().intensity < next.intensity { Some(next.clone()) } else { max }
- ).unwrap().max_freq;
-
- Some(max_frequency)
+ ).unwrap();
+
+ Some(max_bucket.ave_freq())
}
-#[test]
-fn fft_on_sine_wave() {
- use std::f64::consts;
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::f64::consts::PI;
- let sample_rate = 44100.0 as f64;
- let amplitude = 1.0 as f64;
- let frames = 16384;
- let frequency = 10000.0 as f64; //10KHz
- let frequency_resolution = sample_rate / 2.0 / frames as f64;
+ const SAMPLE_RATE: f64 = 44100.0;
+ const FRAMES: usize = 512;
+
+ fn frequency_resolution() -> f64 {
+ SAMPLE_RATE / 2.0 / FRAMES as f64
+ }
+
+ fn sin_arg(f: f64, t: f64, phase: f64) -> f64 {
+ 2.0 as f64 * PI * f * t + phase
+ }
+
+ fn sample_sinusoud(amplitude: f64, frequency: f64, phase: f64) -> Vec<f64> {
+ (0..FRAMES)
+ .map(|x| {
+ let t = x as f64 / SAMPLE_RATE;
+ sin_arg(frequency, t, phase).sin() * amplitude
+ }).collect()
+ }
- let samples = (0..frames)
- .map(|x| {
- let t = x as f64 / sample_rate;
- (2.0 as f64 * consts::PI * frequency * t).sin() * amplitude
- }).collect();
+ #[test]
+ fn fft_on_sine_wave() {
+ let frequency = 10000.0 as f64; //10KHz
+
+ let samples = sample_sinusoud(1.0, frequency, 0.0);
+ let frequency_domain = fft(samples, SAMPLE_RATE);
+ let fundamental = find_fundamental_frequency(&frequency_domain).unwrap();
+
+ assert!((fundamental-frequency).abs() < frequency_resolution(), "expected={}, actual={}", frequency, fundamental);
+ }
- let result = fft(samples, sample_rate);
- let fundamental = find_fundamental_frequency(&result);
+ #[test]
+ fn fft_on_two_sine_waves() {
+ let samples1k = sample_sinusoud(0.5, 1000.0, 0.0);
+ let samples2k = sample_sinusoud(1.0, 10000.0, 0.0);
+ let expected_fundamental = 1000.0;
+
+ let samples = samples1k.iter().zip(samples2k.iter())
+ .map(|(a, b)| a+b)
+ .collect();
+ let frequency_domain = fft(samples, SAMPLE_RATE);
+
+ let fundamental = find_fundamental_frequency(&frequency_domain).unwrap();
- assert!((fundamental-frequency).abs() < frequency_resolution, "expected={}, actual={}", frequency, fundamental);
+ assert!((fundamental-expected_fundamental).abs() < frequency_resolution(), "expected_fundamental={}, actual={}", expected_fundamental, fundamental);
+ }
}
pub fn hz_to_pitch(hz: f64) -> String {