Go Down

Topic: Question about magnitude (Read 4037 times) previous topic - next topic

Noisecontrol

a and b what is it?

That  souce code show magnitude for me

Do that value magnitude  set in this equiption?
dB=10log(magnitude^2)-c
??

PieterP

#16
Jun 05, 2018, 03:15 pm Last Edit: Jun 05, 2018, 03:16 pm by PieterP
https://github.com/kosme/arduinoFFT/blob/d8c22a897e637bb1719dfbef84f83a279c634eef/src/arduinoFFT.cpp#L165

a = vReal[k], b = vImag[k]

Note that this function calculates the square root. Don't do that, it's unnecessary.

Noisecontrol

FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */

This part code calculate magnitude in per frequncey bin
You say me that per mag divid to 64 then set in this equiption
dB=10log( magnitude^2)- c

Is it true?

PieterP

#18
Jun 05, 2018, 03:23 pm Last Edit: Jun 05, 2018, 03:26 pm by PieterP
Yes. But instead of calculating magnitude[k] ² as sqrt(vReal[k]² + vImag[k]²)², calculate it directly as vReal[k]² + vImag[k]².

PieterP

Is this a personal project? Is it an assignment for your studies? What's your background in mathematics and DSP?

Noisecontrol

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

Noisecontrol

Why in 0 Hz magnitude is maximum and in low frequency  magnitude is greater than middle and hight frequency ?

PieterP

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.

PieterP

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).

DVDdoug

#24
Jun 05, 2018, 07:51 pm Last Edit: Jun 05, 2018, 07:59 pm by DVDdoug
Quote
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.

MarkT

#25
Jun 05, 2018, 11:30 pm Last Edit: Jun 05, 2018, 11:34 pm by MarkT
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:
Quote
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...
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

DVDdoug

Quote
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.

PieterP

#27
Jun 06, 2018, 09:36 am Last Edit: Jun 06, 2018, 09:39 am by PieterP
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.

PieterP

#28
Jun 06, 2018, 10:41 am Last Edit: Jun 06, 2018, 10:42 am by PieterP
Here's some MATLAB/Octave code that may help you to get an idea of what's going on:

Code: [Select]
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.


MarkT

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.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up