cardonabits / haxo-rs

Software for the haxophone
MIT License
42 stars 10 forks source link

Sending MIDI CC#7 frequently and when there's no change #30

Closed Ekolide closed 8 months ago

Ekolide commented 8 months ago

Hi!

Using the USB MIDI capabilities of the Haxophone running on a Raspberry Pi Zero, currently it's dumping it's breath/volume (CC#7) very frequently, and when there's no change to it's value.

So if there's no breath input on the Haxophone, it sends CC#7 at a value of 0 at a rapid pace. When there is input, it sends the same value at a rapid pace, possibly tens of times before the player shifts their breath, and CC#7 changes value.

I was using aseqdump (part of alsa-utils) on a Debian 11 install when I noticed this. There's a plethora of MIDI monitor programs for other distributions. I don't know the frequency at which it sends CC#7, but it was practically impossible to debug any other MIDI message. I tried a couple of ideas to record the output, but none conveyed the effect.

Of course, using another MIDI monitor you could filter out the messages you don't want to see. But I'm wondering if this might be one of the reasons that MIDI latency currently is high. The bandwidth might be filled by messages with CC#7, needing to be processed by the receiver. I have a commercial embedded Linux device with a USB Host port that supports USB MIDI, and there's been no latency issues for me at all. It runs a higher latency internally than my Debian install, but still has a much lower latency feel. So improvement somewhere should be possible.

My suggested change is to only send a CC#7 value when it has changed. This probably won't affect FluidSynth at all, or it might be a performance improvement.

Let me know if there's any questions or anything that needs to be clarified.

jcard0na commented 8 months ago

Thanks, this makes sense. This is where this would have to be fixed: https://github.com/cardonabits/haxo-rs/blob/main/src/main.rs#L116-L120

Something along these lines might do it:


     let mut neg_pressure_countdown: u32 = NEG_PRESS_INIT_VAL;
+    let mut last_vol: i32 = 0;
     loop {
         tick.recv().unwrap();
         #[cfg(feature = "instrumentation")]
         busy_pin.set_high();

         let keys = keyscan::scan()?;
         let pressure = sensor.read()?;
         let vol = max(0, pressure);
+        if last_vol != vol {
             const MIDI_CC_VOLUME: i32 = 7;
             synth.cc(0, MIDI_CC_VOLUME, vol);
             #[cfg(feature = "midi")]
             midi_out.cc(MIDI_CC_VOLUME, vol);
+           last_vol = vol;
+         }