Skip to content

Commit

Permalink
Cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
Woyten committed Aug 20, 2022
1 parent b4579f7 commit d2be6f6
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 56 deletions.
4 changes: 3 additions & 1 deletion magnetron/src/automation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use std::marker::PhantomData;

use crate::{spec::Spec, waveform::WaveformState};

type AutomationFn<S> = Box<dyn FnMut(&AutomationContext<S>) -> f64 + Send>;

pub struct Automation<S> {
pub(crate) automation_fn: Box<dyn FnMut(&AutomationContext<S>) -> f64 + Send>,
pub(crate) automation_fn: AutomationFn<S>,
}

pub struct AutomationContext<'a, S> {
Expand Down
4 changes: 3 additions & 1 deletion magnetron/src/waveform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ impl Envelope {
}
}

type StageFn<S> = Box<dyn FnMut(&mut BufferWriter, &AutomationContext<S>) + Send>;

pub struct Stage<A: AutomationSpec> {
pub(crate) stage_fn: Box<dyn FnMut(&mut BufferWriter, &AutomationContext<A::Storage>) + Send>,
pub(crate) stage_fn: StageFn<A::Storage>,
}

impl<A: AutomationSpec> Stage<A> {
Expand Down
7 changes: 5 additions & 2 deletions microwave/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Make xenharmonic music and explore musical tunings.
`microwave` is a microtonal modular waveform synthesizer with soundfont rendering capabilities based on:

- [tune](https://github.com/Woyten/tune) &ndash; a microtonal library
- [magnetron](https://github.com/Woyten/tune) &ndash; a modular synthesizer architecture
- [magnetron](https://github.com/Woyten/tune/tree/master/magnetron) &ndash; a modular synthesizer architecture
- [fluid-xenth](https://github.com/Woyten/tune/tree/master/fluid-xenth) &ndash; a microtonal soundfont renderer
- [Nannou](https://nannou.cc/) &ndash; a UI framework

Expand Down Expand Up @@ -41,6 +41,9 @@ Option C: Use Cargo to build a fresh binary from scratch for your own target arc
# On the CI environment (Ubuntu 20.04) we only need to add one library:
sudo apt install libasound2-dev

# Make sure pkg-config is installed
sudo apt install pkg-config

cargo install -f microwave
```

Expand Down Expand Up @@ -231,4 +234,4 @@ microwave help

# License

`microwave` statically links against [OxiSynth](https://crates.io/crates/oxisynth) for soundfont rendering capabilities. This makes the *binary executable* of `microwave` a derivative work of OxiSynth. OxiSynth is licensed under the *GNU Lesser General Public License, version 2.1*.
`microwave` statically links against [OxiSynth](https://crates.io/crates/oxisynth) for soundfont rendering capabilities. This makes the *binary executable* of `microwave` a derivative work of OxiSynth. OxiSynth is licensed under the *GNU Lesser General Public License, version 2.1*.
92 changes: 42 additions & 50 deletions microwave/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ mod task;
mod tunable;
mod view;

use std::{env, io, path::PathBuf, process, sync::mpsc};
use std::{cell::RefCell, env, io, path::PathBuf, sync::mpsc};

use crate::magnetron::effects::{DelayOptions, ReverbOptions, RotaryOptions};
use audio::{AudioModel, AudioOptions};
use clap::Parser;
use keyboard::KeyboardLayout;
use model::{Model, SourceId};
use nannou::{app::App, wgpu::Backends};
use nannou::{
app::{self, App},
wgpu::Backends,
};
use piano::{Backend, NoAudio, PianoEngine};
use synth::ControlChangeNumbers;
use tune::{
Expand All @@ -36,7 +39,7 @@ use tune_cli::{
midi::{MidiInArgs, MidiOutArgs, TuningMethod},
KbmOptions, SclCommand,
},
CliError, CliResult,
CliResult,
};
use view::DynViewModel;

Expand Down Expand Up @@ -351,75 +354,49 @@ fn parse_keyboard_colors(src: &str) -> Result<KeyColors, String> {
}

fn main() {
let model_fn = match env::args().collect::<Vec<_>>().as_slice() {
[_] => {
println!(
"[WARNING] Use a subcommand, e.g. `microwave run` to start microwave properly"
);
create_app_from_empty_args
}
[_, arg, ..] if arg == "bench" => {
create_model_from_main_options(MainOptions::parse()).unwrap();
return;
}
[..] => create_app_from_given_args,
let options = if env::args().len() < 2 {
println!("[WARNING] Use a subcommand, e.g. `microwave run` to start microwave properly");
MainOptions::parse_from(["microwave", "run"])
} else {
MainOptions::parse()
};

nannou::app(model_fn)
.backends(Backends::PRIMARY | Backends::GL)
.update(model::update)
.run();
}

fn create_app_from_empty_args(app: &App) -> Model {
create_app_from_main_options(app, MainOptions::parse_from(["xx", "run"]))
}

fn create_app_from_given_args(app: &App) -> Model {
create_app_from_main_options(app, MainOptions::parse())
}

fn create_app_from_main_options(app: &App, options: MainOptions) -> Model {
match create_model_from_main_options(options) {
Ok(model) => {
create_window(app);
model
}
Ok(None) => {}
Ok(Some(model)) => run_app(model),
Err(err) => {
eprintln!("[FAIL] {:?}", err);
process::exit(1);
}
}
}

fn create_model_from_main_options(options: MainOptions) -> CliResult<Model> {
fn create_model_from_main_options(options: MainOptions) -> CliResult<Option<Model>> {
match options {
MainOptions::Run(options) => Kbm::builder(NoteLetter::D.in_octave(4))
.build()
.map_err(CliError::from)
.and_then(|kbm| create_model_from_run_options(kbm, options)),
MainOptions::WithRefNote { kbm, options } => kbm
.to_kbm()
.map_err(CliError::from)
.and_then(|kbm| create_model_from_run_options(kbm, options)),
MainOptions::Run(options) => create_model_from_run_options(
Kbm::builder(NoteLetter::D.in_octave(4)).build()?,
options,
)
.map(Some),
MainOptions::WithRefNote { kbm, options } => {
create_model_from_run_options(kbm.to_kbm()?, options).map(Some)
}
MainOptions::UseKbmFile {
kbm_file_location,
options,
} => shared::import_kbm_file(&kbm_file_location)
.map_err(CliError::from)
.and_then(|kbm| create_model_from_run_options(kbm, options)),
} => create_model_from_run_options(shared::import_kbm_file(&kbm_file_location)?, options)
.map(Some),
MainOptions::Devices => {
let stdout = io::stdout();
shared::midi::print_midi_devices(stdout.lock(), "microwave").unwrap();
process::exit(0);
shared::midi::print_midi_devices(stdout.lock(), "microwave")?;
Ok(None)
}
MainOptions::Bench { analyze } => {
if analyze {
bench::analyze_benchmark()?;
} else {
bench::run_benchmark()?;
}
process::exit(0);
Ok(None)
}
}
}
Expand Down Expand Up @@ -556,6 +533,21 @@ fn create_keyboard(scl: &Scl, config: &RunOptions) -> Keyboard {
keyboard.with_steps(primary_step, secondary_step)
}

fn run_app(model: Model) {
// Since ModelFn is not a closure we need this workaround to pass the calculated model
thread_local!(static MODEL: RefCell<Option<Model>> = Default::default());

MODEL.with(|m| m.borrow_mut().replace(model));

app::Builder::new(|app| {
create_window(app);
MODEL.with(|m| m.borrow_mut().take().unwrap())
})
.backends(Backends::PRIMARY | Backends::GL)
.update(model::update)
.run();
}

fn create_window(app: &App) {
app.new_window()
.maximized(true)
Expand Down
2 changes: 1 addition & 1 deletion microwave/src/piano.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ pub trait Backend<S>: Send {
impl PianoEngineModel {
pub fn backend_mut(&mut self) -> &mut dyn Backend<SourceId> {
let curr_backend = self.curr_backend;
&mut *self.backends[curr_backend]
self.backends[curr_backend].as_mut()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/midi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl ChannelMessage {
/// assert_eq!(ChannelMessage::from_raw_message(&invalid_message), None);
/// ```
pub fn from_raw_message(message: &[u8]) -> Option<ChannelMessage> {
let status_byte = *message.get(0)?;
let status_byte = *message.first()?;
let channel = status_byte & 0b0000_1111;
let action = status_byte >> 4;
let message_type = match action {
Expand Down

0 comments on commit d2be6f6

Please sign in to comment.