summaryrefslogtreecommitdiff
path: root/src/audio.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2016-09-25 16:19:58 +0200
committerJustin Worthe <justin.worthe@gmail.com>2016-09-25 16:19:58 +0200
commit59607a6ba83048d8f92920d974f4ab2c6ecbaae6 (patch)
tree92a92d2e12409700049188414648d796f6757797 /src/audio.rs
GUI, lists PA devices, backend can watch audio stream
Diffstat (limited to 'src/audio.rs')
-rw-r--r--src/audio.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/audio.rs b/src/audio.rs
new file mode 100644
index 0000000..526a227
--- /dev/null
+++ b/src/audio.rs
@@ -0,0 +1,74 @@
+extern crate portaudio;
+use portaudio as pa;
+
+const SAMPLE_RATE: f64 = 44100.0;
+const FRAMES: usize = 512;
+
+pub fn get_device_list() -> Result<Vec<(u32, String)>, pa::Error> {
+ let pa = try!(pa::PortAudio::new());
+ let default_host = try!(pa.default_host_api());
+ println!("Using default host: {:#?}", default_host);
+
+ let mut list = Vec::new();
+ let devices = try!(pa.devices());
+ for device in devices {
+ let (pa::DeviceIndex(idx), info) = try!(device);
+ if info.max_input_channels == 0 {
+ continue;
+ }
+ list.push((idx, info.name.to_string()));
+ }
+ Ok(list)
+}
+
+pub fn run(device_index: u32) -> Result<(), pa::Error> {
+ let pa = try!(pa::PortAudio::new());
+
+ let input_info = try!(pa.device_info(pa::DeviceIndex(device_index)));
+ println!("Using {} for input", input_info.name);
+
+ // Construct the input stream parameters.
+ let latency = input_info.default_low_input_latency;
+ let input_params = pa::StreamParameters::<f32>::new(pa::DeviceIndex(device_index), 1, true, latency);
+
+ // Check that the stream format is supported.
+ try!(pa.is_input_format_supported(input_params, SAMPLE_RATE));
+
+ // Construct the settings with which we'll open our duplex stream.
+ let settings = pa::InputStreamSettings::new(input_params, SAMPLE_RATE, FRAMES as u32);
+
+ // We'll use this channel to send the count_down to the main thread for fun.
+ let (sender, receiver) = ::std::sync::mpsc::channel();
+
+ // A callback to pass to the non-blocking stream.
+ let callback = move |pa::InputStreamCallbackArgs { buffer, .. }| {
+ sender.send(buffer.iter().map(|x| *x as f64).collect()).ok();
+ pa::Continue
+ };
+
+ // Construct a stream with input and output sample types of f32.
+ let mut stream = try!(pa.open_non_blocking_stream(settings, callback));
+
+ try!(stream.start());
+
+ let mut samples_index = 0;
+ // Do some stuff!
+ 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());
+ }
+
+ try!(stream.stop());
+
+ Ok(())
+}