Select Git revision
main.rs 16.98 KiB
//! # 16x16 Hexmatrix OSC-Jack-Mixer
use std::io;
use jack;
use jack::{Port, AudioIn, AudioOut};
use rosc;
use rosc::{OscPacket, OscMessage};
use std::net::{SocketAddrV4, UdpSocket};
use std::str::FromStr;
use std::sync::atomic::{AtomicUsize, Ordering};
use arr_macro::arr;
use clap::{Arg, App};
/*
TODO:
- [ ] Document dependecies
- [ ] Performance improvements:
- [ ] implement performance monitoring
- [ ] f32.mul_add() or f32.to_bits() / f32.from_bits()
- [ ] only calculate connected ports https://docs.rs/jack/0.7.1/jack/struct.Port.html#method.connected_count
- [ ] Flag volume modulations as dirty
- [x] Support other Buffers than 1024
- [ ] Features:
- [ ] Flags to control printing (--quiet etc)
- [ ] Option to set initial values
- [ ] Option to limit certain inputs/outputs to certain volumes
- [ ] Option to ignore certain modulations
- [ ] GUI/TLI to see matrix and current volumes
- [ ] OSC: Per Channel Solo/Mute/Invert
- [ ] OSC: Output Volumes
- [ ] OSC: Output Levels
*/
// Number of inputs and outputs.
// Careful: this needs to be changed in many places
const N_INPUTS: usize = 16;
const N_OUTPUTS: usize = 16;
// Atomic Variables for Shared Mutability of Modulation values
// One per Input, with n values where n is the number of outputs
// Incoming float values get scaled to a unsigned usize (e.g. 64 bit)
// Static arrays are used here for maximum performance
// (No: it is not possible to nest arr! macro calls. yet.)
static VOLS1: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS2: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS3: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS4: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS5: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS6: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS7: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS8: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS9: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS10: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS11: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS12: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS13: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS14: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS15: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
static VOLS16: [AtomicUsize; N_INPUTS] = arr![AtomicUsize::new(0); 16];
fn main() {
let matches = App::new(option_env!("CARGO_PKG_NAME").unwrap())
.version(option_env!("CARGO_PKG_VERSION").unwrap())
.about(option_env!("CARGO_PKG_DESCRIPTION").unwrap())
.help_template("{bin} ({version})\n{about}\n\nUsage:\n {usage}\n\nTo send a certain amount of one input to a output send a OSC message that looks like this: /ch/1/send/16 <volume>\nThis would set the send volume of input 1 to output 16 to the value of <volume>. A value of 0.0 would be off, a value of 1.0 would result in a unattenuated signal. Values above 1.0 result in amplification.\n\nOSC-Addresses:\n /ch/<in>/send/<out> <volume> Set the send volume (in → out)\n\nOptions:\n{options}")