gzweigle / open-hybrid-piano

Building a hybrid MIDI digital piano
https://www.youtube.com/@gzpiano88
GNU General Public License v3.0
44 stars 1 forks source link

FW, ME: Selecting hammers/dampers in the IPS boards #9

Open davidedelvento opened 11 months ago

davidedelvento commented 11 months ago

Let's assume that one wants to have both hammers and dampers sensors. If my understanding is correct, current firmware require wiring all hammers (via SCA boards) to one IPS board and all dampers (again via SCA boards) to the other IPS board.

I think it would make it much easier wiring (shorter wires and less crossing cables) and much more efficient use of resources if each board could be configured (in firmware) to act as a hybrid hammers/dampers IPS for half the keyboard. The wiring is clear: you will be wiring only half the keyboard to one board, and the other half to the other board, halving the total length of the cables (potentially reducing noise when doing so, but I am not sure).

For the "more efficient use of resources" consider this scenario to begin: nothing is playing on the piano, both boards (and their ADCs in the SCA boards) are "frantically" sampling all sensors waiting for something to happen. Well, sampling the dampers is unnecessary, so that's the first waste, but that's not my main concern. The main concern is that sampling must be fast to make sure the latency between "key is played" and "MIDI signal is sent" is the lowest possible. Since the ADCs are multiplexed, we are not as fast as possible with the hardware we have. If a single board could be used to sample both hammers and dampers, the ADCs can be multiplexed at twice the frequency (because there is no need to check the damper until the note has been played), effectively having the ADC latency with no change in hw. Similarly, the software could probably be prevented from spending cycles checking the dampers until the note is played.

Of course this optimization cannot be used when a note is being held, because in such scenario it could be either re-played or it could be released and to detect what happens we must sample both the hammer and the damper sensor. But only about 10 notes can be held at a same time (given the players typically have 10 fingers), so still the optimization will work with 78/88 ~ 88% efficiency! It would be particularly useful if the dampers for one note will be assigned to a SCA board different from the corresponding hammer. Why? Because as described above when a note is held one has to monitor both hammer and damper and that would decrease the sampling rate when one needs it most, i.e. when the likelihood of repetitions and nearby note playing is highest.

Would this be extremely complicated with current firmware (which I have not studied yet) or is it doable? I'm willing to contribute to software and wiring scheme design if you deem it worthwhile.

gzweigle commented 11 months ago

The present released code scans all 96 inputs every 400 microseconds (adc_sample_period_microseconds in hammer_settings.cpp). My plan to go faster was more ADC on SCA, running in parallel (up to 6x fast is possible). But agree, another approach is as described above. No board spins needed.

gzweigle commented 5 months ago

An advantage of present approach is single MIDI output. Also, I have optimized the firmware to get the sample period down to 300 microseconds.

I've been playing the piano regularly for over half a year and the piano plays very well at this sample rate. Especially after fixing many sources of error (per YouTube video I recently posted).

My roadmap for faster sample rate remains the ADC parallelization on SCA, which requires only changes to the small, removable, SCA card.

The proposed architecture is very interesting but I in the interest of keeping the backlog small, I am considering to close this issue. Comments?

davidedelvento commented 5 months ago

Yes, single MIDI out is highly desirable, but I don't see how it's relevant here? Probably just my ignorance here, this is what I am thinking: if you have separate hammer and damper boards each with 88 (or 96) channels, vs having two boards each one using half the keys but both hammers and dampers? If you need single MIDI out, in both cases the two boards need to communicate with each other and consolidate the output. If that consolidation code does not exist yet and it's not a priority to write it yet, in one case you have note-on from one board and note-off from another (which can be problematic for digital instruments), whereas in the other you have note-on and note-off from the same board (just for different note-number) which should be easier on the receiving size.

Moreover, IMHO, one big advantage of this approach is also the wiring: each board can be located closer to the relevant keys, simplifying wiring a lot.

Regarding your actual question about the ADC thing, I have no strong opinion, and the only opinion I have is not backed by data, since I have not been using a complete instrument as you have. I would just note that this aspect may be related to #55 but on that topic too you know that part better than I can comment.

So in conclusion, my opinion is that this is still a desirable feature to implement (leave the issue open), even though it may not be as important for some of the goals I originally mentioned, such as increase ADC rate (deprioritize).

gzweigle commented 5 months ago

I am happy to leave open. I agree on the wire length benefit.

With present architecture, dampers are optional. Just add a damper board (identical to hammer board). Nothing else changes.

With respect to MIDI - it is output from the hammer board only. Damper measurements are sent over CAN bus from damper board to hammer board. Hammer board consolidates to a single MIDI output. The dampers, as you correctly noted, require less resolution and so I was able to fit all damper data over the relatively slow CAN bus.

gzweigle commented 5 months ago

Here is the damper board to hammer board code:

https://github.com/gzweigle/DIY-Grand-Digital-Piano/blob/main/firmware/releases/StemPianoIPS2/src/board2board.cpp