7

For the purpose of controlling DIY disco lighting, I'm looking at implementing beat detection in a microcontroller with limited computing power (i.e. Arduino Uno). While detecting all beats would be a plus (for one, it would allow measuring BPM, which could be used to adjust the light to the style of music), it's not absolutely needed for this application since light setting must be typically changed at a much lower frequency than the beat. So what I'm really looking at is to detect "conspicuous" events in the music (beat, resume after blank, etc.) to synchronise light change, but without 100% reliability.

The constraints are the following:

  • Limited computing power is available. The Uno is based on a ATmega328 8-bit 16MHz MCU. If this is too constraining, I could consider moving to a Due, which is based on a AT91SAM3X8E, 32-bit 84MHz Cortex-M3 MCU.
  • Noisy sound input. Ideally, the sound would be captured with a small, cheap microphone. I'm not sure yet what sampling rate can be achieved with the Uno. In any case, I expect the signal to be fairly noisy. If that proved the be required, I could possibly consider implementing a proper sound input (e.g. with the rugged audio shield) but I'd rather avoid that if possible because of the constraint of hooking the music playing devices (there may be several) to the light control electronics.
  • Ideally, the algorithm would have a parameter to adjust sensitivity to beat event detection. That way, the sensitivity could be automatically increased to make sure events are detected even in bad conditions (low music volume, noise from conversations, etc.)

My questions are thus:

  1. What (class of) algorithm would fit appropriately this application?
  2. Is there any implementation available that could be readily integrated in a Arduino project?
abey
  • 171
  • 1
  • 1
  • 6
  • It sounds like you are satisfied with detecting events that might constitute beats rather than needing to actually do full fledged beat detection. Is that right? – Bjorn Roche Jun 10 '13 at 14:06
  • Yes that's correct. The idea is to synchronise light change (color, animation scheme or even motion direction for motorised lights) to events in the music, to reinforce the effect of both music and light. As I said, BPM measurement would be a plus :) – abey Jun 10 '13 at 15:19
  • How much analog electronics are you willing to build? – endolith Jun 11 '13 at 15:57
  • @endolith: I'm not against doing some. I'm not against buying some either, if you know boards that would be suitable :) – abey Jun 11 '13 at 16:48
  • @abey: Hmmm... Something that works well on computers is to auto-correlate the STFT in the time dimension only, which is equivalent to making a bandpass filter bank, autocorrelating each band, and then summing them together. I'm trying to think if there's a crude way to do something like this, like with a 3-band filter or something. – endolith Jun 11 '13 at 17:24
  • @endolith: I'm not sure I understand the details of how this would work, this being not in my field of expertise. Could you elaborate in an answer? Specifically, if this could be implemented with the CMSIS DSP FFT lib, which should run more or less smoothly on the Arduino Due, it could be interesting for me. – abey Jun 11 '13 at 17:54
  • @abey: Really, you can do FFT stuff on an Arduino? This is kind of an FFT on top of another FFT, though. See a basic description here: http://dsp.stackexchange.com/a/1113/29 – endolith Jun 11 '13 at 19:17
  • @abey: Actually, though, that's really a BPM detector, not a beat detector. It tells you the rate of the beats, not the times at which they occur. So it's not directly applicable. You still need some kind of onset detector. – endolith Jun 11 '13 at 19:39
  • @endolith: Noted. FYI, the duo is a 84MHz 32bit Cortex-M3. It's not a bad MCU and the CMSIS libs are not bad either. They also have fixed point implementation which could be useful for audio processing. – abey Jun 11 '13 at 19:53

2 Answers2

6

I did one very simple bpm calculation in matlab and maybe it can help you!

source

Steps:

  1. Decompose the signal in six frequency bands (six level) using DWT

  2. Extrac the Envelope from all sub-bands

    • To make the Envelope Calculation do you need:
      • Apply Full Wave Rectification
      • Apply Low Pass Filter
      • Apply Downsample
      • Apply Mean Removal
  3. Autocorrelation

