Optimizing Onset Detection for Cymbals?

So working on another hardware idea where I want to mount a contact mic on a cymbal (underneath, in the “bell” area) and use that to do onset detection, classification, etc… Basically a cymbal version of the stuff I’ve been doing with a custom sensor in SP-Tools.

I’ve experimented with a similar idea over the years and got some decent results with a hi-hat many years ago, using some HIRT to do mic correction to improve the overall sound of the hi-hat.

I’ve done the same thing now, and I have to say the sound quality is… aggressively passable on the bell. Like with the hi-hat, not going to forgo an air mic, but it’s almost usable.

BUT

The main reason I’m making this post is that I’m finding it quite tricky to optimize the onset detection for a cymbal. Even with the direct audio from a contact mic the “roar” of the ride is so much that it’s tricky to pull independent onsets out of.

I’ve gotten the best results so far using mic correction first, to apply a quite aggressive filter, but I’d like to learn/figure out some ‘best practices’ to try and do it without that. Or rather, have something that’s a bit more generalizable than making a mic correction for every cymbal, and every contact mic placement, etc…

This is the best I’ve gotten:

(you can hear the raw contact mic audio first, then the reference (a C214), then the corrected audio)

Here’s the test patch and audio too if someone wants to take a look.
contactmic_test.zip (3.6 MB)

I’ve massaged the floor some, but again, that feels very setup/cymbal-specific. I feel like there’s likely some highpass and envelope speed directions that could improve things, but I have a hard time optimizing it (this specific recipe there of up/down speeds is a @tremblap special from a few years ago!).

Hiya,

So the tl;dr is that because the amplitude envelope doesn’t show very stark changes for these cymbal onsets, it’s tricky trying to ‘tune’ the detector in a reliable way?

My gut feeling is that if the cue isn’t in the envelope then trying a different ‘feature’ would be the thing, but of course you probably want something time-domain to limit latency. Somewhere I think I have a paper with a rough and ready time-domain brightness estimator. When I have a moment, I’ll try and implement and see how it fares for the audio you posted.

1 Like

Yeah that’s basically it. My tendency is to try and force an amplitude thing to be the case but it’s possible that it won’t be as consistent with more decay-oriented instruments.

Ideally yeah, though if it’s not possible, accuracy is better than erratic but low-latency onsets.

The idea of a time-domain brightness estimator is interesting. I’ve not messed around with anything like that, so no clue what that entails. So if/when you have time, that’d be amazing!

Playing around with it, as yet unconvinced (the time domain brightness thing)

However, FWIW, – on your original patch I don’t think the dB-ish output of ampfeature is your friend here because it essentially dampens the attacks and makes tuning more difficult. In your patch I’ve found it easier to tame by sticking a db2a~ after fluid.ampfeature~ (and then twiddling knobs).

Meanwhile, a question: what are your hopes and dreams for the fast rolls at the end of the recording? You want to be able to pick up all those strikes reliably?

1 Like

Oh, and try putting the hpf up to 5k

1 Like

Ah bummer. I love the idea of fixing problems by throwing new technical things at it (things are rarely so easy sadly, lol).

Interesting. I hadn’t thought of trying that. It does seem to make the differential much more pronounced. I even dug out the old Max version of the algorithm to see if it would be improved by removing the atodb~ before the envelope followers but didn’t get too much joy.

Here it is for reference:


