Skip to content

Scanning speed and velocity mapping of Cybrid

gzpiano

For my DIY hybrid version, it continuously computes the velocity with an FIR digital filter (in a microprocessor).  See line 56 of Matlab code in linked github page above.  When I play the piano, it sounds great…..although….. only 8 keys assembled…. no la campanella….


RIP

gzpiano For my DIY hybrid version, it continuously computes the velocity with an FIR digital filter

Do you mean this line

dx = filter(b,[1],samples) * 2 * 0.0254 * sample_rate / (M+2);

Where is filter defined? Is it intrinsic matlab function?

Edit: Please ignore the dollar signs above. If you are curious they were supposed to make the above line "look like a formula", but they don't work. The dollars gave me gripe when using them as money unit, continue to give me gripe when using them as function / code delimiters. They are displayed normally in the text, but they are untouchable in edit mode: once you mistakenly type them (as I did) you can never delete them (try if you don't believe me)


CyberGene

RIP I fixed it for you but you need to use backticks, not dollar signs.


xooorx

luns The "hammer" sensors I'm aware of are at the shank, or rather the flange. [...]

luns I do doubt that the measurement is limited to the few mm of hammer position between let-off and hammer strike.

Looking at the ATX service manual...

1) Let-off is set at 4mm (page 10). Possibly slightly wider than a pure acoustic action to accommodate the stop rail? To make the sensing easier?

2) Taking measurements from figure 4 (page 4) suggests the measurement is taken over a hammer movement of about 3mm, although the shutter on the flange is only moving around half this distance due to its location. The figure may well not be to scale but it is clear anyway from the shape of the shutter that the distance measured is very small.

3) From the section on adjusting the sensor height (page 12):

For instances, if the sensor is located at an extremely high position, the position of emitting sound may be higher than the position where the hammer stops by the stop rail. In this state, no electronic sound will be emitted.
On the contrary, if the sensor is located too low, this may cause deterioration of the functionality in detecting consecutive key stroking.

So... "too high" = past the stop rail, "too low" = repetition stops working i.e. below the let-off, so it seems that "just right" is indeed limited to the few mm of hammer position between let-off and hammer strike.


vagfilm

gzpiano , it continuously computes the velocity with an FIR digital filter (in a microprocessor).

