Go Down

Topic: how can I measure the frequency of sound? (Read 571 times) previous topic - next topic

zueses

I need to read an analog signal at about 500-1000Hz for at least 5 seconds.

I've a battery powered microphone wired into an analog and ground pin on my arduino and am trying to measure the frequency (and amplitude) of sound coming from a rijke tube


To accurately represent the sound waves I need to take samples with a frequency at least twice that of the sound I'm studying, hence the frequency above. Having stripped down every other part of my code, I could still only get at the most 107 readings a second, as shown below

Code: [Select]
// EmonLibrary examples openenergymonitor.org, Licence GNU GPL V3

#include "EmonLib.h"             // Include Emon Library



#define VOLT_CAL 269
#define CURRENT_CAL 60
unsigned long time;

EnergyMonitor emon1;             // Create an instance

void setup()

  Serial.begin(9600);

  Serial.println("CLEARDATE");
  Serial.println("LABEL, DATE, TIME,Wall Voltage,Wall Current, Mic Voltage, Time Elapsed");
}

void loop()
{
  int sensorValue = analogRead(A4);

   time = millis();

Serial.print(sensorValue);
Serial.print(",");
Serial.println(time); //prints time since program started
delay (1);
}


can anyone tell me what I'm doing wrong/how I can increase the sample rate?

I've also tried to use a for loop to take my readings first, only printing them at the end but also maxed out at only 100 readings a second with the next attempt of code

Code: [Select]
#define NUMSAMPS 100
int data[NUMSAMPS];
int times[NUMSAMPS];

void setup()

  Serial.begin(9600);
  Serial.println("Mic Voltage, Time Elapsed");
}

void loop()
{
for(int i=0;i<NUMSAMPS;i++)
{
data[i]=analogRead(A4);
times[i]=millis();
}
for(int i=0;i<NUMSAMPS;i++)
{
Serial.println(data[i]);
}
for(int i=0;i<NUMSAMPS;i++)
{
Serial.println(times[i]);
}
}



Any direction would be appreciated very much

DVDdoug

This won't be of much help...

You might want to look-into the FFT & FHT libraries or there is something called autocorrelation.   (I've never used any of them.)

Of course, you can't have any delays in your main-read loop....

You also shouldn't print every time through the loop.   You need to collect some data, then analyze and print-out.     And there's not much RAM so it has to be short samples.

From what I understand, the FFT & FHT libraries don't sample continuously.   They pause sampling to do the processing/analysis.

zueses

thanks for the reply and trying to anyway (-:

Quote
You need to collect some data, then analyze and print-out.
thats kind of what i tried to do on the 2nd attempt! probably..not well enough though.
will give the rest a look through, FFT was my next step anyway!

Grumpy_Mike

#3
Mar 27, 2019, 08:44 am Last Edit: Mar 27, 2019, 08:49 am by Grumpy_Mike
You can get a sample rate of about 10K samples per second straight off using internal A/D. Anything less and it is down to your poor code.

Quote
To accurately represent the sound waves I need to take samples with a frequency at least twice that of the sound I'm studying, hence the frequency above.
No to accurately represent the sound wave you need many times more than two samples per cycle. You are getting confused with the nyquist rate which is the minimum you need to just get the frequency information not accurately get the frequency information.

Measuring frequency of a simple waveform can be done in two ways.
1) Counting the number of cycles in a fixed period of time.
2) Measuring the time between two successive points in the waveform.

A good way of doing either is to use a zero crossing detector on the input waveform. Then there is no need to use analogue inputs at all, just digital ones, and they are so much faster.

An FFT will not give you an accurate measure of frequency because the results are put into bins. Each bit contains all the frequency components between two frequencies. The number of bins is determined by how many samples you use and you can't get enough in an Arduino for anything very accurate.

MarkT

To accurately represent the sound waves I need to take samples with a frequency at least twice that of the sound I'm studying
Everyone seems to get this wrong, you must sample definitely _more than_ twice the signal frequency.
In practice due to the requirement of having a practical anti-aliasing filter design, a lot more than twice is good
to have.  2.5 to 3 times is about the minimum you see in practice even with sophisticated anti-aliasing.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

marxmellow

Um. First things first. Are you trying to accurately reproduce the sound? No.whew. then its easier. You want to measure the frequency of a known period at a known amplitude right? Ok whats left? Frequency. Are you going for a frequency reading ( ie:its 1khz) or does it range? Are you looking for when it hits a certain frequency? This is why i ask...  use a bridge rectifier to reduce it to dc.  The higher the frequency given that the amplitude is the same the higher the dcvoltage will be once its rectified. Your looking for an average amoubt of energy. Do an experiment. Take a function gererator and generate a 1khz tone. Rectify it and measure the voltage. Then up it to 10k and see what you get. The average will be higher. So therefore the measured voltage will be as well.
You really have to look at exactly What are you trying to isolate. Reduce the rest of the crap around it to nothing and it becomes simple. Of course if you are trying to sample it? Get a littleboard that does it for you. There are audio engineers that make poor sounding samplers. Dont recreate the wheel.
Jc

marxmellow

Everyone seems to get this wrong, you must sample definitely _more than_ twice the signal frequency.
In practice due to the requirement of having a practical anti-aliasing filter design, a lot more than twice is good
to have.  2.5 to 3 times is about the minimum you see in practice even with sophisticated anti-aliasing.