ederwander
  • 2,038
  • 12
  • 19
4

I think you can accomplish this pretty easily:

  • start with a low sample rate (simply because there is no reason for a high sample rate).
  • use a low pass filter to eliminate signal above ~100 Hz. (You'll have to experiment to find the right cuttoff frequency).
  • Create an envelope (optional). Doing this will help ensure that each beat looks like a single beat, rather than lots of separate hits.
  • Threshold the signal -- anything above a certain level is a "beat", below is not. Adjusting the threshold is your sensitivity control.

For more on low pass filtering, see my blog entry on the audio eq: http://blog.bjornroche.com/2012/08/basic-audio-eqs.html

To create an envelope, you just need to take the absolute value (or square) of each sample, and do something like

$$y[i]=\lbrace\begin{matrix}x[i], x[i]>y[i-1]\\y[i-1]*.99,x[i]<=y[i-1]\end{matrix}$$

Bjorn Roche
  • 1,006
  • 6
  • 13
  • 1
    With a low sampling rate, would you expect aliasing due to high frequency sounds (assuming no analog low pass on the mic)? Or this just doesn't happen in practice? – abey Jun 10 '13 at 18:17
  • Hopefully your S/R converter takes care of this. If not, it is broken. – Bjorn Roche Jun 10 '13 at 19:09
  • 2
    @abey: The answer is a bit vague on that point. Yes, you will want to band limit the signal appropriately for the 100 Hz sample rate. You would either do this by running your ADC at that rate, in which case you would need an analog filter somewhere ahead of the sampler, or you can sample at a higher rate and convert the rate digitally, in which case your sample rate converter should include the filtering required to enforce this condition. – Jason R Jun 10 '13 at 21:59
  • Excuse me: in my comment I meant that your ADC should take care of this (I erroneously said S/R converter). Sorry. At any rate, when you get audio at a given sample rate, as a rule of thumb, the audio should already be filtered for you, whether by sample rate conversion or by ADC. If not, something is broken. – Bjorn Roche Jun 11 '13 at 01:00
  • @BjornRoche: I don't think the ADC in a micro will take care of anything. It just samples the input when you tell it to, using successive approximation. You need an analog anti-aliasing filter if you want to prevent aliasing. – endolith Jun 11 '13 at 15:54
  • Also I don't see any point in calculating an envelope, since you're already only paying attention to values above some threshold. How will the envelope trip a comparator any differently than the signal itself? – endolith Jun 11 '13 at 15:58
  • @endolith: good question and good point for filtering. If I go the DIY way for the mic, I'll need to make sure to implement some suitable filtering. I've not yet dug into the electronics side (may be a future EE.SE question?). Before integrating everything in the MCU, I'm thinking of prototyping the algo using a laptop's integrated mic and MATLAB, and send serial commands to the MCU in charge of the light. In this case aliasing should be ok (I can low pass digitally), but the question of (adaptive?) thresholding remains to deal robustly with a sh*tty input signal. – abey Jun 11 '13 at 16:56
  • @abey: Yep, it would need to be an adaptive threshold since the signal level can change – endolith Jun 11 '13 at 17:14
  • Without a low-pass or "Anti-alias" filter, an A/D converter is not an A/D converter, it is simply a sampling circuit. If the arduino is that broken, you can use a higher sample rate. You should have enough compute power for that. – Bjorn Roche Jun 11 '13 at 18:08
  • @endolith: I explained the purpose of the envelope in my answer: "[the envelope] will help ensure that each beat looks like a single beat, rather than lots of separate hits." In other words, the envelope will make one bass hit cross the threshold one time, rather than bounce over it several times, which is what will happen without it. – Bjorn Roche Jun 11 '13 at 18:10
  • I managed to envelope the signal (low passed) to detect the beats, I simulated it in LTspice and it worked pretty well. But how could I detect the peak with my MCU? Should I use the ADC or analog comparator to detect peaks and make some calculation with the timer module? –  Oct 13 '14 at 21:20