FIR filtering... Clever idea. But using unsupervised realtime FIR filtering, are you able to separate a low velocity hit from a low velocity silent note (ie, the hammer is slowly advanced to 1-2mm of the string and does not touch it because of the jeck slipping under the knuckle? And can you compute strikes that have 2 velocities (ie, slow advance until let off point and the sudden acceleration?). My basic knowledge of FIR makes me think it is good for linear movements not complex "multipeak" so to say... Am I wrong? (most probably because I am above my paygrade here 😊). Asking this because FIR may be an interesting approach to realtime analysis of my non-music related professional data signals, but I never attempted to use it, and maybe I should...


vagfilm

RIP Where is filter defined? Is it intrinsic matlab function?

Per @gzpiano post I assume the FIR is computed in the microprocessor and the result fed to matlab.


RIP

vagfilm delvento Where is filter defined? Is it intrinsic matlab function?

Per @stem_piano post I assume the FIR is computed in the microprocessor and the result fed to matlab.

Perhaps, but the matlab code has a filter function call which is not defined in the provided source, so I wonder what that is.


gzpiano

RIP

Yeah, filter() is a Matlab function. Its just a convolution (denominator is set to [1] on line 56). You should be able to run this code with Octave as well, which is free open source. The hammer position sample data is provided in the same directory.

If anyone wants to go this route, its fairly easy to find DSP libraries that implement the taps on line 41. Those taps include a lowpass filter to reduce some of the differentiation noise.

Although I am happily building my worlds-most-unnecessarily-complicated-DIY-hybrid, I am also happy to help out other projects, for example providing a filter implementation pull request. However, I can't guarantee any schedule or deadlines.

vagfilm

Yes for sure, there needs to be more to the algorithm. FIR is just the subset for a continuous velocity calculation.


vagfilm

gzpiano FIR is just the subset for a continuous velocity calculation.

Thanks and "too bad"... It would be neat for my other things... But I may give it a spin since I never played with FIR filtering.


JayKominek

gzpiano For my DIY hybrid version, it continuously computes the velocity with an FIR digital filter (in a microprocessor).  See line 56 of Matlab code in linked github page above.

Any opinions on alternative filter constructions? I was fiddling with Savitzky-Golay on some old recorded data last night, getting decent looking results, and was thinking about trying to squish it into my firmware this afternoon.


gzpiano

JayKominek

Good idea. I convolved a boxcar (moving average, [1 1 1 1 1… 1]) with a first order numerical derivative [1 -1] to get the taps in that code on github. Rather simple. Where I have seen noise most problematic is in low velocity hammer strikes. Super quiet notes. Savitzky–Golay might be a great way to get better accuracy for that case.

The github data is relatively fast strikes, so it doesn't show the noise issue as much.


xooorx

gzpiano Any chance you could post some of the low velocity strike data? I've been messing around with the strike data that's on GitHub (and may post something about that soon) but if there's some more problematic data it would be good to see it.

Also, how constrained are you for processing power? Are you doing boxcar + first order just to try the simple stuff first or are you needing to avoid multiplications and divisions?


gzpiano

xooorx

Sure, next time I have everything put together I will try to remember.

Meanwhile, this link is the place in my algorithm video where I have a plot of the issue:

With respect to processing power, that was not really a factor.


RIP

gzpiano this link is the place in my algorithm

Thanks. You've done quite a number of interesting videos.

gzpiano With respect to processing power, that was not really a factor.

I agree. Even with a limited RP2040, I can do about almost one hundred of loops per ms. In each loop I synchronously and sequentially sample the position of three hammers (eventually will do that async with DMA, this is the slowest of everything done in each loop), do some calculations, send data synchronously via I2C (also slow, but done only when needed) and more. Doing a filter like (or even something more complicated) this is nothing.

I am banging my head wrt some stupid details (go https://github.com/davidedelvento/Rpi-pico-i2c-example if you are curious) when those will be solved I'll have a pretty decent 9-key electronics which I can install in the piano and with enough firmware to work (among other things, with some regulation possible via MIDI 😎️) and provide my own hammer strike data to further analyze.

Let me go do that right now…


JayKominek

RIP with a limited RP2040, I can do about almost one hundred of loops per ms. In each loop I synchronously and sequentially sample the position of three hammers (eventually will do that async with DMA, this is the slowest of everything done in each loop), do some calculations, send data synchronously via I2C (also slow, but done only when needed) and more. Doing a filter like (or even something more complicated) this is nothing.

You'll have plenty of clock cycles for any integer algorithm you could want, but with only M0 cores, I'd expect single precision floating point algorithms to be prohibitive. I think something like an RC filter at 20kHz might be the limit.


xooorx

gzpiano Good idea. I convolved a boxcar (moving average, [1 1 1 1 1… 1]) with a first order numerical derivative [1 -1] to get the taps in that code on github. Rather simple. Where I have seen noise most problematic is in low velocity hammer strikes. Super quiet notes.

The noise problems I saw when playing around with the samples on GitHub turned out to be due to the heavy quantisation of the data. (I see from comments in the Matlab code that you have a fix for this coming).

The numerical differentiation to get the velocity is differentiating the signal and the quantisation noise, which is OK if you've got enough bits but rapidly falls apart if you don't...

Numerically differentiating a 24 bit sine wave:
int24.png

Numerically differentiating a 16 bit sine wave:
int16.png

Numerically differentiating a 12 bit sine wave:
int12.png

Numerically differentiating an 8 bit sine wave:
int8.png


xooorx

OK I tried various filters and some of them sort of worked a bit, but nothing worked as well as just doing the differentiation between non-adjacent samples e.g. instead of V = P[0] - P[-1], using V = (P[0] - P[-4])/4.

Cleans up the 8-bit version to this:
int6.png

Cleans up the 12-bit version to this:
int7.png

(Also note the plots in the previous post used a fancy 4-point differentiator:
V = (P[-2] - 8P[-1] + 8P[1] - P[2])/12
which is worse than:
V = P[0] - P[-1])


luns

Will write more when I’m at a computer instead of the phone, but for now, I wanted to point out the (p(0)-p(-4))/4 differentiation is really just the p(0)-p(-1) followed by a length-4 unit-area boxcar. The differentiation is inherently high pass, emphasizing noise where there’s not really any signal you would care about, but the boxcar does a passable job of filtering out much of that noise.

The best filter to use in place of the boxcar depends on what we know of the signal we’re trying to detect. For a pure sine wave, the ideal filter would be a narrow bandpass filter tuned to the frequency of the sine wave. For a hammer position which is the second integral of what can look like a spikey acceleration, I would go for some second order lowpass filter, or basically a simple biquad filter.

More later…


xooorx

luns Will write more when I’m at a computer instead of the phone, but for now, I wanted to point out the (p(0)-p(-4))/4 differentiation is really just the p(0)-p(-1) followed by a length-4 unit-area boxcar.

Aha... I tried various ways of filtering the position signal before differentiating but got better results by, effectively, differentiating the position and low-pass filtering the result. (Am no longer sure which way round @gzpiano was doing it).

luns The best filter to use in place of the boxcar depends on what we know of the signal we’re trying to detect.

For quantisation noise it might be that prevention is better than cure i.e. use higher bit converters. @gzpiano's posted data was quantised to 3-digit decimal but came from a system that will soon be doing 24 bits. OTOH my own plans currently involve a 12-bit converter so I need to work out if that's enough or if I need to switch it up.


RIP

JayKominek You'll have plenty of clock cycles for any integer algorithm you could want, but with only M0 cores, I'd expect single precision floating point algorithms to be prohibitive. I think something like an RC filter at 20kHz might be the limit.

Well, unless we prove it otherwise by a big success, the RP2040 is just a test platform for a different ADC, namely one with only 12 bits (less than 9 ENOB) and higher frequency (up to 500kHz), the exact opposite of what @gzpiano is doing (IIRC he uses 24 bits and 8kHz, but check his videos for an authoritative answer).

As such the cost of fully fledged floating point live data processing on the RP2040 is irrelevant. That said, I grew up writing primitive numerical algorithms on a 6502 using just individual bytes. And later watched in awe FRACT386 (later still renamed FRACTINT). If needs be, we can experiment with numerical algorithms with bytes again, so I'll feel younger 🙂 -- the main limitation if one needs speed is that it'd be easier to use fixed point position, but I am wondering why I'm even getting there besides nostalgia, since I just said we won't do that "in production"…

Sorry for the short detour, let's go back to the good discussion @xooorx and @luns are having.


« Previous Page Next Page »