Musical Sensor

Vibrating cantilevers has a long history of being used as sensors, but almost always in the micro-domain. The cantilever is frequently etched into silicon or other substrate. The weight of even single molecules can be measured or detected.

The idea is fairly simple. Change the distribution of weight on the cantilever, and the frequency of vibration will change.

It can even be used as a motion detector since acceleration in the same plane as the natural vibration will either start the cantilever vibrating or will change the frequency of the vibration.

A research group at the University of California, Riverside was attempting to find a cheap, easy way to detect counterfeit or adulterated medicines.

Adulterated medicines will almost always have a difference density to the “real” product. So, if a fixed volume is tested, then the weight will be different. Cantilevers based sensors can be very sensitive to such changes.

But what could be used to create the cantilevers?

The mbira is musical instrument that uses cantilevers to produce tones (similar to a music box). This became the inspiration for the paper Musical Instruments as Sensors

Of course, there is also the need to capture the frequency and compare to a standard. Since the mbira produces tones in the audible range, why not use the recording capabilities of a smartphone?

The researchers created a site which allows a user to upload recordings and have them analyzed. According to the paper, the analysis software is written (at least in part) in python.


Another writeup

Github for the Grover Lab


Spirit X3 – Separate Lexer Part II

Last time, we looked at the lexer and supporting staff. This time, we will look at the primitive parser and final usage.

The full code is in GitHub.


The tok parser is quite simple. Give it the TokenType to look for and it returns true if that is indeed the next token in the stream.

This is the beauty of the separate lexer. The lexer is responsible for the hard work of classifying the characters and splitting them up into logical chucks. Parsing can concentrate on a little higher level of syntactical analysis – how those chunks are organized.

One subtlety in tok’s code. We must be sure to consume the token (advance the iterator) if and only if we actually match.  Since we are only assuming a ForwardIterator, we can’t depend on a decrement operation in order to “unconsume”. So we, make sure the increment is only done in the true leg of the match logic.

There is a bit of a flaw in the interface of tok. Currently it makes an undocumented assumption that the iterator’s value type has a istype operation. Once Concepts are standardize (hopefully in C++2020), we would be able to document this. As it is, passing, say, a char iterator would cause a vary hard to debug instantiation error.

In parting, we define two specializations for operator>>. These will allow use to simplify the parser expression we write. If we were doing this for real, we would also specialize operator| at the very least.


There should be no surprises here. The grammar is straight-forward. Those helper specializations come in handy letting us string together token type rather than having to explicitly wrap everything into a tok().

auto vardef = tok(tokVar) >> tokIdent >> tokSemi ;

rather than

auto vardef = tok(tokVar) >> tok(tokIdent) >> tok(tokSemi);

And we’re done.

But we can do a bit better.


The current way tok()is specified, it exposes a string as its attribute. So, the syntensized attribute for, e.g. vardef would be something like array. But this is less than desirable. Normally, we would not be concerned about an attribute of say, the var keyword. If we DID want to know, we could capture the difference as seaparate rules.

There will certainly be exceptions. For instance, if we had two keywords for a type (say int, and float), we would definitely care which of these we parsed, but not want to have a separate rule for each.

The solution is to define two different parsers – one which  returns an attribute and one which exposes the attribute type used. And in v2/parser.hpp, that is what has been done.


This is the version that returns the string. It is a renamed copy of the original tok.


This is the new one that does not return an attribute. There are only two changes from the original.

The attribute is specified as unused:

using attribute_type = x3::unused_type;

and the assignment to attr has been removed.

Now the v2/main can say…

auto vardef = tok_kw(tokVar) >> tokIdent >> tok_kw(tokSemi);

And now, the synthesized attribute for vardef is a simple string.

Other Improvement

We could make other improvements.
We could get keywords to automatically use tok_kw by using two different enum classes.
We could provide a third variety that returns the TokenType as the attribute (to solve the int, float problem.
I’ll leave those as exercises for reader.