----------begin_max5_patcher----------
4062.3oc6csziihjD9bU+JP9vntkpt17cB6L8pdztG1CyJMG1ayrpD1F6hYv
fW.Wc26nt+su4KbAX.mXL1T0zkT4GIObjeYjQDY7H4Ot8lYyS9TP1Lm+pyu3
byM+ws2bipIYC2X99My13+oEQ9YpSaVbvGSl+aytSen7fOkqZdqi5TBW7iQq
SRCyebSwor0OewigwqeHMXQt9WBBbY2CtyAAHx2f.p5an6AN+GyUEuaSxt7n
fb0uJzzpto7OuMPeilkEtN1OZ19KKbohZDT363dyd9dEFW+VoHqfTSO0zUuY
1pvnfmBRyBShKc12Lye61RMeSoKQhO+Vh5F4d29lBi0Mw12TZvSgEWOZeq9o
BvIWfL6RU8oYehQl87sIYYPZ7tPEona7K2VPRJ.O1eSP1V+E5KVNzUb3mgaJ
Pg1Ptq5MLVg5dfR3sXTecTxheOPgefhFS1FDGFuMMHKHN2O2P86O7xfU96hx
eXURbdV3+SQCPwcsoiuxPiMdPYuP0A9wzPwvYworNMbYRrjHpLVHat3mSvLo
Xdju9bmQcFw9aa3hErFBfokClI5j6xl6mJGplGETdrZVdRRT0Cs+5hBVkaN7
1v33ZnXdx11OXZ35G63ZmmHN3ltt2pij8vtX8QePvUj+Pl+SUQ6b+nHyT2p2
9O4GGtwOOHOTODf.6OXPruni9X1hzjnnJ8W8QdpgirTvkuH3igKyeT8CUlYP
b5gaKXhlseTdY35fr7psk6uNqZKY4eVC5kZZ2byr3GxC1rMRzKpdBRARY4YO
l7wLyIVvnUF.dV9W4Y0kkCVo8tjGVUlXtiQ7ToC1jzPBWyACkuo+RYYgsKOz
JYhGHWbV0aaIQiEs+kaus3C2c9gkTAEGXIzPAJnApjXwgV.MntflY2I9uMfg
1JvfNi.ypnDw89H8aLTIpFQUx1zfvA86UIohItUTxzezXte75VQDWTU5LUL6
IWLaSO8u77nQkWxJHivT7HLl60ExfSBHKagP21WO1rKHTO8hnsO.C1+VGSv.
sHVws7uVp.iLX163paaC2zwYBlUccOF9r0ywzIROWbimKrn8HySfpdNxqq4I
m0YD7WNBQnXjRHBjecEhPeAI2k.zPF35BY3IAjMemvb83iwkgzKDipWDLo30
S0fuNAFr6j.X5vdvnD+kptvQXzzvkA0ntC0L4tQMxkwJYkD6JJqZe4vsoJSa
jHVuNXNsmBzaZs4csrh6TxEjSlaa8ErxDrzCFM8S1f6BTKoKbc0kMdATXNL3
m6pzmhQSE3m9mK3GoUUyPSD3m7mJ32CngeJYZ.+LuWLv+hjMaBhyaTk36vfg
MrncwKF6oFPz5JOoE2vPyrC7FMcjchSjyCNoWn1fvI7jFmnmEbh.PCFmHSZb
hcdvILcv3DcRiS7ghSpIbDFav3D6ZiS14uIiQ5FW8OH+MwNhm1dG9h4wowTG
FWaRGl.GJOxgJIdMoCq.m3CV1LE9ZVGlAmH5bNXP3zqZcXE3DlOXbh+ZVGVA
NoC3zfzgAdQnCqvSGDuyfNL3jQGlcQMgAJo+9BD0DzzHzqVANXWRIFiKA3Pd
4.NPyZv8tTbN3WPbNLSrHuXLNSinD0kZo3jvr.mUQIIoCaIVLECGGoinI6zU
Ow8lxpweJIZ2l.mkgqVEjJNoZHS+UqqkhYvMHX.504Sa6eF35ybc0ImDev1+
PeU6iQCNw.C1WrT5q40mUfSCe89T1q40mUfS7guNV2WyqOyfSbvf8EKcRq.b
ntOxj3NFw3jSGllzQ.YnNiTK8tPH9.PI3j1YjnyCLYjgODXZR6KR34Al3jAC
SS5IcCUxDqj.bn2.PI5KCGrYxkE2yPRIC4s3fMcf2lXYiM3L1wmNQGqibd7c
CKsaPZ.iPbKUdLiXMCQOIkVWHrLKJbYvWcvNXW74.UwZ2QwGaPkbRtG.eQAU
DBPUuLHfEqyaDCvBAfwFYcmvHqedxx4e0NVQimQ0UoxXBXrqcQAJNuvM617U
mZzRGSS0Npy0crwF7rqr.tsNOFtUddVgKPi2zwiMt.aGWpSnOWm8UgfVq291
p49ZWdS0deK0ee60f+wqC+1pE+J0iuE0jes5x2inUwvzNRUWXCXJs5PVyklu
EkmuMkn+QKSeKKU+NJWe6JY+iT19Gsz8OZ46ejR3+3kw+QKkeKJmeaJo+9TV
+cTZ+Gs796tD+6tL+6tT+6rb+aqj+atr+aoz+sp7+sbK.n4sAf5BZpKF+fie
zkEWUltPtWdPZvRG+cKCSbDBeqepQgwAKR1EmefvpVVDkINyf6wbfmXwybOl
KmdmiI+vv0ls04JppKr2a1gWYC1HTQWXU8giMfpwwv3gBiHcgAytWfbZ2XML
jiO4QNswENK1kmrZ0PgOH2qD9wGN9Qm73GI+QmjTgwANxp+LH8iIohVdTnHn
lQamDfhc09REhkHJTGGigAonqNjdfwtUQzbm4NGvI13NmhxjIWv8TWWrKiho
LBghghUu60j4ucmPIcTmnMV3QcVznSRfUXpnvtokNqRC9u6BhW7YK.YjY2iR
vyQ.d.BBScwdtDrqbo71ByviAycirSdVVs9bgQOhEM47As3.hyGDllKLVMKX
u3.mOHLgLIJY8mKKsvddcnK6dDxiwoHOjQAOlgOWiBKCWHsXyO8ycNd.4S8w
iE9YK7WVwyyslDZ5.DKySOJ.ivDWFF4BQzVcU0ofrMrZ5NCSQGdaXDQU0ul8
XlNoX2+5E.ivciQ005Un6tKKDCiWF7oKEaqs.rY594Fg6FacOYrsSaH2CvWB
NXcW1dVXO38tUWuj0ncGlXUIoLZP.YGP4wWYnULrU8rhzpyir9VEDIOutA6r
jcoKJXmJ3ZbNDpDpByCi26Tpe4YSjZ3jWHzHlVDeROWFhv.DOBf.ID0FnDfC
Q.tqqXfB6hTMg3DLA555xQTNSHqVNdcRLXmbOm1idNjZQOW9GC5RwhdGV0yk
sf8.tDfnQMVPf.LFCnHDmS4WkNtbTDZ6PN50zPNoOC47i2y06OXlWtB8GzYt
+7hYjrkNSGSdguV548QrkTQlS2TXoCVNXHyjNqd4CZm1+feddZnXEOZsPMEI
nSxgwqiRl6GUyyts4S4aOrCLxAtyrb6k6R035wBSNVm8bJe734Mz.30dYv.t
5g6MKOIyey1riFHbhN3X5sqPNenkHjsajLPuqMDsNH9qNenf0wgBQ1E+WlmI
ofF8.i2NB8s3+9b7eWls8dwXYKw.lqcuq1ckd5D4hVO879VHf+VHf+VHfe4E
B3kA0R9iCxdte3eI3iUxJV92rwqPbsSf0ICMy32WLs2NFps4482oQrl5esHl
wB+fn2v1l8OEiXIoe1QOc9MBFq298+Z5uF+yxR1cu8TugPLdnUbOeOTeJx+C
iWjFH8nhy6UFX+W1eIOeJqbdi9t67CuWXg628cNKdTlsvuILF9Vm2Ktv29Gp
SN2bZhVzWc9WjuEDkE3T5t72b.u0o9UX9v6bdydR5skuI+Zt7UAhCEmbwcR8
a+8yt9NQOL1A1CtRzy9pbziHDraWUd8wNQ2oOfGQatFlaI50kuGO4Xybw7YH
qOq.8nK.cDVhbOnOlEKPthF0kg4RVf4qq59f6J8RUmBbVWtZW0qSVTxGcBhe
JHRXaU4ynsjVn4MXds+y8v5EtISag54qfk6aWzYW6JXZkvjqAiHP8B5OGHB4
piHuQpi1weo+17.YhDjrw4m+Qm+sP217H+O+1isge3pDv4p29tg5u0ih5prc
KnVV490GijqUSJ+OOww+ojPALE4KN6kN9449K98rSkQBq2WIY5bd2i0Tp.YY
s5hu5fT1hG2DlK.Iw5kVWcmhoWXhYKYBW54YwogInKySFoCBPYG9xgqejG0b
DIsbm1xJuzTIN4JlTm2HS7ImjTGewBqBy2Il0KrCWxSCu+sUlmeX7HGYVmdS
gsxP0+ZDSmy9blNMG0tw3z32lzU3r+7rjH4yoqV1Oh5yTTSULg0F2xFfXKz0
2hfFxhjlexkol4ZdEOfMQHvUuKaRtCw7JgV9jmBb9G+8SlUPO5C8zyhvCfU3
p6f9cwakRgVUIUUOAIJZHgrOBGxbPYHg3PGXiiFgCzUeWxoqGchOlFj83Wcf
.GH8bTTuTSoRiUIl9HFUDHv6ZW7o0ywrtpfbl01WLDPA2tPLPaVgzfb1QwPi
i9jpTyK5TXTuRU3974UlI0Ch+jT7TfxsHM+OdT6nG8YbY4+a8Ql0ovmRuPQN
W6nd+z0xLlVO.njEbuyGzC.BEiNenXLASc9P4QDYLN.migEihJBXbezihqXK
XI+BAaHAgdYsYL5LN1giQlc.CrdOhY.FRLgUCJrB+rrQgfz0JOdre1B6c11o
zd9Y48Atg9Y7sI26VBkOvstRxqpecaymy0bpamix8kJb4VREnCR1vYpBKwdF
vwizPsSZfwgznVRZJCvbPi0fGtWjAbrHCjsbx3wjJf1xt.Fy4S5gaqghl0zN
rD3r7CcrvkaSBiyMxrjOY5j96G4cuKBgXhuKW.hK8fVGQ3AaC7.uFvCCZ1tW
E1YAboDhGBppBCnqJNIsd.nYiegB1+sQD.shI+fnZ1CK4pAKDlh+fH58TAVB
nd5+3bQWl21wFQ..ZiHOut.fQaBlIo4bg2iY.l7pntTOrxMJThDpZ3XiDTYq
9SBbDEHRAVRE7KtAFVSZGld9isAF1SZ.u1oMz3PaVNCzcL4prkoZDoAhsxh4
tWZ1G6IM1kl6wZRi0AiM4JSZtWZQUVSZJAGvlIM50kzfcfZ3wgzrUCHmdwmF
XKowfWbdMde30llCnX5EWjKqOKBdzzIYqGAZXVaMSYQ5sMI0ySKtrHfgHB.g
Ua0JXwBkZ9XWTH25NK+hOGxVmQT3EvwgJrUFyHRCXaUOfGyUgfISBp.0GF1w
xqgXX+Lf+b3BAWBW4.ErPtAxiwvfhUEabtvAGYr571tvJ5HxGfXSB+1pHC3U
2K1HRezYMZfQuTlLZTApOXwnMhX6jDx34isQoiA8rjiuADXh2y.d8aLqyvbp
pvwVhy49P9tw+SrJkTXQc41LI6uXQPbdETzUBRtXOgolxOwAdtxsUl55RpTb
JPi1l6Jz.QqbtxnUqN6GBik0qcvw2aSJUzzxmBmBhroB7b1FQOKrrwrMMrUA
bpk5ScCOU.F49ZHRU+MXAmCQ8IAuDEdoH8MAYY9qCrk3mudUXTz9tPS0Vue7
ZSAPyqUYt96xSVm5uLzjsUUNXEXA4AfdJVErgUQ9IQSvCXZLWIbOqFS7G+tF
+TyWJp3RESoECG203mN3R2llrMIceoueO1qR8DaRdgY66uMuakbl4hOblZ+4
HpWo.8faVQuDAaLPIUjHF5vdWBN4b+s1RvkSlEgfxexOOw4mj0N+ryAMZtGE
2fisazXnqVqY8lpW8ir6yTemmQK1W8pQve8c3BIQTaGsn1NYwg6fEsuyUTeG
qPAEs8DJ31ub6+G.UKJY5
-----------end_max5_patcher-----------

