Looking for "better" tap tempo abstraction
I’m looking for a tap tempo algorithm in Max that does better time detection than the examples I’ve found. In particular, I’m looking for something that can both lock in to a tempo quickly but yet be able to adjust as I tap without taking too long to match my new tempo but not be too jumpy. I’ve played around with the examples, changing the number of taps being averaged, etc, but I can’t get it work nearly as well as the tap tempo detection that I have on either my Korg Oasys or on my Boss Digital Space Echo (which seems to work even better than the Oasys). On these, I can let them free-run but if I start tapping, they very quickly adjust to my new tempo with any sudden changes. I suspect they’re using some non-linear weighted system for adjusting the tempo based on "recent" taps.
Anyone know of a more sophisticated tap tempo system for Max?
"more sophisticated" than what? You don’t mention the method you’re using; I would suggest [timer] followed by some [zl] objects for averaging, like this:
----------begin_max5_patcher---------- 743.3ocyXtrbaCBEFdsyL4cfp0tNbQWvcUeJ5lNY5fkINzXgzHgacRl9tWIH xwwQRFYKYrWXFN.he93bNBzq2dyDuEoa4EdfuA9IXxjWKsLQaqxxjZCS7RXa iWyJzczKgWTvVw8l9ViJ9VktAzNSOjJURVBWa9G77kLIaWixMIB4ZtR+zv6O jBwK5gfPyf606zMp5tipMarodNiaDumG3951DK0ya5he+Uh+toMioheTHW8q bdrxLH774kSD.YJH3YAkUnyff60i4e2dSUYYwTqgyhMJUpr40JpuqoEL4plW W3HKVWXey5BV++Yrtj7+VNuedOOgqxSAHHD7cVrR7GNvodAcPLa7DvXesCAN RWabPVFK9IfnhYWewKnNozbpFKzvphP5Hxn0BI+DnCoezA2Ncl1JgHGmPDBo pvOb.HTbZRBWp9LhJJ8i3KX4m.lP8CSvlv.tKLfB0wQT8+Q3wDCJVFXQVhin .paJnW4jH5fgg1hWtCPFrjI39mLQTtyzXzB0hzIFeEhIAL5rvSqGMgF4R7zL al2IahLtNZpDhLGSYTbcdYMnXSxkv+4TR2144blaBoHZ+HiazY5.0AjVkmtI 6ZESgVfInIaLY.vzE5TtQVr6izYrG2C49k6.gvxeybYRjGVmxZIKaDxBNQ0b JBMhQIJQBO2kAHFF0dTB0BNEr+Y2FGNUvWWdaSWBJcLWqbJ33XhpoT.bDozS 7mOADA6Gh767LMSapnQj4ebjEnC8BiZEYlGr9tOG9IYzOT8kh9HHKR2jGWq3 5O3A.9tDWxKTBISIJSW+duvGzqGEKWxke.eIhkYokK22TRW6uVKtp74GWbjd KNDDo+zM9jpBBjtq1fH6pzFVxTzoHayqj8Qg6pMHxFamqPjSbEPVItpKa6.w Y09MxMwPGhjlE2795KNLw2HazVnax8XiznNQZg1HM2DlFXkzhtheahN4M5ZV bNvgypDbGFMegDmUuXH3rkVkgxh+CP4grOG -----------end_max5_patcher-----------
The minute fluctuations in timings between physical taps WILL create jumps, unless you use some heavy-handed interpolation – which will introduce a delay. Maybe add a [line] at the output?
EDIT: added a synced beat generator
I had looked at (http://www.cycling74.com/forums/topic.php?id=23813) and also at jb.taptempo (http://www.greyfade.com/joe/maxmsp.html)
They both felt like "engineering" / "mechanical" solutions but neither of them "felt" right, at least compared to the way tap tempo works on the instruments and devices I mentioned, both of which I’ve used in live situations with a band and was able to easily sync my sequenced arpegggiators to the drummer. There were no noticeable jumps nor was there any significant delay.
I’ve done a little bit of reading since posting the question and as far as I can tell, it’s not sufficient to just take the moving average of some number of taps. The articles I’ve seen seem to have some non-linear (weighted) bias as well as some beat prediction capabilities.
To paraphrase the judge, this is one of those things that I know what feels right but I don’t know why.
I’ll take a look at your patch when I’m in front of my computer later today.
then perhaps my ‘solution’ is a little simplistic for your needs – no weighted bias or predictive capabilities, just some averaging, but with the [zl] and [line] objects it works for me.
sorry to disappoint :(
if you keep this thread live over the next week or so, I have no doubt that a maths guru will jump in with some [expr] or other function that does what you need……
-average the first N timings
-accept subsequent timings only within that measurement
-set new tempo only after N measurements are completed
First of all, you’re not disappointing, I truly appreciate getting responses — sometimes such dialogs help guide towards solutions.
Nor am I suggesting that such things as "weighted bias" and/or "predictive capabilities" ARE the solution, it’s just that as I look around, I’m seeing references to such things.
Now, I just had a chance to play with your patch and as it turns out, your timer triggering that metro actually seems to work quite well EXCEPT that as I manually tap, I think it’s generating both the automatic beat as well as my tap, so I get two taps close together.
(By the way, I’m less interested in actually seeing the BPM value, than just getting a smooth beat that’s responsive to manual tapping)
Again, ah yes
I overlooked that bang duplication;
maybe a simple [onebang] with a small delayed reset, c. 5-20ms, off the top of my head?
I have found success with the [zl stream] object with the [mean] object underneath it. Using an argument of 3 or 4 is pretty smooth comparatively.
How does this compare to the tap tempo in the sync~ object, does anyone know? Can these solutions be used to affect max’s global tempo setting?
Hey, it’s been a while but I’m going to stick my nose in here. As a DJ, I am looking for a similar solution. Basically, I am looking for a super intuitive timing belt type device that I can use to sync Ableton Live to live performances and cd’s with the flexibility to allow for drift.
Ultimately the goal, I just sit and tap quarter notes into the thing and it does whatever necessary to stay with me. However, if I stop tapping to sip on a martini, it keeps going. If I feel the groove lock, and I want to mess with some other effects, I can stop tapping, but if it starts to fall out of sync, I can just start tapping away and it adjusts to match.
My first attempt (involving averages and differences…etc) only led to ableton oscillating around the tempo of the song and rapidly going buck wild…one tap it’s going 32 bpm, next tap 500 bpm. From there it’s just a crap shoot and sonic destruction. I see it only as a great way to end a set…
But I digress. I"m seeing a few major components to such a system:
- detection of good vs mistaken taps. If mistakes get filtered out (like 1/2 way between a beat) then junky data won’t corrupt your tempo.
- some way to detect consistent differences in timing which don’t mean a change in tempo (constantly 10 ms behind the beat doesn’t mean slower tempo, it just means slow down and speed back up when you’ve added 10 ms delay.
- What to do when you stop tapping…if the user stops tapping when it feels right, there might have to be a final adjustment to keep the system in the groove based on all of the previous data.
- some system to keep it from drifting to the wrong downbeat while trying to correct.
- of course, how do you recognize an accel. or rit. and work that in? Also, what about a sudden a-tempo which is bound to happen as well.
DHJDHJDHJ, I think that is closer to the core of what you are asking, and I have been asking that for quite some time now. I wish I had more facility to answer these questions, and unfortunately due to my current work, I haven’t been able to devote much time to the problem, but maybe collaboratively, we Max/MSPer’s could come up with a solution. Any thoughts?
It might be an idea to limit the range of possible right answers to something within 10bpm of the current tempo or manually enter an initial idea for tempo. That way you could stop your patch outputting stupid numbers like 500bpm or 32bpm so limit it to your normal working tempo range which for DJ music tends to be an extremely fine range with many DJ’s never going much more than 5BPM either way – a tempo range of 118 to 144 would probably cover almost all techno, house, club DJ’s and it would be easy to have HipHop and D’nB modes for those working outside that tempo range.
Final adjustment could be done with a nudge function – basically a line to the transport object that speeds up/slows down the tempo and the reverts to the original tempo when you let go of the button – so a 1 from the button starts the tempo ramp and a 0 from the button stops the ramp and resets the original tempo.
Instead of or complimentary to your use of a tap tempo solution you could look into bonk~ and MIDI Clock.
I haven’t built a tap tempo (outside of the one Brendan showed you) but if I was going to this is where I would start – weighting, analysis, MIDI syncing and fine control.
----------begin_max5_patcher---------- 1793.3oc2assjahCD8Y6uBEprUkI6jIRhKF121Z+E12RRMEFK6gDLPAxSlro x+9htfML.xBaLFm4A7ftQ2mt0QsZD+b9LikIuPxM.+E3SfYy947Yy3EwJXl7 9YFa8eIHxOm2LifjsaIwTi6E0QIuP4kGmPI.5SDPQCR8yByShA46Vl5SCdhj U17nvXRPxtXdeLkEtNIllG9eDVYH7CPYw7tFFu4wLR.UHh1HXQ0.rsM6mE7q VtO.AeQ1mvUbgIY4W+foS4CMd21v3HBkq.nJOzX+s7GpwemE5GUo4I6nksGx J7WymytbulXTL46ERPCHhBPO.VWVr3YP+QJQnaFqiR7Kv0x+YuNoO7XJPDjs G6GyEbrB1A7XOHvC9Dfmtbgn9oF8VmwVbWBSG9Oha5TmstZtDcoyAQgAe6yw 8WuQN15q2lSsoBEd3q1RxyKTR3CcNi3TlCX4BOvM35oDVvCBrfFP2g+nf9Li oLgImfOgIR3SXInGcTp7nI2bgs4.RVVR1In3lB+eWth6fTp3vqlhWPrWLHGe Afk9waNI9eOXE6u.L5BFvKtZ7+cvI7dfBpfydMQOIc4C1Jvj1CY.OBDBcfIj WRy.ucMB7Qv6d6Z76w2A9S.ZPILKcZDbGHrkRuF6qFB0EqA5NPN0OiB1RnYI .zmiw0KA+4Xy6.emo4r.T2Bx+Qbv.EPpb4WwUDRY.o3oWzGTx1zDiSMLbDjq u1Ji8.e8h8X4NJ8vxnMlrTmkssPKw1UVUQrbJ6Zqpo5kSOe2+yUYP1P8UF3E VYnIa1DQ5TYBioJ0EKgimz+yxp7Za5Bx6BqKcvby4dzzb0inaEprzyzRYfNH 2qFW8YZekrp5Yes9cx9J0b8rulWM66HEHaIYkxPRP3oVfroUxA1EHfVup4.y 0TE1zN2mYe8PpJLjLIfHQjhgILh7LIKmsk0CsdlgeZZkhmUoKLX7qI7Ax998 EEFKJBsunLxygk82STXgwYdYk6CGwBKB+RDKlHWH77.ThIEFxMQIAeivgFXY gqHq62njjRhOzCdKpcodKCiSyH4Ewc4SkJQ0mr+tH5isa1qW+Z+.RmctU62L iMYgqRhYBQsdxJt7wwBIPjsvpxMuEw9oszYZRRzR+LlIYYDolotXZheb3VeJ gFJjGLbe+B2llEJBvdeYjX+hw3o7frjnnZCknlmaolUEdCAjuGth9DerNfV0 RhcU+rpSfqUtJ9r9vooXtaoSc31hQlMqCVuF+WJqwAVuJEQ7fgsGwciH3vUU l1HFUy.zEA4rRRR4bwSDuqQbVm77Mer.oJ9SownZ.DGyDn.ME3ns0QQSTmnI 9DQSz3flT.Dr7nPYe8paauRhkiLgxLPcTHEdq5fRA3QBRw8CR2uSmaNHcSwB G.rRLkAnC.XJcSs7NJXtXvmxORfYkznpSjmmBVV6Ut4zHkpMvRmaW5yk.jZz jOK+9A.UKS.qXQolu71Fnp8sKC5RvGFKXEu.VAVati5NymvzDVYuzT+MjVwU jZFzyw2TlVBwdiLwrY7HWEf3Ma.SqHQ9+nH.a3w8NOe7DIdW0NlGyozcRCmb oouK4zcX4k42n7ZWfR2qPC6VsqTS4KEQbLLRB9FP75PFIRvhMJmo2NNGh0pE uf7iG2i8jNrGwvZnmJ6UY2c1VcqxlZQ3+pWGUG9QFi5zplzPJhq.Zq2zJ7.N s5e8SmfHRYHA5hHnADQ9GFQSaXxgTvwdkzcjMKtxvpucvJOYWVPITHskf5p0 JRNMLdeBI+zgXIeUCeJb0p5I.TjOqUoIE6uUJefunk0suhMWbP5H2NMZ3UWt 0AucmdvsVtIKlVvsths0zBtstQ8tstM8tstM8twnd.2SGwdglRMFOo7Rv5tT YKlkqp2smljISqU3Yo+WawFMsDas4RNA3F6Xwxsho7TXh7ZdGVb5dwlV6u6R 5acQ0Vyoj1pKyUKvxUkAXglSkZw48pJ2nKr20kRtczTtMmThs1w36LoDaWcE 6gbYYYgkm0Hib+mIqdr3wPBnO5SoYgK2QE6Qu1AgpsCqyk5D9nnpic3h1Dkr zORdZt1OFFyOfBSriCnk3i2P9Iuo97l6N0NMfu4irC3y9WnvQNMr8GTLsa+P rzVpx+86jhZITbs9TDbFbWC9SodB6Dfxqo4jPSy.JqQK20B20V.rIuV6bZML T5JSHrNxj8nJSt5JRnQSjL0xz4LpvjYcHPgLglTlNyd5MYC4aG.4I9z.vNsb m7.o4Zs+tyEb0Ydw3ZueEyvv3CZ5I1G1Br36BDINOJUuC4VCbcOev8UBYGA4 YNpdtHScPW33RNqESHZ5ISdiqoySG2I2I2ZXH29ASRhPLxl8ik7yalc2YJrN ZZRwimI0RWFB3zhgvaTEIsb7wipHoiuz3FhqNKadNjCE27q4+OjOtT9D -----------end_max5_patcher-----------
I thought a bit about the problem, and I cooked up this idea. Note the subpatcher. It doesn’t measure tempo. Instead, it takes two out of sync metro objects and syncs them up. Of course they have to work at the same tempo, but this can provide final sync once the tempo tapped is established. This could aid in solving bullet 2 of my point mentioned before.
Audiolemon, that is a good point. It is important to differentiate between half note and quarter note pulses. Is dubstep 140 BPM or 70?
Another thought, which I’ll explore next time I work on this problem, is how does the function of taps affect the clock depending on how many taps have been performed? I expect my first few taps to be out of time, and wouldn’t want tap #2 to trigger a skip, but if I’ve been tapping a while, I would want to have good enough response to lead a ritard, accelerando, or even an a-tempo.
My advice would be to avoid rolling your own and instead look at some of the results from the Music information Retrieval world.
Tempo tracking is hard problem , so it’s worth looking at expert solutions. There’s always knowledge to be gained from trying to do it yourself, but for sheer efficacy…
Will try to post some links this week.
Peter, I agree. It is always easier to follow a recipe someone else has hashed out than to work it out yourself. I would take that advice if Ableton’s tap tempo function wouldn’t spin out of control so easily. At least that’s what I’ve experienced with it.
I tried combining my shifting abstraction with a kind of ZL filter presented by N00B_MEISTER earlier. It feels good. It averages to your tempo, and then will slowly shift in sync with your taps. However, on extreme jumps it will still oscillate around tempi a bit before it averages in. I think the problem involves how many beats to average in your tempo calculation. I am averaging 16 taps, which leads to a very sluggish tempo change.
My next thought is to have Max analyze the curve created by the series of taps. More on that later, time for breakfast.
I’m looking forward to these MIR sites, never knew that existed.
You might also look at a median filter. These are good for this particular type of situation because they ignore outliers.
(use zl.stream 7 -> zl.median for example)
I didn’t think of a median. I never tried that. I’ll have to check it out. Thanks man!
Just be sure to account for the difference between odd-numbered and even-numbered medians. (odd-numbered will always output a value in the input set; even numbered will output the average of the two center values)
Median filters are also really great for threshold detection tasks. Unlike averaging filters, they can jump to a new value faster.