From d4eeac3b8eebee5bb88db1c5b749b9dfe31ac7a7 Mon Sep 17 00:00:00 2001 From: Roope Salmi Date: Mon, 19 Apr 2021 13:47:03 +0300 Subject: [PATCH] Windows-tuki demoon --- Cargo.lock | 8 ++++---- examples/demo.rs | 45 ++++++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48bf481..de5469e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1885,7 +1885,7 @@ checksum = "62ddb402ac6c2af6f7a2844243887631c4e94b51585b229fcfddb43958cd55ca" [[package]] name = "tuix" version = "0.1.0" -source = "git+https://github.com/geom3trik/tuix?branch=experiment#5abe0ff88f5d5bf51628362b0a7cf03669cf89f3" +source = "git+https://github.com/geom3trik/tuix?branch=experiment#1fa695263ce74a035b2ee9d2e9f9ee7d32f842ad" dependencies = [ "tuix_core", "tuix_glutin", @@ -1895,7 +1895,7 @@ dependencies = [ [[package]] name = "tuix_core" version = "0.1.0" -source = "git+https://github.com/geom3trik/tuix?branch=experiment#5abe0ff88f5d5bf51628362b0a7cf03669cf89f3" +source = "git+https://github.com/geom3trik/tuix?branch=experiment#1fa695263ce74a035b2ee9d2e9f9ee7d32f842ad" dependencies = [ "cssparser", "femtovg", @@ -1908,7 +1908,7 @@ dependencies = [ [[package]] name = "tuix_glutin" version = "0.1.0" -source = "git+https://github.com/geom3trik/tuix?branch=experiment#5abe0ff88f5d5bf51628362b0a7cf03669cf89f3" +source = "git+https://github.com/geom3trik/tuix?branch=experiment#1fa695263ce74a035b2ee9d2e9f9ee7d32f842ad" dependencies = [ "femtovg", "glutin", @@ -1919,7 +1919,7 @@ dependencies = [ [[package]] name = "tuix_inspector_derive" version = "0.1.0" -source = "git+https://github.com/geom3trik/tuix?branch=experiment#5abe0ff88f5d5bf51628362b0a7cf03669cf89f3" +source = "git+https://github.com/geom3trik/tuix?branch=experiment#1fa695263ce74a035b2ee9d2e9f9ee7d32f842ad" dependencies = [ "proc-macro2", "quote", diff --git a/examples/demo.rs b/examples/demo.rs index 3bd3bc0..3c502a1 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -9,18 +9,19 @@ fn main() -> Result<(), Box> { let host = cpal::default_host(); let device = host.default_input_device().unwrap(); eprintln!("Käytetään äänilaitetta: \"{}\"", device.name()?); - let mut config: cpal::StreamConfig = device.default_input_config()?.into(); - config.channels = 1; - let (plot, mut plot_ingest) = Plot::new_and_ingestor(config.sample_rate.0); - let audio_cb = move |data: &[f32], _: &cpal::InputCallbackInfo| { - plot_ingest.process(data); - }; - let input_stream = device.build_input_stream(&config, audio_cb, err_fn)?; - input_stream.play()?; + let config = device.default_input_config()?; + let sample_format = config.sample_format(); + let config: cpal::StreamConfig = config.into(); + let (plot, plot_ingest) = Plot::new_and_ingestor(config.sample_rate.0, config.channels as usize); + match sample_format { + cpal::SampleFormat::F32 => run_audio::(device, config, plot_ingest)?, + cpal::SampleFormat::I16 => run_audio::(device, config, plot_ingest)?, + cpal::SampleFormat::U16 => run_audio::(device, config, plot_ingest)?, + } let app = Application::new(move |state, window| { state.add_theme(style::themes::DEFAULT_THEME); state.add_theme(THEME); - window.set_layout_type(state, LayoutType::Horizontal); + window.set_layout_type(state, LayoutType::Row); Control::default().build(state, window.entity(), |builder| { builder.set_width(Stretch(1.)).set_min_width(Pixels(200.)) }); @@ -35,6 +36,17 @@ fn main() -> Result<(), Box> { fn err_fn(err: cpal::StreamError) { eprintln!("Virhe äänilaitteen kanssa: {}", err); } +fn run_audio(device: cpal::Device, config: cpal::StreamConfig, mut plot_ingest: PlotIngest) -> Result<(), Box> { + let audio_cb = move |data: &[T], _: &cpal::InputCallbackInfo| { + plot_ingest.process(data); + }; + std::thread::spawn(move || { + let input_stream = device.build_input_stream(&config, audio_cb, err_fn).unwrap(); + input_stream.play().unwrap(); + std::thread::park(); + }); + Ok(()) +} #[derive(Clone, PartialEq, Debug)] enum PlotControlEvent { @@ -49,16 +61,18 @@ const N: usize = 2 * 735; const M: usize = 2 * 360; struct PlotIngest { + channels: usize, publish_handle: triple_buffer::Input<[f32; N]>, buffer: Vec, clock: usize, } impl PlotIngest { - fn process(&mut self, data: &[f32]) { - for sample in data { + fn process(&mut self, data: &[T]) { + for frame in data.chunks(self.channels) { if self.clock < N { - self.buffer.push(*sample); + let val = frame.iter().map(|v| v.to_f32()).sum::() / self.channels as f32; + self.buffer.push(val); if self.buffer.len() == N { if let Ok(array) = self.buffer[..].try_into() { self.publish_handle.write(array); @@ -93,7 +107,7 @@ fn decay_time_to_factor(time: f32) -> f32 { } impl Plot { - pub fn new_and_ingestor(_sample_rate: u32) -> (Self, PlotIngest) { + pub fn new_and_ingestor(_sample_rate: u32, channels: usize) -> (Self, PlotIngest) { let buffer = triple_buffer::TripleBuffer::new([0.; N]); let (buf_in, buf_out) = buffer.split(); let mut weight = [0.; M]; @@ -115,6 +129,7 @@ impl Plot { memory_decay: decay_time_to_factor(0.8), }, PlotIngest { + channels, publish_handle: buf_in, buffer: Vec::with_capacity(N), clock: 0, @@ -132,7 +147,7 @@ impl Widget for Plot { entity } fn on_draw(&mut self, state: &mut State, entity: Entity, canvas: &mut Canvas) { - state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root())); + state.insert_event(Event::new(WindowEvent::Redraw).direct(Entity::root())); let BoundingBox { x, y, h, w } = state.data.get_bounds(entity); let buf = self.consume_handle.read(); @@ -217,7 +232,7 @@ impl Widget for Control { type Ret = Entity; fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret { entity.set_element(state, "control"); - entity.set_flex_direction(state, FlexDirection::Column); + entity.set_layout_type(state, LayoutType::Column); let checkbox = Row::new().build(state, entity, |builder| builder.class("check")); Checkbox::new(true) .on_checked(Event::new(PlotControlEvent::Stabilize(true)).propagate(Propagation::All))