Even spikier!

Of course I am!

It actually does a decent job of it but only if I use the mic correction and your suggestions.

Here are my settings:

I suspect that in the earlier stage, the logarithmic representation is helpful (e.g. for setting the noise floor, and for the way it will affect the envelope followers)* but when it comes to thresholding – particularly when you’re interested in sharp events like this – it’s more of a hindrance.

* in fact, subtracting the two envelopes in the log domain means that it functions as a division in the linear domain, which – coincidentally – is the operation at the heart of this time domain brightness thing I was looking at.

1 Like

Yeah that makes sense, and seems to line up with the reality of what’s happening. The best results I’m getting are from the fluid.ampfeature~ version.

Ok, so spent some more time playing with this today, and found some settings that capture every single hit*:

*when using the mic correction.

It actually does fairly well on the raw audio too, perhaps due to the even more extreme highpass at the start.

I kept cranking that (the highpass) and had it up to 15k at some point and it was working quite well. That felt a bit absurd so I left it down at a much more reasonable, “like grandma’ would have liked it”, 8k highpass.

I then tried to make a more generic/generalizable eq curve for the raw contact mic to try and get good results, and something course like this seems to do a decent enough job:

I imagine the eq issue is two-fold. First being making sure there’s enough bite from the tip of the stick to capture an amplitude change, and the other being the “roar” that masks out a lot of information in the mids/lowmids. I suspect this will be cymbal-specific in terms of absolute efficiency but it would be good to try to work out a general ‘good enough’ contour.

