From 89866f944ba99123435b53a72d06f8cc94610f6b Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Wed, 9 Sep 2020 01:25:47 +0200 Subject: [PATCH] Basic single-channel rendering --- Cargo.toml | 1 + src/canvas.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 567e6f6..5b046eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,4 +25,5 @@ features = [ "AudioContext", "AudioBuffer", "HtmlCanvasElement", + "CanvasRenderingContext2d", ] diff --git a/src/canvas.rs b/src/canvas.rs index c2e260c..67b5782 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -1,4 +1,6 @@ use crate::agents::audio_agent::{AudioAgent, AudioData}; +use crate::utils; +use wasm_bindgen::JsCast; use web_sys::HtmlCanvasElement; use yew::agent::Bridged; use yew::prelude::*; @@ -59,15 +61,60 @@ impl Canvas { } fn handle_samples_loaded_error(&mut self, err: &str) { - self.reset(); - ConsoleService::error(&format!("Error loading samples: {}", err)); + + self.audio_data = None; + self.redraw_canvas(); } fn redraw_canvas(&mut self) { let canvas_element = self.canvas_node.cast::().unwrap(); - let _context = canvas_element.get_context("2d").unwrap(); - // TODO: draw canvas... - ConsoleService::log("TODO: draw on canvas..."); + // canvas_element.clear(); TODO + + let width = canvas_element.width(); + let height = canvas_element.height(); + + // TODO: error handling + let context = canvas_element + .get_context("2d") + .unwrap() + .unwrap() + .dyn_into::() + .unwrap(); + + context.set_fill_style(&"black".into()); + context.set_stroke_style(&"green".into()); + context.fill_rect(0.0, 0.0, width as f64, height as f64); + + // TODO: improve + if self.audio_data.is_none() { + return; + } + let audio_data = self.audio_data.as_ref().unwrap(); + + // TODO: multi-channel + let _num_channels = audio_data.number_of_channels(); // 1 + + let channel_data = audio_data.get_channel_data(0).unwrap(); + let chunks = utils::chunks_fixed(&channel_data, width as usize); + + chunks.enumerate().for_each(|(i, chunk)| { + let max = chunk + .iter() + .map(|v| (v * 32767.0) as i32) + .map(|v| v.abs()) + .max() + .unwrap(); + + let pc = (max as f64 / 32767.0) * 100.0; + let len = (height as f64 / 100.0 * pc).floor(); + let mid = height as f64 / 2f64; + + context.begin_path(); + context.move_to(i as f64, mid - (len / 2f64)); + context.line_to(i as f64, mid + (len / 2f64)); + context.stroke(); + // ConsoleService::log(&format!("index {}: max {}, pc {}, len {}", i, max, pc, len)); + }); } }