Lots of good ideas. I will play around. To provide more context:
I am recording realtime MIDI into some custom (Ruby) software. I am sticking all the recorded notes into a data structure I call Timeline, which maps timestamps to lists of MIDI events.
Because this is realtime, human input, it's messy. Notes don't land on the beat, and I also don't know how to establish a tempo without any a priori tempo information. I considered playing a metronome tick and recording against that, but I rather like the idea of just free-form improvising on my MIDI keyboard, and then trying to extract useful musical patterns (like rhythmic motifs) from the raw data. As a first step, I want to "clean up" the input and quantize it. But I can't quantize it without knowing where the beats fall, and so I need to figure out the tempo to establish the pulse.
I just want a rough, "good enough" solution. If it guesses a tempo that's off by a factor of 2, 3, 4, etc, I think it will still be useful.
If you want to know more, my project is here:
https://github.com/adamjmurray/mtk . It is not well documented yet and there are a bunch of things I want to rework (so the API will change). The realtime MIDI input currently relies on my jsound gem for JRuby (
http://rubygems.org/gems/jsound). It's also going to work in Max and Max for Live (I have big plans for enhancing Live's MIDI editing possibilities) using my "JRuby for Max" project which is close to 1.0 launch (see
http://compusition.com/web/news/2011/06/06 for a beta version of that). Oh damn, Matt, I should have got you involved in the beta. You still doing Ruby scripting in Max? I've been really bad about promoting my projects... it's more fun coding than talking about it ;)
Anyway, back to the discussion...
The paper David linked to sounds very relevant, but it merely references other papers that contain the information I am looking for. However, it led me to here
http://www.ismir.net/proceedings/index.php where I found a ton of papers on all sorts of computational music topics! I already got distracted with a bunch of other papers that sound interesting :)
Mike, thanks for taking a stab at a pseudo-algorithm. I see Matt's point, but I think I will probably get the best results by considering both inter-note onset time and note duration (i.e. long notes tend to fall on stronger beats).
As Mike mentioned in the comment: // you might need to do some fuzziness here if your time intervals are not all exactly quantized...
That's a big part of my problem since I'm using "messy" input. I am getting a handle on how to make a rough guess at tempo, and how to quantify the quality of a guessed tempo, but I'm not sure how I will improve the guess without resorting to some sort of inefficient brute force algorithm. (Perhaps I want something like Newton's method?) Hopefully some of these research papers will give me ideas.
And Tim, thanks so much for that code. I will try porting it to my project, if that's ok, and of course I will give you and the others credit. Once I know the root of the key, I suppose guessing the scale should be fairly easy using some basic statistics.
-Adam (jeez, that was a long email)