I did record a few more cymbals this way for test audio so will try running those through these settings and seeing what’s what.

edit:
The cascade~ contour seems to work alright on the other cymbals I recorded.

Circling back to this. Do you think this is something that would also generalize out to other kinds of material? I had a quick (varied but not super thorough) test on other material and didn’t come across much where the differential looked ‘improved’ in the same way it does for the cymbal stuff. Is this just an odd edge case of something being quite bright and not having a sharp transient? (was wondering if I should bake this in as an attribute in my onset detection)

Lastly, is there anytihng else from the paper that may be of interest (or what’s the paper?). If you did put it together in a patch and don’t mind sharing, would be cool to experiment with.

1 Like

My granny also liked her high pass filters around 8k. Once it’s a detection signal, you can just go with what works best. Doesn’t really matter too much if it seems silly (at 15k I can well imagine that almost all of the ring has been attenuated, but the click of the strike will pass through more).

Rides have a characteristic pronounced resonance, and you can really hear that build up at the end of your clip: notching that out seems like a sound plan (and simple enough to do by ear for each cymbal, presumably).

I’d sort of expect it to work for things where you have long decays, especially quite noisy ones. Something like a tight snare, probably not so much. But a gong?

Two papers, second one has some more implementation details, and I followed those.

https://mds.marshall.edu/cgi/viewcontent.cgi?article=1017&context=wdcs_faculty

