![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
scott wrote:
>> Only problem is that first I'd have to find out what the necessary API
>> calls are. This is highly likely to be quite intractibly difficult.
>
> It's not *that* hard to use the Windows wave API to repeatedly get a
> buffer full of samples,
Hey, at least he didn't say it's obviously impossible. :-)
> I thought WAV was quite easy to decode, isn't the data just stored
> byte-by-byte after some header?
Yes. But the headers tell you important stuff like sample size and samples
per second and such.
--
Darren New, San Diego CA, USA (PST)
Eiffel - The language that lets you specify exactly
that the code does what you think it does, even if
it doesn't do what you wanted.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> Now I'm wondering if I can come up with something a little more
> accurate. (Although, obviously, accuracy is ultimately determined by how
> good your coordination and sense of rhythm are!)
See attached. Press any key rhythmically to send "taps". The reset
button... uh... resets the stats.
It works by recording the amount of time between consecutive taps. As it
happens, taking the arithmetic mean of these numbers produces an
identical result to just taking the duration between first and last tap
and dividing by the number of taps. However, by storing the actual
times, I can also take the standard deviation.
(There's probably some way to compute the SD incrimentally. But, as it
happens, even after several hundred taps, there's no noticable problem
recomputing all the stats from scratch. Firefox uses about 0.5% CPU
while doing this. Which is impressive for a trivial scripting language.
I guess computers are just really, really fast these days!)
In my experiments, the error is always about +/- 4% or so. For fast
tracks there's less timing jitter, but greater timing precision is
required to get an accurate BPM reading, so the error is still about 4%.
(The "error" I'm quoting is just the size of one standard deviation.
ASSUMING A NORMAL DISTRIBUTION, this equates to 68% certainty.)
My next idea is to try generating a series of perfectly-spaced beats and
optimise for the best possible fit to all the taps...
Post a reply to this message
Attachments:
Download 'us-ascii' (4 KB)
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> Hey, at least he didn't say it's obviously impossible. :-)
No - just ludicrously difficult. ;-)
>> I thought WAV was quite easy to decode, isn't the data just stored
>> byte-by-byte after some header?
>
> Yes. But the headers tell you important stuff like sample size and
> samples per second and such.
I might be mistaken, but I think it also specifies byte-order and
whether the samples are signed or unsigned - pretty damned important
info, that! ;-)
Still, I would also guess that, say, CDex is going to write identical
WAV files for every track ripped. So I can probably just go measure how
many bytes the header is, and skip that...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Hey, at least he didn't say it's obviously impossible. :-)
>
> No - just ludicrously difficult. ;-)
Funny how it took me about 30 mins of research and coding to come up with a
working program, when previously I didn't know a single thing about it. It
didn't require any skills beyond being able to set up a struct and calling
windows API functions. In my book ludicrously difficult is when I think and
work on something for *weeks* or *months* and cannot get anywhere close to a
working program.
> Still, I would also guess that, say, CDex is going to write identical WAV
> files for every track ripped. So I can probably just go measure how many
> bytes the header is, and skip that...
IIRC that's exactly what I did at some point previously. I guessed/knew the
samples were in 16bit stereo format, so just took 4 bytes at a time from the
file and experimented with the order until the result wasn't white noise!
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> See attached. Press any key rhythmically to send "taps". The reset
> button... uh... resets the stats.
If I press buttons too fast I get a negative maximum BPM :-)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>>> Hey, at least he didn't say it's obviously impossible. :-)
>>
>> No - just ludicrously difficult. ;-)
>
> Funny how it took me about 30 mins of research and coding to come up
> with a working program, when previously I didn't know a single thing
> about it. It didn't require any skills beyond being able to set up a
> struct and calling windows API functions.
So I'm guessing you know an awful lot more about C than I do.
>> Still, I would also guess that, say, CDex is going to write identical
>> WAV files for every track ripped. So I can probably just go measure
>> how many bytes the header is, and skip that...
>
> IIRC that's exactly what I did at some point previously. I guessed/knew
> the samples were in 16bit stereo format, so just took 4 bytes at a time
> from the file and experimented with the order until the result wasn't
> white noise!
I suppose you could just open the file in a hex editor and look for the
chunk names.
Oh, wait - you'd need a hex editor to do that...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
scott wrote:
>> See attached. Press any key rhythmically to send "taps". The reset
>> button... uh... resets the stats.
>
> If I press buttons too fast I get a negative maximum BPM :-)
Really? That's impressive. You're a special guy! :-D
No, the minimum and maximum values are derived by taking the mean and
adding/subtracting the SD. If the SD is sufficiently large, it should be
possible to make the minimum value negative. (I.e., if the error ratio
is greater than 100%.) Not sure how you'd make the maximum go negative,
but it's probably possible somehow...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Funny how it took me about 30 mins of research and coding to come up with
>> a working program, when previously I didn't know a single thing about it.
>> It didn't require any skills beyond being able to set up a struct and
>> calling windows API functions.
>
> So I'm guessing you know an awful lot more about C than I do.
What's C got to do with it? You can call DLL functions from lots of
different languages. So long as your language allows you to set up a block
of data with the common data types it shouldn't be at all tricky.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
scott wrote:
>>> Funny how it took me about 30 mins of research and coding to come up
>>> with a working program, when previously I didn't know a single thing
>>> about it. It didn't require any skills beyond being able to set up a
>>> struct and calling windows API functions.
>>
>> So I'm guessing you know an awful lot more about C than I do.
>
> What's C got to do with it? You can call DLL functions from lots of
> different languages.
Sure. So long as you have the necessary magic numbers for the specific
functions you want to access, and you know how to do the pointer
manipulation to make it happen. It's not exactly trivial though.
(Unless, of course, you're working with a language which actually has
built-in support for calling DLLs. Then presumably it *is* trivial.)
> So long as your language allows you to set up a
> block of data with the common data types it shouldn't be at all tricky.
Heh, right.
I still think recording a few keypresses and doing some statistics on
them is way, way simpler.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> No, the minimum and maximum values are derived by taking the mean and
> adding/subtracting the SD. If the SD is sufficiently large, it should be
> possible to make the minimum value negative. (I.e., if the error ratio is
> greater than 100%.) Not sure how you'd make the maximum go negative, but
> it's probably possible somehow...
How are you calculating the maximum BPM? I guess you are calculating some
minimum beat time using the mean and SD and then inverting it? Maybe the
minimum beat time is negative if the SD is too big compared to the mean?
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |