From 864add840350b2440575e1c99eb093a4762099f1 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sat, 20 Feb 2021 21:47:30 +0100 Subject: [PATCH] Provide SignalProcessing methods to the Lua script This is accomplished by providing a wrapped reference to the SignalProcessing instance of the Rust program as a global Lua variable. The wrapper class implements mlua::UserData, wraps the relevant SignalProcessing methods and provides them as Lua methods. So far, this is implemented for get_energy_in_band() only. --- src/main.rs | 39 +++++++++++++++++++++++---------------- src/userscript.rs | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9772e51..714076e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,25 +12,29 @@ mod userscript; use crate::signal_processing::SignalProcessing; use crate::userscript::UserScript; +use std::rc::Rc; +use std::cell::RefCell; + fn main() { let mut stdin = std::io::stdin(); - // set up Lua environment - - println!("Loading user script..."); - - let script = UserScript::new("test.lua").unwrap(); - - println!("Calling init()..."); - - script.init().unwrap(); - // set up signal processing println!("Initializing signal processing..."); - let mut sigproc = SignalProcessing::new(config::BLOCK_LEN, config::SAMP_RATE).unwrap(); + let sigproc = Rc::new(RefCell::new( + SignalProcessing::new(config::BLOCK_LEN, config::SAMP_RATE).unwrap())); + + // set up Lua environment + + println!("Loading user script..."); + + let script = UserScript::new(sigproc.clone(), "test.lua").unwrap(); + + println!("Calling init()..."); + + script.init().unwrap(); println!("Done! Starting main loop…"); @@ -67,12 +71,15 @@ fn main() } - sigproc.import_i16_mono_from_iter(samples.iter()).unwrap(); - sigproc.update_fft().unwrap(); + { + let mut s = sigproc.borrow_mut(); + s.import_i16_mono_from_iter(samples.iter()).unwrap(); + s.update_fft().unwrap(); + } - let energy_bass = sigproc.get_energy_in_band( 0.0, 400.0); - let energy_mid = sigproc.get_energy_in_band( 400.0, 4000.0); - let energy_treble = sigproc.get_energy_in_band(4000.0, config::SAMP_RATE/2.0); + let energy_bass = sigproc.borrow().get_energy_in_band( 0.0, 400.0); + let energy_mid = sigproc.borrow().get_energy_in_band( 400.0, 4000.0); + let energy_treble = sigproc.borrow().get_energy_in_band(4000.0, config::SAMP_RATE/2.0); // dump the output println!("Bass: {:11.2} – Mid: {:11.2} – Treble: {:11.2}", energy_bass, energy_mid, energy_treble); diff --git a/src/userscript.rs b/src/userscript.rs index 7603b8b..9b3d4f8 100644 --- a/src/userscript.rs +++ b/src/userscript.rs @@ -21,11 +21,15 @@ */ use crate::config; +use crate::signal_processing::SignalProcessing; use mlua::Lua; use mlua::FromLua; use mlua::Error; +use std::rc::Rc; +use std::cell::RefCell; + pub struct UserScript { lua_state: Lua, @@ -33,12 +37,26 @@ pub struct UserScript impl UserScript { - pub fn new(user_script_path: &str) -> std::result::Result + pub fn new(sigproc: Rc>, user_script_path: &str) -> std::result::Result { let s = UserScript { lua_state: Lua::new(), }; + // provide some configuration constants to Lua via a table + let config_table = s.lua_state.create_table()?; + + config_table.set("sampling_rate", config::SAMP_RATE)?; + config_table.set("block_length", config::BLOCK_LEN)?; + config_table.set("samples_per_update", config::SAMPLES_PER_UPDATE)?; + + s.lua_state.globals().set("CONFIG", config_table)?; + + // register the signal processing reference as Lua user data + s.lua_state.globals().set("sigproc", SignalProcessingWrapper{ + signal_processing: sigproc + })?; + // load the user script and execute it to make variables and functions available let user_script = std::fs::read_to_string(user_script_path)?; s.lua_state.load(&user_script).exec()?; @@ -93,3 +111,23 @@ impl UserScript Ok(()) } } + + +/* + * Wrap a SignalProcessing instance and provide a Lua interface for some of its methods. + */ +struct SignalProcessingWrapper +{ + signal_processing: Rc>, +} + +impl mlua::UserData for SignalProcessingWrapper +{ + fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) + { + methods.add_method("get_energy_in_band", |_, this, (start_freq, end_freq): (f32, f32)| { + Ok(this.signal_processing.borrow().get_energy_in_band(start_freq, end_freq)) + }); + } +} +