It’s very simple indeed. The only thing to play with is the type / friskiness of the envelope followers.


----------begin_max5_patcher----------
468.3ocyTtsajBCCF9Z3oHJWSmMIbXZ2WkpUqRgnYSEjfBgVVU09ruINvzNs
zNy.yJ0ahjMN76OaG+TbD9N8fnCi9I5VTTzSwQQfKuinQ6HbCenrl2AggUhG
02cONI7IqXvBtqD0V9KStU8M5dasvB2gN5skaK+iTs62FQoMnYZwFVdBhRK1
PRPYL+Iych903cB+F6eaEgKf6j6T7Z79.jUf9tb5pL5azWp1Ku22yww9ij0Q
I+AgguS7BhRHHSS2h4Mm3IkRJVEvoo+uA9GKukdCEPLaKXtbFYyxH6aTSkVj
s4B1TubSwvsOebnrwgTOGojoyEQCkjMKNjQmk5lFgJzHlBTppDCKk4PxMOzj
iN0xRS+DnOfo74aQmKSvOGWKUueELjfd+GBZmt2TNUzm13gdMGqDcVohakZ0
aBxukvGzrEySUooexWqD6RnD8TUhtRkfYyiK0g4SirpUKU1wNFkQ2r0M3r8F
XEv1L+fi230WKlJgAl9VWYgcB4JLYt5NvoUWxNi5RV9diOVW93KBdaqamb2n
dPd5djeuFB+5DvTpBl4foQ7fbJdF3gabOwst228FfM7PQXSDtQ6DV0KG01Ug
bRBKPT7FQWKOTLf8LwOG+OPFbgwe
-----------end_max5_patcher-----------
1 Like

Yeah that makes sense. Will play with it a bit more.

Interesting. None of the stuff I’ve been testing with has that kind of extreme decay, but I’ll do some testing with that. I think I will add it as an attribute as it’s good for this cymbal stuff, if nothing else.

Awesome, super interesting (same with the patch).

And for reference here’s some of the results in context. Demoing the mic correction (with very loose onset detection settings, so it doesn’t freak out with the bell hits on the classifier bits at the end):

In putting together the bits for this video I realized I’ve got to also account for bell and shoulder hits when tweaking the fine onset detection. If I leave it like the settings above it catches every hit, but then bounces around like mad with the bell hits. So have to fine tune that a bit more methinks.

Either way, pretty chuffed with the results so far.

1 Like

Boring semantic side question, but what would you call this change (as in, I’m not entirely sure what to name the attribute to control this).

So it’s specifically the unit/scaling of the amplitude differential before thresholding yes? Something like @differentialscaling doesn’t really roll off the tongue (or fingertips), but it’s kind of in the ballpark I guess. I guess a simpler @differential then having options for linear and logarithmic, or maybe keeping it 'CoMa like and using the obtuse @power with 1 being the default (ala fluid.spectralshape~).

Ah, the hardest problem in computer science (naming stuff).

My preference is for whatever combination of brief and descriptive you can muster. I think ‘differential’ possibly relies on someone knowing what’s going on inside a bit too much? @envelope? @detector? (with lin / log options).

Hah, real bastard naming things!

Hmm, that’s pretty good. Something like @envelope did cross my mind too, but I think it would get to messy as that’s a more generic “namespace” that I likely use elsewhere (or would at some point).

Is “log” descriptive enough for dB?

And I take it you’re not a fan of

?

Works for me. You could just use dB instead though.

IIRC, in spectralshape that’s just an indication of whether to use the power spectrum or magnitude spectrum (i.e. X2 or abs(X)), so doesn’t really apply here

1 Like