pub fn register(ext: Extension) -> Result<()>Expand description
Add a block to the registry: it is listed by registry, built by build,
described by json_schema and checked by check_link like the others. A crate
that defines blocks registers them before it runs a specification, and may ship its
own comnum binary around cli::main.
§Errors
Error::Config when a block of that name exists.
§Examples
A block of another crate: its parameters are declared with
block_params! and its ports with
block_info!, as those of the blocks of this crate, so that
comnum blocks, the JSON Schema and the checks of the links describe it too.
use comnum_core::rng::Rng;
use comnum_spec::blocks::{self, Block, BuildContext, Extension, Frame, Params};
use comnum_spec::{RunOptions, Spec, block_info, block_params, run};
use serde_json::Value as Json;
block_params! {
struct GainSpec {
gain_db: f64 [0.0] "dB", "power gain";
}
}
/// Multiply every sample by an amplitude gain.
struct Gain(f64);
impl Block for Gain {
fn apply(&self, s: &mut Frame, _: &mut Rng) -> comnum_core::Result<()> {
s.streams_mut().flatten().for_each(|v| *v *= self.0);
Ok(())
}
}
fn build(p: Json, _label: String, _: &BuildContext) -> comnum_core::Result<Box<dyn Block>> {
let q = GainSpec::parse("gain", p)?;
Ok(Box::new(Gain(comnum_math::db2amp(q.gain_db))))
}
blocks::register(Extension {
info: block_info!("gain", "Amplify the samples.", GainSpec, needs [Samples], gives []),
build,
})?;
let spec = Spec::from_yaml(
"name: amplified\nlink: [source, {type: gain, gain_db: 6}]\n\
metrics: {report: [ser]}\nstop: {max_trials: 2}",
)?;
let results = run(&spec, &RunOptions::default())?;
assert_eq!(results[0].metric("ser").unwrap().value(), 0.0);
// listed with its parameters, and checked as the blocks of this crate
let info = blocks::registry().into_iter().find(|b| b.name == "gain").unwrap();
assert_eq!((info.params[0].name, info.params[0].unit), ("gain_db", "dB"));
let unknown = serde_json::json!({"type": "gain", "gain": 6});
assert!(blocks::build(&unknown, &BuildContext::default()).is_err());