Get music frequency, amplitude and bpm

Hey,
I would like to get frequency, amplitude and bpm of a music signal (coming from an audio jack). I have looked at several methods and none of them worked for me (even searched the second page of google). Some of these methods required some ICs which I obviously do not have.

I would especially like to get the bass/beat of the music signal.

I have some MSGEQ7 ICs coming which in theory can split the audion into 7 analog signals. I dont know if this would be accurate enough.

I know questions like this were asked several times before, but I hope I can learn something new and find the solution to this.

Thanks

Beat detection might be the most difficult... The bass isn't always the best indication of beat. Sometimes it's a snare drum, etc.


First off, you need the "right" connection or the "right" microphone/circuit, etc.

Typically, you'll use a line-level headphone-level) audio signal and bias the input so you can read the negative-half of the audio signal. My post for [u]The Worlds Simplest Lighting Effect[/u] has an attached schematic for a bias circuit.


Amplitude is pretty straightforward as long as you understand that you are sampling a waveform so you need to find the peaks, or the RMS, or the average of the absolute values, or the average of the positive half of the waveform, etc. My "Simplest Effect" looks for the peaks. The waveform is positive half the time and negative half the time, so the true-average, ignoring or subtracting any "artificial" bias, is zero.

I didn't do this for my "simplest effect" example, but generally use a peak detector (AKA envelope follower) which converts the waveform into a varying DC voltage proportional to the peak amplitude. That simplifies the software and I only have to sample about 10 times per second instead of thousands of times per second. But of course, you loose frequency information.


[u]FFT[/u] (or FHT) can give you the frequency information (the amplitude of each frequency band) and there are FFT & FHT libraries for the Arduino. If you search YouTube for "Arduino Spectrum Analyzer" you'll get some ideas of what you can do with FFT.

I don't know if the MSGEQ7 will give you the resolution you want, but if it works for you, it greatly simplifies your software and it takes care of the bias issue. It gives the same information as FFT (amplitude for each frequency-band) but it's done with filters in hardware.


I've done crude beat detection and for my purposes I like the imperfect beat detection. I wasn't trying to "calculate" BPM, I was making lights blink/change with the beat.

Here's something I wrote previously:

