It is personal and i didnt studied math
I know industrial acoustic but dont know FFt
I have personal project that first i must determin dBA in enviroment and then do another part project
Why in 0 Hz magnitude is maximum and in low frequency magnitude is greater than middle and hight frequency ?
I don't have much experience with the actual applications of the FFT, and I didn't study all of the maths (yet), so I think there might be other people (on this forum or elsewhere) who could do a better job at explaining it to you. There are many resources online, but it's pretty hard if you don't have one complete, chronological explanation to follow.
Some maths knowledge is required as well. Sadly, you can't just learn it by reading a couple of forum posts. You have to read up on the theories behind all of it, and then do the calculations for yourself.
Noisecontrol:
Why in 0 Hz magnitude is maximum and in low frequency magnitude is greater than middle and hight frequency ?
Probably because you have a DC offset on your input (you should bias your input to 2.5V and then compensate for that in software).
Why in 0 Hz magnitude is maximum and in low frequency magnitude is greater than middle and hight frequency ?
There is no 0Hz component to sound* but the input is usually biased/DC offset because the Arduino can't directly read the negative-half of an audio signal.
If the input is not biased/offset your waveform will be half-wave rectified, so it will again have a positive DC (zero Hz) bias, but it will also be badly distorted and your FFT will be totally fouled-up.
With real world sounds there is usually more energy in the low frequencies (that's one of the reasons woofers are bigger than tweeters), but it depends on the sound... A bass guitar obviously has more low-frequency energy than a trumpet.
White noise has equal energy at all frequencies. With white noise all of your FFT bins should be equal.
Pink has equal energy in each octave. On a linear scale the higher octaves are "wider" than the lower octaves, so pink noise is rolled-off -3dB per octave. Most spectrum analyzers show the frequency bands as octaves (or as a log scale) so pink noise "looks flat" on a spectrum analyzer.
And if you are generating white or pink noise from a speaker, remember that your speaker & microphone are imperfect.
- Air pressure (absolute or relative) is zero Hz (or near zero Hz). Since there is air pressure here on earth there is a 0Hz component. But microphones don't pick-up constant-static air pressure, regular speakers can't put-out 0Hz, and although you can sometimes feel air pressure with your ears, it is not sound.
Noisecontrol:
I think it is difficult
If i convert adc to dB and then do fft on it
Does magnitude is equal dB in per bin?
You cannot convert to dB before the FFT, the FFT is a linear operation on voltages.
DVDdoug:
With real world sounds there is usually more energy in the low frequencies (that's one of the reasons woofers are bigger than tweeters),
The reason is the wavelength of low frequencies is larger, nothing to do with the average
power spectral density of music since speakers can reproduce any signal and are ideally
flat response across the band.
The interesting question is why microphones don't have to be large for low frequencies...
The reason is the wavelength of low frequencies is larger, nothing to do with the average
power spectral density of music since speakers can reproduce any signal and are ideally
flat response across the band.
I'm not talking about wavelength. The voice coil in a woofer is larger than a tweeter and it can handle more power. If you remove the crossover and run full-power into the woofer nothing bad will happen. If you run full-bandwidth full-power into the tweeter you might fry it.
I think you lose the notion of "RMS Voltage" when applying the FFT. The RMS over the entire spectrum is the same (corrected for your processing gain (sqrt(2n)) and the coherent gain of your window (rms(window))). However, you can't use the entire spectrum, you have to use the energy per frequency bin to be able to weigh them.
So the question here is: what is the relationship between the energy in the bin and the RMS voltage of the original sine wave.
I think your formula applies to the time domain, where you can use a digital filter to do the weighting, and then just taking the RMS voltage of the resulting signal.
ANSI S1.42 specifies the (continuous) transfer functions for such an a-weighting filter. (here)
You could either filter it in the analog domain, using op-amps and analog filters:
http://sound.whsites.net/project17.htm
Or you could transform it into the digital domain and use a discrete digital filter. Usually, a bilinear transform is used. It is an approximation of the mapping between the s-plane and the z-plane. However, some people note that this produces an error at the higher end of the spectrum, which could be a problem for you. You could use some kind of regression or optimization to minimize the error in the higher regions as well.
But there's a catch: according to Nyquist, you need a sampling rate of at least twice the frequency of the highest frequency in your analog signal. Every frequency higher than half of your sampling rate will cause aliasing, and completely mess up your results.
This implies two things: you need a sampling frequency of at least 40 kHz (2×20 kHz), preferably higher.
You need a (strong) analog filter to make sure that very little frequencies above 20 kHz remain in the signal that you send to the ADC. (Note: this is true when applying digital filters, but also when applying an FFT!)
The maximum sampling frequency of the Arduino's ADC is about 10 kHz. That's nowhere near enough.
That being said, you might be interested in this: How to prove that A-weighting doesn't work
You might find people who know more about this topic than myself on StackOverflow Signal Processing.
Here's some MATLAB/Octave code that may help you to get an idea of what's going on:
close all;
nb_samples = 128; % 128 samples → 128 frequency bins
n = (0:nb_samples-1)';
f_s = 256; % 256 Hz sample frequency
f_1 = 32; % Sine wave with a frequency of 32 Hz
A_1 = 1; % and amplitude of 1
f_2 = 60; % Sine wave with a frequency of 60 Hz
A_2 = 0.5; % and amplitude of 0.5
t = n / f_s; % Generate a vector with time
sine_1 = A_1*sin(2*pi*f_1*t);
sine_2 = A_2*sin(2*pi*f_2*t);
sine = sine_1 + sine_2;
subplot(2,2,1);
plot(t, sine, '-o');
title('Original sine waves');
rms_original = rms(sine);
db_rms_original = 20*log10(rms_original);
%% Without window
fft_sine = fft(sine);
freq = n*f_s/nb_samples;
subplot(2,2,2);
stem(freq, abs(fft_sine)/nb_samples);
title('Magnitude per frequency bin after FFT (without window)');
energy_fft = sum(abs(fft_sine).^2)/nb_samples^2;
db_energy_fft = 10*log10(energy_fft);
energy_gain = sqrt(energy_fft)/rms_original;
db_energy_gain = db_energy_fft - db_rms_original;
fprintf("Without window\n");
fprintf("==============\n");
fprintf("V_RMS = %f (%f dB)\n", rms_original, db_rms_original);
fprintf("Energy_FFT = %f (%f dB)\n", sqrt(energy_fft), db_energy_fft);
fprintf("Energy gain = %f (%f dB)\n\n", energy_gain, db_energy_gain);
%% With window
window = hamming(nb_samples);
rms_window = rms(window);
db_rms_window = 20*log10(rms_window);
windowed_sine = window.*sine;
subplot(2,2,3);
hold on;
plot(t, windowed_sine, '-o');
plot(t, window, '-k');
plot(t, -window, '-k');
title('Sine waves after applying window');
fft_sine = fft(windowed_sine);
freq = n*f_s/nb_samples;
subplot(2,2,4);
stem(freq, abs(fft_sine)/nb_samples);
title('Magnitude per frequency bin after FFT (with window)');
energy_fft = sum(abs(fft_sine).^2)/nb_samples^2;
db_energy_fft = 10*log10(energy_fft);
energy_gain = sqrt(energy_fft)/rms_original;
db_energy_gain = db_energy_fft - db_rms_original;
fprintf("With window\n");
fprintf("===========\n");
fprintf("V_RMS = %f (%f dB)\n", rms_original, db_rms_original);
fprintf("Energy_FFT = %f (%f dB)\n", sqrt(energy_fft), db_energy_fft);
fprintf("Energy gain = %f (%f dB)\n", energy_gain, db_energy_gain);
fprintf("Coherent window gain = %f (%f dB)\n\n", rms_window, db_rms_window);
Output:
Without window
==============
V_RMS = 0.790569 (-2.041200 dB)
Energy_FFT = 0.790569 (-2.041200 dB)
Energy gain = 1.000000 (0.000000 dB)
With window
===========
V_RMS = 0.790569 (-2.041200 dB)
Energy_FFT = 0.496454 (-6.082415 dB)
Energy gain = 0.627971 (-4.041215 dB)
Coherent window gain = 0.627969 (-4.041233 dB)
Note that some energy is lost due to the windowing, so you'll have to make up for that.
DVDdoug:
I'm not talking about wavelength. The voice coil in a woofer is larger than a tweeter and it can handle more power. If you remove the crossover and run full-power into the woofer nothing bad will happen. If you run full-bandwidth full-power into the tweeter you might fry it.
A lot of bass drivers are 1" coils, whatever size the cone is. You pay a lot of money for larger coils and magnets,
its the majority of the materials cost. Standard hifi powers of 50W peak, average music, then the average power is a few watts and nothing cooks. PA system, everything is different, larger, vented, speaker motors are commonplace.
Bass drivers use thicker coils, as they have much larger excursion than tweeters so can have 10 to 100 times
the amount of copper in the coil to help spread the heat.
Hello
Maximum adc is 1024 then why when adc analized by fft ,magnitude value in per bin frequency could be greater than 1024 ?
If magnitude in per frequency should not
be less than 1024 ?
Maximum adc is 1024
No, 1023.
How can i fft result ( magnitude)convert to voltage in per frequency bin?
Noisecontrol:
...fft result ...
¿Fast Fourier Transform?
vffgaston:
¿Fast Fourier Transform?
Yes
I don't know how it's scaled, but if you can't find it in the documentation you can calibrate it.
For example, feed-in a 1V, 1kHz, signal and see what you get. Then, you can use the map() function to map the values to voltage. If you feed-in a 1V, 100Hz, signal you should get (about) the same reading in the 100Hz bin. And if you mix the two signals both bins should still read (about) the same as before.
Choose frequencies that are in the center of the bin frequencies.
...If you need a way to generate sine waves, [u]Audacity[/u] can make a WAV file. that you can play on your soundcard. You can also mix in Audacity so you can try with two (or more) known frequencies. But since mixing is done by summation, you'll want to generate waves at -6dB (half of the maximum) or less. And, you'll need a multimeter to measure the voltage.
I didnt find any documantion about convert fft results to adc or voltage in google.
But when fft analized a signal , we have expected that get amplitud in per frequency base that factor analized. in other word if adc is amplitude of a signal in per time we have expected frequncies have same unit amplituid
I didnt find any documantion about convert fft results to adc or voltage in google.
Presumably you mean DAC, which standard Arduinos do not have, but why would anyone bother to document something so simple?
analogWrite(pin,bin_value);
Maximum adc is 1024 then why when adc analized by fft ,magnitude value in per bin frequency could be greater than 1024 ?
Possibly, depending on how the FFT results are scaled. Different FFT subroutine packages scale the output differently.
Here is an idea: write some simple programs and learn how the FFT works.
That way you can answer questions like this yourself, and learn something in the process.
Example using the OpenMusicLabs FFT library:
/*
fft_test_constant
example sketch for testing the fft library.
This generates a constant data set demonstrating the DC
offset term. Enable the fft_window() line to see the effect of
windowing.
*/
// do #defines BEFORE #includes
#define LIN_OUT 1 // use the lin output function
#define FFT_N 32 // set to 32 point fft
#include <FFT.h> // include the library
void setup() {
int i, k;
Serial.begin(9600); // output on the serial port
for (i = 0 ; i < FFT_N ; i++) { // create data samples
fft_input[2 * i] = 1000; // put real data into even bins
fft_input[2 * i + 1] = 0; // set odd bins to 0
}
// fft_window(); //Try with and without this line, it smears
fft_reorder(); // reorder the data before doing the fft
fft_run(); // process the data using the fft
fft_mag_lin(); // calculate the magnitude of the output
// print the frequency index and amplitudes
Serial.println("bin amplitude");
for (i = 0; i < FFT_N / 2; i++) {
Serial.print(i);
Serial.print(" ");
Serial.println(fft_lin_out[i]);
}
Serial.println("Done");
}
void loop() {}
Output:
bin amplitude
0 1000
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 0
Done
jremington:
Presumably you mean DAC, which standard Arduinos do not have, but why would anyone bother to document something so simple?analogWrite(pin,bin_value);
No i want to convert fft results in per bin to voltage
