Time signature, data structure tweaks

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2026-03-28 01:20:37 +02:00
parent ecc931dbb7
commit 3ca8a24443

View File

@@ -1,5 +1,5 @@
use anyhow::{Result, anyhow}; use anyhow::{Result, anyhow};
use macroquad::prelude::*; use macroquad::color::*;
use serialport::SerialPortType; use serialport::SerialPortType;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@@ -12,7 +12,6 @@ pub enum Instruction {
pub struct SerialDevice { pub struct SerialDevice {
port: Box<dyn serialport::SerialPort>, port: Box<dyn serialport::SerialPort>,
ready: bool,
} }
const CHANNEL_COUNT: u8 = 4; const CHANNEL_COUNT: u8 = 4;
@@ -26,18 +25,16 @@ impl SerialDevice {
SerialPortType::UsbPort(_) => { SerialPortType::UsbPort(_) => {
this = Ok(Self { this = Ok(Self {
port: serialport::new(port.port_name, 115200).open()?, port: serialport::new(port.port_name, 115200).open()?,
ready: true,
}); });
break;
} }
_ => {} _ => {}
}; };
break;
} }
this this
} }
fn note_off(&mut self, ch: u8) -> Result<()> { fn note_off(&mut self, ch: u8) -> Result<()> {
assert!(self.ready);
assert!((0..CHANNEL_COUNT).contains(&ch)); assert!((0..CHANNEL_COUNT).contains(&ch));
let bytes: Vec<u8> = vec![0x80 + ch]; let bytes: Vec<u8> = vec![0x80 + ch];
self.port.write(&bytes)?; self.port.write(&bytes)?;
@@ -45,7 +42,6 @@ impl SerialDevice {
} }
fn note_on(&mut self, ch: u8, note: u8) -> Result<()> { fn note_on(&mut self, ch: u8, note: u8) -> Result<()> {
assert!(self.ready);
assert!((0..CHANNEL_COUNT).contains(&ch)); assert!((0..CHANNEL_COUNT).contains(&ch));
assert!((0..=127).contains(&note)); assert!((0..=127).contains(&note));
let bytes: Vec<u8> = vec![0x90 + ch, note]; let bytes: Vec<u8> = vec![0x90 + ch, note];
@@ -54,19 +50,16 @@ impl SerialDevice {
} }
fn modulation(&mut self, ch: u8, depth: u8, rate: u8) -> Result<()> { fn modulation(&mut self, ch: u8, depth: u8, rate: u8) -> Result<()> {
assert!(self.ready);
assert!((0..CHANNEL_COUNT).contains(&ch)); assert!((0..CHANNEL_COUNT).contains(&ch));
assert!((0..=127).contains(&depth)); assert!((0..=127).contains(&depth));
assert!((0..=255).contains(&rate));
let bytes: Vec<u8> = vec![0xA0 + ch, depth, rate]; let bytes: Vec<u8> = vec![0xA0 + ch, depth, rate];
self.port.write(&bytes)?; self.port.write(&bytes)?;
Ok(()) Ok(())
} }
fn frequency_on(&mut self, ch: u8, freq: u16) -> Result<()> { fn frequency_on(&mut self, ch: u8, freq: u16) -> Result<()> {
assert!(self.ready);
assert!((0..CHANNEL_COUNT).contains(&ch)); assert!((0..CHANNEL_COUNT).contains(&ch));
let bytes: Vec<u8> = vec![0xB0 + ch, (freq & 0xff) as u8, (freq & 0xff00 >> 8) as u8]; let bytes: Vec<u8> = vec![0xB0 + ch, (freq & 0xff) as u8, (freq >> 8) as u8];
self.port.write(&bytes)?; self.port.write(&bytes)?;
Ok(()) Ok(())
} }
@@ -87,28 +80,55 @@ impl SerialDevice {
} }
} }
const INSTRUCTIONS_PATTERN: usize = 1024;
pub struct Pattern { pub struct Pattern {
pub channels: [[Option<Instruction>; INSTRUCTIONS_PATTERN]; CHANNEL_COUNT as usize], pub rows: Vec<[Option<Instruction>; CHANNEL_COUNT as usize]>,
} }
impl Pattern { impl Pattern {
pub fn new() -> Self { pub fn new() -> Self {
let mut rows = Vec::new();
rows.resize_with(256, || [None; CHANNEL_COUNT as usize]);
Self { rows }
}
}
pub struct TimeSignature {
pub numerator: u8,
pub denominator: u8,
}
impl Default for TimeSignature {
fn default() -> Self {
Self { Self {
channels: [[None; INSTRUCTIONS_PATTERN]; CHANNEL_COUNT as usize], numerator: 4,
denominator: 4,
} }
} }
} }
pub struct Song { pub struct Song {
pub bpm: f64,
pub time_signature: TimeSignature,
pub patterns: Vec<Pattern>, pub patterns: Vec<Pattern>,
pub pattern_order: Vec<usize>, // index into patterns pub pattern_order: Vec<usize>, // index into patterns
} }
impl Song { impl Song {
pub fn new() -> Self { const DEFAULT_BPM: f64 = 120.0;
pub fn new(bpm: Option<f64>, time_signature: Option<TimeSignature>) -> Self {
Self { Self {
bpm: bpm.unwrap_or(Self::DEFAULT_BPM),
time_signature: time_signature.unwrap_or_default(),
patterns: vec![Pattern::new()],
pattern_order: vec![0],
}
}
pub fn empty(bpm: Option<f64>, time_signature: Option<TimeSignature>) -> Self {
Self {
bpm: bpm.unwrap_or(Self::DEFAULT_BPM),
time_signature: time_signature.unwrap_or_default(),
patterns: Vec::new(), patterns: Vec::new(),
pattern_order: Vec::new(), pattern_order: Vec::new(),
} }
@@ -130,14 +150,20 @@ impl App {
} }
async fn update(&self) { async fn update(&self) {
clear_background(RED); macroquad::window::clear_background(WHITE);
draw_line(40.0, 40.0, 100.0, 200.0, 15.0, BLUE); macroquad::shapes::draw_line(40.0, 40.0, 100.0, 200.0, 15.0, BLUE);
draw_rectangle(screen_width() / 2.0 - 60.0, 100.0, 120.0, 60.0, GREEN); macroquad::shapes::draw_rectangle(
macroquad::window::screen_width() / 2.0 - 60.0,
100.0,
120.0,
60.0,
GREEN,
);
draw_text("Hello, Macroquad!", 20.0, 20.0, 30.0, DARKGRAY); macroquad::text::draw_text("Hello, Macroquad!", 20.0, 20.0, 30.0, DARKGRAY);
next_frame().await macroquad::window::next_frame().await
} }
} }