I don't know how this is done "properly", but I've made a crude beat detector. I lost the source code in a computer crash but here's how it works.

  1. I read and save the peak value (presumably the beat).

  2. I delay about 1/4 second (maybe 200mS, I don't remember for sure) to prevent a false trigger.

  3. Then I look for another peak equal to (or greater than) the previous peak and over then next several milliseconds the trigger threshold drifts down in case the next beat isn't quite as strong as the last one.

  4. When a beat is triggered, I save that as the new threshold and start the loop over.

This is NOT perfect and it's NOT triggered by every beat. But that's OK for my sound activated lighting effects because I don't really want a boring-constant 1-2-3-4-1-2-3-4...

I don't do any bass filtering. I don't know if that would make it better or not. Sometimes there is a snare drum that emphasizes the beat.

What I think WOULD really help would be something that calculates and "remembers" the timing... For example, when you dance or tap your foot to the beat you don't wait 'til you hear the beat... You "get in rhythm" and you anticipate the next beat.

I would start with a low pass filter to skim off everything above 1 khz. this would eliminate triggers from high frequency notes and let the Arduino focus on the boogie beat.

Music does not have a "frequency", but rather a rapidly changing spectrum of frequencies.

Beat detection algorithms include

these two

Or this collection

Or this collection

DVDdoug:
First off, you need the "right" connection or the "right" microphone/circuit, etc.

Typically, you'll use a line-level headphone-level) audio signal and bias the input so you can read the negative-half of the audio signal. My post for [u]The Worlds Simplest Lighting Effect[/u] has an attached schematic for a bias circuit.

SO I tried this, but it's quite inaccurate and provides a ton of false positives even with a 1.5k Hz low pass filter, it works better with a 795 Hz low pass filter, but it's still not what I'm looking for, there are times for which the the LED is solid, probably due to your average adjusting way too slow

SO I tried this, but it's quite inaccurate and provides a ton of false positives even with a 1.5k Hz low pass filter, it works better with a 795 Hz low pass filter, but it's still not what I'm looking for, there are times for which the the LED is solid, probably due to your average adjusting way too slow

It works GREAT if you have a good audio signal but read the comments in the code... It's NOT beat detection! ...It's the "World's Simplest Lighting Effect". I actually call it a "flicker effect".

I gave you the link in case you needed the attached bias-circuit schematic.

But, the averaging may give you some "ideas". The averaging allows automatic sensitivity adjustment for loud songs, quiet songs, and other volume changes/variations. I use similar algorithms for all of my sound activated effects.

The World's Simplest Effect is mostly just an example I posted to get people started, but I do actually use variations of that effect in a setup that cycles-through a handful of different effects.

I see, I have built this low pass circuit, tho I don't know if it works, I dont have an oscilloscope nor a multimeter. While listening to the output (yellow and black wires at the top connected to my headphones) I cannot really hear a diffrence in terms of cutting off higer frequencies (IF my calculations are correct it should cutoff at 1500Hz, and one with a 2k resistor instead of a 1k sounds the same). I understand that the filter is not instand, and it has a curve, but I don't hear the bass louder than the highs, in fact I hear all frequencies equally lover than the input. I may have misunderstood something so please help me fix this.

Headphones are usually 32 - 64 Ohms, so with a 2K series resistor you should see a significant signal loss, so the filter is not going to work right with headphones.

1500Hz is not "bass", but a 1500Hz low-pass filter should sound VERY "muffled".

You didn't tell us the capacitor value (and a schematic the best way show a circuit).

The line input on an amplifier, or the input to powered computer speakers is typically 10K - 100K and the Arduino basically has infinite resistance ~100M Ohms so it should work as expected with those loads. (although you can't leave the Arduino input "floating" and you'll need the bias circuit so your impedance/resistance will depend on your circuit.)

[u]RC Filter Calculator[/u] This assumes a high-impedance load (relative to the resistor value).

I see, I have built this low pass circuit, tho I don't know if it works, I dont have an oscilloscope nor a multimeter.

But here's what you CAN DO. Generate some tones at high (or mid) frequencies with your soundcard.* Then read the analog input with the Arduino and send the results to the Serial Monitor. Try it with and without your filter. (Of course, you'll need to find the peaks, etc., as I mentioned above.)

And you might consider buying a meter. A cheap meter is better than no-meter, but make sure it can read low AC voltages.** They are super-helpful for tracking-down problems. If this is your one-and-only electronics project, MAYBE you can get-by without one, but if this going to be your new hobby, I strongly recommend you get one.

I don't have an oscilloscope at home, but I have access to them at work. Sometimes I "lust" for one, but so far I haven't needed one. And if you do get a 'scope, in this case I'd recommend a "real" benchtop scope, NOT some cheap little built-it-yourself thing or a board that connects to your computer.

  • If you don't know how to make test-tones, [u]Audacity[/u] can generate sine waves that you can play immediately or export-as an audio file.

While you're at it, generate and listen to a 1500Hz tone and some other frequencies. Most people would describe 1500Hz as "high pitch", although technically it's closer to mid-frequency (on a logarithmic scale) and you can hear a LOT higher.

Audacity also has Equalizer & High & low-pass filter effects if you want to experiment hear what filtered music sounds like.

** My meter is not super-cheap but it doesn't read much below 1V on the AC range (at least not accurately). A lot of audio signals are lower than that, so someday I'm going to upgrade my meter.

So I got my MSGEQ7 chip, but for some reason it only outputs a constant 5v. (I have checked my A0 pin and it reads 0 if grounded and 1023 at 5V) I have looked at this post and tried to solve my mistakes as well

