git ssb

0+

dinoworm 🐛 / metronome



Commit fca343292fb72c697c29294488b5b36397ac1dc5

gotta catch the beat

Michael Williams committed on 5/13/2018, 11:47:46 AM
Parent: f675cb27f2640ba304b1816b279b2ef7f8c19a59

Files changed

README.mdchanged
src/clock.rschanged
src/control.rschanged
src/interface.rschanged
src/main.rschanged
README.mdView
@@ -1,5 +1,26 @@
1-## notes
1 +# metronome
22
3 +a simple metronome in rust
4 +
5 +_work in progress_
6 +
7 +## usage
8 +install rust
9 +
10 +> on debian:
11 +>
12 +> ```
13 +> sudo apt install libncurses5-dev libncursesw5-dev
14 +> ```
15 +
316 ```shell
4-sudo apt install libncursesw5-dev
17 +git clone https://github.com/ahdinosaur/metronome
18 +cd metronome
19 +cargo run
520 ```
21 +
22 +controls:
23 +
24 +- press enter to reset time
25 +- press up and down to nudge tempo
26 +- TODO press space to tap tempo
src/clock.rsView
@@ -2,9 +2,9 @@
22 // http://www.deluge.co/?q=midi-tempo-bpm
33
44 use std::time::{Duration, Instant};
55 use std::thread::{sleep, spawn};
6-use std::sync::mpsc::{channel, Sender, Receiver};
6 +use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};
77
88 use control;
99
1010 pub type Time = Instant;
@@ -19,8 +19,9 @@
1919 static BEATS_PER_MINUTE: u64 = 60;
2020 static DEFAULT_TICKS_PER_BEAT: u64 = 16;
2121 static DEFAULT_BEATS_PER_BAR: u64 = 4;
2222 static DEFAULT_BARS_PER_LOOP: u64 = 4;
23 +static DEFAULT_BEATS_PER_MINUTE: f64 = 60_f64;
2324
2425 #[derive(Clone, Copy, Debug, Hash)]
2526 pub struct ClockSignature {
2627 pub nanos_per_beat: u64, // tempo
@@ -42,8 +43,12 @@
4243 bars_per_loop: DEFAULT_BARS_PER_LOOP,
4344 }
4445 }
4546
47 + pub fn default () -> Self {
48 + Self::new(DEFAULT_BEATS_PER_MINUTE)
49 + }
50 +
4651 pub fn to_beats_per_minute (&self) -> f64 {
4752 let nanos_per_beat = self.nanos_per_beat;
4853 let beats_per_nano = 1_f64 / self.nanos_per_beat as f64;
4954 let beats_per_second = beats_per_nano * NANOS_PER_SECOND as f64;
@@ -104,34 +109,70 @@
104109 signature: ClockSignature
105110 }
106111
107112 pub enum ClockMessage {
108- Time(ClockTime)
113 + Reset,
114 + NudgeTempo(f64),
115 + Signature(ClockSignature)
109116 }
110117
111118 impl Clock {
112- pub fn new (signature: ClockSignature) -> Self {
119 + pub fn new () -> Self {
113120 let start = Time::now();
114-
121 + let signature = ClockSignature::default();
122 +
115123 Self {
116124 start,
117125 tick: start,
118126 signature
119127 }
120128 }
121129
122- pub fn start (signature: ClockSignature, control_tx: Sender<control::ControlMessage>) {
123- let mut clock = Self::new(signature);
130 + pub fn start (control_tx: Sender<control::ControlMessage>) -> Sender<ClockMessage> {
131 + let mut clock = Self::new();
124132
133 + let (tx, rx) = channel();
134 +
135 + control_tx.send(control::ControlMessage::Signature(ClockSignature::new(DEFAULT_BEATS_PER_MINUTE))).unwrap();
136 +
125137 spawn(move|| {
126138 loop {
127- clock.tick();
139 + // wait a tick
140 + let diff = clock.tick();
128141
142 + // send clock time
129143 control_tx.send(control::ControlMessage::Time(clock.time())).unwrap();
144 +
145 + // handle any incoming messages
146 + let message_result = rx.try_recv();
147 + match message_result {
148 + Ok(ClockMessage::Reset) => {
149 + clock.reset();
150 + },
151 + Ok(ClockMessage::Signature(signature)) => {
152 + clock.signature = signature;
153 + },
154 + Ok(ClockMessage::NudgeTempo(nudge)) => {
155 + let old_beats_per_minute = clock.signature.to_beats_per_minute();
156 + let new_beats_per_minute = old_beats_per_minute - nudge;
157 + let next_signature = ClockSignature::new(new_beats_per_minute);
158 + control_tx.send(control::ControlMessage::Signature(next_signature));
159 + },
160 + Err(TryRecvError::Empty) => {},
161 + Err(TryRecvError::Disconnected) => {
162 + panic!("{:?}", TryRecvError::Disconnected);
163 + }
164 + }
130165 }
131166 });
167 +
168 + tx
132169 }
133170
171 + pub fn reset (&mut self) {
172 + self.start = Time::now();
173 + }
174 +
134175 pub fn time (&self) -> ClockTime {
135176 ClockTime::new(self.nanos_since_start(), self.signature)
136177 }
137178
src/control.rsView
@@ -18,16 +18,19 @@
1818 }
1919 }
2020 }
2121
22-#[derive(Clone, Copy, Debug, Hash)]
22 +#[derive(Clone, Copy, Debug)]
2323 pub enum ControlMessage {
2424 Time(clock::ClockTime),
2525 Signature(clock::ClockSignature),
26- Start,
26 + Reset,
27 + NudgeTempo(f64),
28 + TapTempo
29 + /*
2730 Stop,
28- TapTempo,
2931 SetTempo,
3032 NudgeClock,
3133 Configure
34 + */
3235 }
3336
src/interface.rsView
@@ -12,19 +12,15 @@
1212 static CHAR_RETURN: u32 = 0x000D;
1313 static CHAR_NEWLINE: u32 = 0x000A;
1414
1515 #[derive(Debug)]
16-pub struct TerminalInterface {
17- pub tx: Sender<InterfaceMessage>
18-}
16 +pub struct TerminalInterface {}
1917
2018 impl TerminalInterface {
21- pub fn start (signature: clock::ClockSignature, control_tx: Sender<control::ControlMessage>) -> Self {
19 + pub fn start (control_tx: Sender<control::ControlMessage>) -> Sender<InterfaceMessage> {
2220 let (tx, rx) = channel();
2321
24- let interface = Self {
25- tx
26- };
22 + let mut signature = clock::ClockSignature::default();
2723
2824 spawn(move|| {
2925 /* Setup ncurses. */
3026 ncurses::initscr();
@@ -43,19 +39,31 @@
4339 let ch = ncurses::wget_wch(ncurses::stdscr());
4440
4541 match ch {
4642 Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => {
47- control_tx.send(control::ControlMessage::TapTempo).unwrap();
4843 }
4944
45 + Some(WchResult::KeyCode(ncurses::KEY_UP)) => { // why is up down?
46 + control_tx.send(control::ControlMessage::NudgeTempo(-1_f64)).unwrap();
47 + }
48 +
49 + Some(WchResult::KeyCode(ncurses::KEY_DOWN)) => { // why is down up?
50 + control_tx.send(control::ControlMessage::NudgeTempo(1_f64)).unwrap();
51 + }
52 +
5053 // https://github.com/jeaye/ncurses-rs/blob/master/src/constants.rs
51- Some(WchResult::KeyCode(_)) => {}
54 + Some(WchResult::KeyCode(_)) => {
55 + }
5256
5357 // Some(WchResult::KeyCode(KEY_ENTER)) => beat(),
5458 Some(WchResult::Char(ch)) => {
55- if (ch == CHAR_SPACE || ch == CHAR_NEWLINE) {
59 + if (ch == CHAR_SPACE) {
5660 control_tx.send(control::ControlMessage::TapTempo).unwrap();
5761 }
62 +
63 + if (ch == CHAR_NEWLINE) {
64 + control_tx.send(control::ControlMessage::Reset).unwrap();
65 + }
5866 }
5967
6068 None => {}
6169 }
@@ -76,17 +84,18 @@
7684 print_bar(time);
7785 print_time(time);
7886 print_signature(signature);
7987 },
80- InterfaceMessage::Signature(signature) => {
88 + InterfaceMessage::Signature(next_signature) => {
89 + signature = next_signature;
8190 }
8291 }
8392
8493 ncurses::refresh();
8594 }
8695 });
8796
88- interface
97 + tx
8998 }
9099 }
91100
92101 pub fn print_beat (time: clock::ClockTime) {
src/main.rsView
@@ -8,30 +8,37 @@
88 Metronome::run(60_f64);
99 }
1010
1111
12-pub type Bpm = f64;
12 +pub type Tempo = f64;
1313
14-struct Metronome {
15- pub bpm: Bpm
16-}
14 +struct Metronome {}
1715
1816 impl Metronome {
19- pub fn run (bpm: Bpm) {
17 + pub fn run (tempo: Tempo) {
2018 let control = control::Control::new();
2119
22- let clock_signature = clock::ClockSignature::new(bpm);
20 + let terminal_tx = interface::TerminalInterface::start(control.tx.clone());
21 + let clock_tx = clock::Clock::start(control.tx.clone());
2322
24- let clock = clock::Clock::start(clock_signature, control.tx.clone());
25- let terminal_interface = interface::TerminalInterface::start(clock_signature, control.tx.clone());
26-
2723 for control_message in control.rx {
2824 match control_message {
25 + // sent by interface
26 + control::ControlMessage::Reset => {
27 + clock_tx.send(clock::ClockMessage::Reset).unwrap();
28 + },
29 + // sent by interface
30 + control::ControlMessage::NudgeTempo(nudge) => {
31 + clock_tx.send(clock::ClockMessage::NudgeTempo(nudge)).unwrap();
32 + },
33 + // sent by clock
2934 control::ControlMessage::Signature(signature) => {
30- terminal_interface.tx.send(interface::InterfaceMessage::Signature(signature)).unwrap();
35 + clock_tx.send(clock::ClockMessage::Signature(signature)).unwrap();
36 + terminal_tx.send(interface::InterfaceMessage::Signature(signature)).unwrap();
3137 },
38 + // sent by clock
3239 control::ControlMessage::Time(time) => {
33- terminal_interface.tx.send(interface::InterfaceMessage::Time(time)).unwrap();
40 + terminal_tx.send(interface::InterfaceMessage::Time(time)).unwrap();
3441 },
3542 _ => {}
3643 }
3744 }

Built with git-ssb-web