Skip to content

Commit

Permalink
passing references and slices around, no yield
Browse files Browse the repository at this point in the history
There's an issue with thread::yield_now() that causes it to eat CPU
cycles when used in a loop. Recommended to use sleep(1ms) instead

rust-lang/rust#46774
  • Loading branch information
dctucker committed Mar 8, 2022
1 parent 4394387 commit 96e578a
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 43 deletions.
2 changes: 1 addition & 1 deletion rust/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl App {
}
break 'signal;
}
std::thread::yield_now();
thread::sleep(Duration::from_millis(500));
}

let mut done = false;
Expand Down
16 changes: 7 additions & 9 deletions rust/src/filters/ccmap.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

#[derive(Debug)]
pub struct CCMap { channel : u8, out_cc : Vec<u8> }
pub struct CCMap { channel : u8, out_cc : [u8 ; 0xff] }
impl CCMap {
pub fn new( args : String ) -> CCMap {
let out_cc = vec![ 0 ; 0xff ];
let out_cc = [ 0u8 ; 0xff ];
let channel = args.split(",").next().unwrap();

let mut ccmap = CCMap {
Expand All @@ -26,9 +25,8 @@ impl CallbackFn for CCMap {
self.out_cc[in_cc]
);
}
fn callback(&self, data : &mut CallbackData, buf : &Vec<u8>) -> usize {
fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize {
let exp_state : u8 = 0xb0 + self.channel;
let mut out_buf = [0u8 ; BUFSIZE];
let mut cc : u8 = 0xff;
let mut val : u8 = 0xff;

Expand All @@ -47,9 +45,9 @@ impl CallbackFn for CCMap {
} else if val == 0xff {
if cc < 0x80 {
val = *c;
out_buf[a] = exp_state; a += 1;
out_buf[a] = cc; a += 1;
out_buf[a] = val; a += 1;
data.buffer[a] = exp_state; a += 1;
data.buffer[a] = cc; a += 1;
data.buffer[a] = val; a += 1;
}
val = 0xff;
cc = 0xff;
Expand All @@ -59,6 +57,6 @@ impl CallbackFn for CCMap {
val = 0xff;
}
}
data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap()
data.output_device.send_buffer(&data.buffer[0..a]).unwrap()
}
}
8 changes: 3 additions & 5 deletions rust/src/filters/channel.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

#[derive(Debug)]
pub struct Channel { mask : u32 }
impl Channel {
pub fn new( args : String ) -> Channel {
Expand All @@ -17,9 +16,8 @@ impl Channel {
}
}
impl CallbackFn for Channel {
fn callback(&self, data : &mut CallbackData, buf : &Vec<u8>) -> usize {
fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize {
let mask = self.mask;
let mut out_buf = [0u8 ; BUFSIZE];
let mut current_mask = 0;

if data.output_device.midi_in_exclusive == data.midi_in {
Expand All @@ -43,10 +41,10 @@ impl CallbackFn for Channel {
}

if mask & current_mask != 0 {
out_buf[a] = *c;
data.buffer[a] = *c;
a += 1;
}
}
data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap()
data.output_device.send_buffer(&data.buffer[0..a]).unwrap()
}
}
10 changes: 4 additions & 6 deletions rust/src/filters/funnel.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@

#[derive(Debug)]
pub struct Funnel { channel : u8 }
impl Funnel {
pub fn new( args : String ) -> Funnel {
Funnel { channel : parse_hex(&args) }
}
}
impl CallbackFn for Funnel {
fn callback(&self, data : &mut CallbackData, buf : &Vec<u8>) -> usize {
fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize {
let mask = MASK_ALL;
let mut out_buf = [0u8 ; BUFSIZE];
let mut current_mask = 0;

if data.output_device.midi_in_exclusive == data.midi_in {
Expand All @@ -30,16 +28,16 @@ impl CallbackFn for Funnel {
current_mask = MASK_SYSEX;
} else if *c >= 0x80 {
current_mask = 2 << (*c & 0x0f);
out_buf[a] = *c & 0xf0 | self.channel;
data.buffer[a] = *c & 0xf0 | self.channel;
a += 1;
continue;
}

if mask & current_mask != 0 {
out_buf[a] = *c;
data.buffer[a] = *c;
a += 1;
}
}
data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap()
data.output_device.send_buffer(&data.buffer[0..a]).unwrap()
}
}
10 changes: 7 additions & 3 deletions rust/src/filters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ fn parse_hex(arg : &str) -> u8 {
#[derive(Debug)]
pub struct Void { }
impl Void { pub fn new( _args : String ) -> Void { Void { } } }
impl CallbackFn for Void { fn callback(&self, _data : &mut CallbackData, _buf : &Vec<u8>) -> usize { 0 } }
impl CallbackFn for Void { fn callback(&self, _data : &mut CallbackData, _buf : &[u8]) -> usize { 0 } }

include!("channel.rs");
include!("funnel.rs");
include!("ccmap.rs");
include!("status.rs");

#[enum_dispatch]
#[derive(Debug)]
pub enum Callback {
Void,
Channel,
Expand All @@ -38,7 +37,7 @@ pub enum Callback {

#[enum_dispatch(Callback)]
pub trait CallbackFn {
fn callback(&self, _data : &mut CallbackData, _buf : &Vec<u8>) -> usize;
fn callback(&self, _data : &mut CallbackData, _buf : &[u8]) -> usize;
fn add_args( &mut self, _args : String ) {}
}

Expand All @@ -53,3 +52,8 @@ impl Callback {
}
}
}
impl std::fmt::Debug for Callback {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Callback {{ }}")
}
}
13 changes: 5 additions & 8 deletions rust/src/filters/status.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::convert::TryInto;

#[derive(Debug)]
pub struct Status { out_status : Vec<u8> }
pub struct Status { out_status : [u8 ; 0x80] }
impl Status {
pub fn new( args : String ) -> Status {
let mut out_status = vec![ 0 ; 0x80 ];
let mut out_status = [ 0 ; 0x80 ];
for arg in args.split(",") {
let status = parse_hex(arg);
let i : usize = ((0x80 | status) - 0x80).try_into().unwrap();
Expand All @@ -14,20 +13,18 @@ impl Status {
}
}
impl CallbackFn for Status {
fn callback(&self, data : &mut CallbackData, buf : &Vec<u8>) -> usize {
let mut out_buf = [0u8 ; BUFSIZE];

fn callback(&self, data : &mut CallbackData, buf : &[u8]) -> usize {
let mut a = 0;
let out_status = &self.out_status;

for c in buf {
let cur_state = data.output_device.scan_status(*c);
let i : usize = ((0x80 | cur_state) - 0x80).try_into().unwrap();
if out_status[i] == cur_state {
out_buf[ a ] = *c;
data.buffer[ a ] = *c;
a += 1;
}
}
data.output_device.send_buffer(&out_buf[0..a].to_vec()).unwrap()
data.output_device.send_buffer(&data.buffer[0..a]).unwrap()
}
}
11 changes: 7 additions & 4 deletions rust/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,23 @@ impl OutputDevice {
},
}
}
pub fn send_buffer(&mut self, buf : &Vec<u8> ) -> Result<usize, String> {
pub fn send_buffer(&mut self, buf : &[u8] ) -> Result<usize, String> {
if buf.len() == 0 {
return Ok(0)
}
let midi = match &self.midi {
Some(mutex) => match mutex.lock() {
Ok(m) => m,
Err(_) => return Err(format!("Could not lock {}", self.port_name)),
},
None => {
println!("Device not connected {}", self.port_name);
//println!("Device not connected {}", self.port_name);
return Ok(0)
},
};
match midi.io().write(buf) {
Ok(n) => {
self.handle_write(buf.to_vec());
self.handle_write(buf);
let mut status : u8 = self.status;
for c in buf.iter() {
if *c >= 0x80 {
Expand All @@ -71,7 +74,7 @@ impl OutputDevice {
Err(_) => Err(format!("Error writing to {}", self.port_name)),
}
}
fn handle_write(&self, buf : Vec<u8>) {
fn handle_write(&self, buf : &[u8]) {
print!("O");
for x in buf.iter(){ print!(" 0x{:02x}", x); }
println!(" {}", self.port_name);
Expand Down
38 changes: 33 additions & 5 deletions rust/src/thru.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ impl ReadData {
self.outs.push( WriteData::new(&out, func, args) );

}
fn handle_read(&mut self, buf : Vec<u8>) {
fn handle_read(&mut self, buf : &[u8]) {
print!("I");
for x in buf.iter(){ print!(" 0x{:02x}", x); }
println!(" {}", self.port_name);
for w in self.outs.iter_mut() {
w.call(&buf);
w.call(buf);
}
}
}
Expand All @@ -73,21 +73,49 @@ impl fmt::Debug for ReadThread {
}
impl ReadThread {
fn read_loop( flags : &Arc<Flags>, arc : &Arc<RwLock<ReadData>>, midi : &Rawmidi ) {
/*
// calculate BPM
let mut clock = std::time::Instant::now();
let mut clock1;
const BPM_SIZE : usize = 32;
let mut bpms = vec![ 0.0f64 ; BPM_SIZE];
let mut bpm_offset : usize = 0;
*/
let mut buf = [0u8; BUFSIZE];
'read: loop {
use alsa::PollDescriptors;
let mut buf : Vec<u8> = vec![0; BUFSIZE];
while ! flags.run.load(Ordering::Relaxed) {
if flags.hup.swap(false, Ordering::Relaxed) { break 'read; }
thread::sleep(Duration::from_millis(500));
}
thread::yield_now();
//thread::yield_now();
if flags.int.load(Ordering::Relaxed) { break 'read; }

let res = alsa::poll::poll(&mut midi.get().unwrap(), 500).unwrap();
//clock1 = std::time::Instant::now();
if res == 0 { continue; }

match midi.io().read(&mut buf) {
Ok(n) => {
arc.write().unwrap().handle_read( buf[0..n].to_vec() );
/*
// calculate BPM
for c in &buf[0..n] {
if *c == 0xf8 {
let bpm = 2_500_000.0f64 / (clock1.duration_since(clock).as_micros() as f64);
bpms[ bpm_offset ] = bpm;
bpm_offset = (bpm_offset + 1) % BPM_SIZE;
let mut sum : f64 = 0.0;
for b in &bpms {
sum += b;
}
sum /= BPM_SIZE as f64;
println!("Tempo = {:?} BPM", sum);
clock = clock1;
break;
}
}
*/
arc.write().unwrap().handle_read( &buf[0..n] );
},
Err(_) => {
println!("Error reading");
Expand Down
15 changes: 13 additions & 2 deletions rust/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ use std::fmt;
use crate::filters::CallbackFn;
use crate::output::OutputDevice;
use crate::filters;
use crate::thru::BUFSIZE;

pub struct CallbackData<'a> {
pub output_device : &'a mut OutputDevice,
pub buffer : &'a mut [u8],
pub midi_in : String,
}

Expand All @@ -15,6 +17,7 @@ pub struct WriteData {
args: String,
pub midi_in : String,
pub callback : filters::Callback,
pub buffer : [u8 ; BUFSIZE],
}
impl fmt::Debug for WriteData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -30,15 +33,23 @@ impl WriteData {
func_name: func.clone(),
args: args.clone(),
midi_in: "".to_string(),
buffer: [ 0u8 ; BUFSIZE ],
callback: filters::Callback::new( func, args.clone() ),
}
}
pub fn add_args(&mut self, args : String) {
self.callback.add_args(args);
}
pub fn call(&mut self, buf : &Vec<u8>) {
pub fn call(&mut self, buf : &[u8]) {
let output_device = &mut match self.output_device.write() {
Ok(dev) => dev,
Err(_) => {
return;
},
};
let mut data = CallbackData {
output_device: &mut self.output_device.write().unwrap(),
output_device: output_device,
buffer: &mut self.buffer,
midi_in: self.midi_in.to_string(),
};
self.callback.callback(&mut data, buf);
Expand Down

0 comments on commit 96e578a

Please sign in to comment.