summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2016-11-05 15:56:24 +0200
committerJustin Worthe <justin.worthe@gmail.com>2016-11-05 15:56:24 +0200
commit75c9880d1a7bb7e54996743989374a45d5a26e49 (patch)
treeb0b3e14714c464a468c27bf8be42efceab0146f7 /src
parent420ad331332bce98f871f1c4ca2c0bea51688767 (diff)
Reordered passing in channels
Diffstat (limited to 'src')
-rw-r--r--src/audio.rs41
-rw-r--r--src/gui.rs41
2 files changed, 34 insertions, 48 deletions
diff --git a/src/audio.rs b/src/audio.rs
index c989c49..c038080 100644
--- a/src/audio.rs
+++ b/src/audio.rs
@@ -34,13 +34,8 @@ fn get_device_list_returns_devices() {
assert!(devices.len() > 0);
}
-
-pub struct OpenRecordingChannel {
- pub receiver: Receiver<Vec<f32>>,
- pub stream: pa::Stream<pa::NonBlocking, pa::Input<f32>>
-}
-
-pub fn start_listening(pa: &pa::PortAudio, device_index: u32) -> Result<OpenRecordingChannel, pa::Error> {
+pub fn start_listening(pa: &pa::PortAudio, device_index: u32,
+ sender: Sender<Vec<f64>>) -> Result<pa::Stream<pa::NonBlocking, pa::Input<f32>>, pa::Error> {
let device_info = try!(pa.device_info(pa::DeviceIndex(device_index)));
let latency = device_info.default_low_input_latency;
@@ -54,22 +49,16 @@ pub fn start_listening(pa: &pa::PortAudio, device_index: u32) -> Result<OpenReco
// Construct the settings with which we'll open our stream.
let stream_settings = pa::InputStreamSettings::new(input_params, SAMPLE_RATE, FRAMES as u32);
- // This channel will let us read from and control the audio stream
- let (sender, receiver) = channel();
-
// This callback A callback to pass to the non-blocking stream.
let callback = move |pa::InputStreamCallbackArgs { buffer, .. }| {
- sender.send(buffer.iter().cloned().collect()).ok();
+ sender.send(buffer.iter().map(|&s| s as f64).collect()).ok();
pa::Continue
};
let mut stream = try!(pa.open_non_blocking_stream(stream_settings, callback));
try!(stream.start());
- Ok(OpenRecordingChannel {
- receiver: receiver,
- stream: stream
- })
+ Ok(stream)
}
#[test]
@@ -77,24 +66,6 @@ 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");
let device = devices.first().expect("Should have at least one device");
- start_listening(&pa, device.0).expect("Error starting listening to first channel");
+ let (sender, _) = channel();
+ start_listening(&pa, device.0, sender).expect("Error starting listening to first channel");
}
-
-
-/*
- let mut samples_index = 0;
- while let Ok(samples) = receiver.recv() {
- samples_index += 1;
- if samples_index % 100 != 0 {
- continue;
- }
-
- let frequency_domain = ::transforms::fft(samples, SAMPLE_RATE);
-
- let max_frequency = frequency_domain.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;
- println!("{}Hz", max_frequency.floor());
- }
-*/
diff --git a/src/gui.rs b/src/gui.rs
index 444f21b..42e062d 100644
--- a/src/gui.rs
+++ b/src/gui.rs
@@ -3,8 +3,11 @@ use gtk::prelude::*;
use std::cell::RefCell;
use portaudio as pa;
use std::rc::Rc;
+use std::sync::Arc;
use std::io;
use std::io::Write;
+use std::thread;
+use std::sync::mpsc::*;
const GUI_XML: &'static str = r#"
<interface>
@@ -20,43 +23,55 @@ const GUI_XML: &'static str = r#"
struct ApplicationState {
pa: pa::PortAudio,
- channel: Option<::audio::OpenRecordingChannel>
+ pa_stream: Option<pa::Stream<pa::NonBlocking, pa::Input<f32>>>
}
pub fn start_gui() -> Result<(), String> {
let pa = try!(::audio::init().map_err(|e| e.to_string()));
let microphones = try!(::audio::get_device_list(&pa).map_err(|e| e.to_string()));
-
+
+ let (mic_sender, mic_receiver) = channel();
let state = Rc::new(RefCell::new(ApplicationState {
pa: pa,
- channel: None
+ pa_stream: None
}));
try!(gtk::init().map_err(|_| "Failed to initialize GTK."));
let gtk_builder = try!(create_window(microphones));
- let dropdown: gtk::ComboBoxText = try!(
- gtk_builder.get_object("dropdown")
- .ok_or("GUI does not contain an object with id 'dropdown'")
- );
{
let state_for_dropdown = state.clone();
+
+ let dropdown: gtk::ComboBoxText = try!(
+ gtk_builder.get_object("dropdown").ok_or("GUI does not contain an object with id 'dropdown'")
+ );
dropdown.connect_changed(move |dropdown: &gtk::ComboBoxText| {
- match state_for_dropdown.borrow_mut().channel {
- Some(ref mut channel) => {channel.stream.stop().ok();},
+ match state_for_dropdown.borrow_mut().pa_stream {
+ Some(ref mut stream) => {stream.stop().ok();},
_ => {}
}
-
let selected_mic = dropdown.get_active_id().and_then(|id| id.parse().ok()).expect("Dropdown did not change to a valid value");
- let channel = ::audio::start_listening(&state_for_dropdown.borrow().pa, selected_mic).ok();
- if channel.is_none() {
+ let stream = ::audio::start_listening(&state_for_dropdown.borrow().pa, selected_mic, mic_sender.clone()).ok();
+ if stream.is_none() {
writeln!(io::stderr(), "Failed to open audio channel").ok();
}
- state_for_dropdown.borrow_mut().channel = channel;
+ state_for_dropdown.borrow_mut().pa_stream = stream;
});
}
+ let async_thread = thread::spawn(move || {
+ for samples in mic_receiver {
+ let frequency_domain = ::transforms::fft(samples, 44100.0);
+
+ let max_frequency = frequency_domain.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;
+ println!("{}Hz", max_frequency.floor());
+ }
+ });
+
gtk::main();
Ok(())
}