Mark if you were to draw out a 12khz waveform and take two samples of it how accurate do you think that wouldbe if you were trying to reproduce it. Your being conservative. Sample at 44k and you makeme happy. My hearing cuts out at about 12k maybe a wee bit higher. Still sounds like crap to a trained ear but im happy. Sample at 92k ( or id it 98...I forget) and it sounds beautifulish.  92/12 equals almost nine times. Two times sampling sounds like that chick at burger king on that cheap radio headset. Play with your computer sound card and youll see. By the way a usb sound card would do this nicely for about five bucks
Want some me fries with that?
Ps. I already asked if that was the goal in the first place. Are we sampling by recreating the wheel?
Jc

Grumpy_Mike

Quote
Still sounds like crap to a trained ear
Rubbish. This is a forum for facts not audiophile nonsense.

MarkT

Mark if you were to draw out a 12khz waveform and take two samples of it how accurate do you think that wouldbe if you were trying to reproduce it. Your being conservative. Sample at 44k and you makeme happy. My hearing cuts out at about 12k maybe a wee bit higher. Still sounds like crap to a trained ear but im happy. Sample at 92k ( or id it 98...I forget) and it sounds beautifulish.  92/12 equals almost nine times. Two times sampling sounds like that chick at burger king on that cheap radio headset. Play with your computer sound card and youll see. By the way a usb sound card would do this nicely for about five bucks
Want some me fries with that?
Ps. I already asked if that was the goal in the first place. Are we sampling by recreating the wheel?
Jc
This is absolutely nothing to do with your wishful thinking about your hearing abilities.

This is a mathematical proven fact about sampled signals.  Note its actually about sampled signals,
not quantized sampled signals.  Its about what you need to avoid any information loss for a
band-limited signal that you sample at a fixed rate.

Its also clear you didn't understand what I wrote.  2.5 to 3x is the minimum factor you see in
practice (due to the cost of making a ultra-high performing brick-wall anti aliasing filter).  You are
claiming I said 2x is adequate which is exactly what I did not say, because it doesn't work at all.

92 and 98 are both wrong, the standard I2S sample rates are 48, 96, 192, 384kSPS, as well as
44.1kSPS for CD.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

pjrc

#9
Apr 03, 2019, 12:02 pm Last Edit: Apr 03, 2019, 12:09 pm by pjrc
If the waveform is relatively simple, so that you can reliably turn it into a digital signal using a voltage comparator similar circuit, then you could use the FreqMeasure library to measure its period.  If you're using an 8 bit AVR board like Arduino Uno or Nano, that's probably the most realistic path.

https://www.pjrc.com/teensy/td_libs_FreqMeasure.html

Those 8 bit boards just don't have much CPU power.  Merely acquiring the signal at a high enough sample rate is quite a challenge on those older boards.  Then doing any sort of meaning analysis on that data is doubly difficult, because the board is already so heavily taxed just reading the samples.

As you step up to more capable boards, better options become available.  Using Arduino Zero (an ARM Cortex-M0 at 48 MHz), you could use the audio frequency meter library.

https://www.arduino.cc/en/Tutorial/SimpleAudioFrequencyMeter

This library is able to deal with moderately complex but steady waveforms, where harmonics cause repeatable extra "zero cross" behavior on every cycle.  You can probably expect good results with sounds like flutes and other wind instruments and clear vocals.  Very complex sounds where the timber or character of the sound changes rapidly during each note are probably beyond this library's capability.

If you step up to even more capable boards, you'll have enough processing power to do much better analysis.  Using Teensy 3.2 or 3.6 (Cortex-M4 at 96 or 180 MHz) you can use the Teensy Audio Library AudioAnalyzeNoteFrequency analysis.

https://www.pjrc.com/teensy/gui/?info=AudioAnalyzeNoteFrequency
https://github.com/PaulStoffregen/Audio/blob/master/examples/Analysis/NoteFrequency/NoteFrequency.ino

This analysis uses the YIN algorithm, which is able to detect the fundamental note frequency from even very complex sounds, like a guitar or tuba.  But this type of analysis comes at quite a CPU usage cost, nearly all the CPU power of a Teensy 3.2 when running at 96 MHz.  If that's all your project really needs to do, then 3.2 is probably a good solution.  If you're going to do more while also performing the analysis, the faster 3.6 board would give you that extra CPU power to actually do substantial other work while acquiring & analyzing the sound.


I'm sure everyone can endlessly argue about sound quality & sample rates.  If you're going to create everything from scratch, maybe that might even be helpful.  But if you want to leverage libraries and resources that already are available, hopefully these links and this guidance about what sort of analysis you can hope to achieve on hardware at different levels of performance will help you get something working quickly & easily.

dsm311

on this note....I'm trying to take sound frequencies using a microphone that has to be plugged in using an aux port. I'm pretty much using this as a model

https://www.arduino.cc/en/Tutorial/SimpleAudioFrequencyMeter

but, for some reason i cant receive any input using the mic. The circuit works because it was tested with an oscilloscope and a function generator and it works. The readings can be off at certain frequencies but its mostly good. I'm thinking that the mic might need either a preamp before connecting to the circuit but I'm not entirely sure.

Go Up