Here is my code and the wiring schematic can be seen in the other post, but if needed I can show it as well.

#define STROBE 4
#define RESET 5
#define DC A0

int Frequencies[7];

void setup() {
  Serial.begin(9600);
  pinMode(STROBE, OUTPUT);
  pinMode(RESET, OUTPUT);

  Serial.println("63Hz,106Hz,400Hz,1kHz,2.5kHz,6.25kHz,16kHz");
}

void loop() {
  Read_Frequencies();
  Graph_Frequencies();
  delay(50);
}

void Read_Frequencies() {
  //Read frequencies for each band
  digitalWrite(RESET, HIGH);
  digitalWrite(RESET, LOW); // HIGH to LOW resets the MSGEQ7.
  for (int freq_amp = 0; freq_amp < 7; freq_amp++) {
    digitalWrite(STROBE, LOW);
    delayMicroseconds(30);
    
    Frequencies[freq_amp] = analogRead(DC);
    digitalWrite(STROBE, HIGH);
  }
}

void Graph_Frequencies() {
  for (int i = 0; i < 7; i++) {
    Serial.print(Frequencies[i]/4);
    Serial.print(",");
  }
  Serial.println("");
}

I've never used the MSGEQ7 and some people have reported problems or defective chips...

Did you study the timing diagram on the datasheet?

You may need a delay between writing reset-high and reset-low. The timing diagram shows 100ns minimum (I don't know how fast the Arduino takes to run those two statements... There may be enough delay already but an additional known-delay wouldn't hurt.)

The timing diagram also shows the output high while reset is high. And it shows the output low when Strobe is high (following a Reset). So if the output stays at +5V after that, the chip is defective (assuming it's wired correctly and it's really getting the control pulses.)

Also, on the 1st Strobe negative-edge following a (negative edge) Reset and the appropriate delay, you are reading the 63Hz (bass) band. If you do nothing else you should be reading the bass "forever", and with no signal you should be getting (nearly) 0V. out

If you're getting 5V out with no signal, and with the correct Reset & Strobe sequence, I'd say the chip is defective or something is wired wrong.

Hey, so I have 2 of these ICs, I tested the other one and the ardino reads a nearly constant 790, with a 1023 spike at the start.

As for the sequence I don't know if I'm doing it right, I'm using code from the sparkfun example and the post I linked above.

Edit #1 I have found an arduino library which does all the timing and should in theory work, but it still gives a constant 1023 on the first and a constant 790 on the second chip

Edit #2 So it turns out that the ground rail on my breadboard is broken so the circuit was not grounded thus it did not work. Now it reads a normal voltage tho one of them is still defective I think

Edit #3 So I tried to check the frequencies with a frequency generator and it turns out that for some reason the 63Hz and 6.25kHz and the 160Hz and 16kHz bands move together so the chip only shows 5 channels, the one which should be the 2.5kHz one shows the highest at around 9.5kHz

Edit #3 So I tried to check the frequencies with a frequency generator and it turns out that for some reason the 63Hz and 6.25kHz and the 160Hz and 16kHz bands move together so the chip only shows 5 channels, the one which should be the 2.5kHz one shows the highest at around 9.5kHz

I assume this is a sine-wave generator? Are the readings linear? i.e. if you cut the amplitude in half, do the 63 & 6.25kHz readings both get cut in half? The chip does have gain and you might be overdriving it.

To confirm the chip is bad, I would suggest modifying the code so you can read one frequency-band at a time.

Did you get the chips from a legitimate supplier? Somebody on the forum said the MSGEQ7 is obsolete and people are selling rejects. Mouser shows it as obsolete, but SparkFun and DigiKey (generally reliable suppliers) are still selling them. DigiKey shows 300 in stock. ...Maybe I should buy a few while they are still available in case I want to use one (or two) someday.