Arduino Forum

Using Arduino => Audio => Topic started by: Noisecontrol on Jun 05, 2018, 12:02 pm

Title: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 12:02 pm
Hello
I use this code for analyize sound

https://github.com/kosme/arduinoFFT/blob/master/Examples/FFT_03/FFT_03.ino



What is magnitude ?
Is it amplitude?
What relation is between magnitude and amplitude and ADC?
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 12:15 pm
Please, edit your post to use code tags. Parts of your code were removed and caused the entire post to be printed in italic. You would have known that if you'd have read the guidelines in the sticky posts on 'how to use this forum'.

Magnitude refers to the distance between a point in the complex plane and the origin. Sometimes, this can be the distance squared.

It is proportional to the sum of the amplitudes of the sinusoidal waves at the input with a frequency that falls within the frequency bin in question.
You probably have to divide by the number of frequency bins for it to be correct, if the library doesn't already do this.

Pieter
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 12:37 pm
Hi pieter
I am sorry
I edit my post

Amplitude= ((magitude ^2)-(frquency^2))^0.5
Is it true?

What is relation between ampltude and ADC in per bin?
How can i calculate ADC in per bin?
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 01:00 pm
When you calculate the FFT of 2n samples, you get a complex number for each of the 2n frequency bins. These frequency bins are symmetrical around the Nyquist frequency (sample frequency / 2), or symmetrical around the origin (i.e. negative frequencies). This means that you only need half of the frequency bins (because the other half is the same).
The magnitude is the distance between these complex numbers and the origin: Magnitude(a+bi) = sqrt(a²+b²).

The way the FFT works, it scales the result by the window size (2n).
So you have to divide the results by 2n to get the actual magnitude.
However, this also includes the negative frequencies, so it will be half of what you would expect. Solution: multiply by two again.

In short: actual magnitude of result (a+bi) = sqrt(a²+b²)/n

Interpretation: if you apply a sine wave with an amplitude of 1 to the input, the magnitude of the resulting frequency bin will be one as well. (Depending on the resolution, and only if the frequency of the sine wave is a natural multiple of the frequency resolution of the FFT, otherwise, it will be smeared out across neighboring bins as well.)

Note: when you're interested in the energy of each frequency bin, or if you want to express it in dB, calculating the square root is a complete waste of resources.

What is relation between ampltude and ADC in per bin?
How can i calculate ADC in per bin?
Parseval's theorem states that the energy in the time domain is the same as the energy in the frequency domain.
However, for a discrete Fourier transform (of which the FFT is an implementation) you have to scale it by a factor of n (or 2n, if you care about negative frequencies).
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 01:22 pm
Your means is if my 2n=128
I must magnitude divid to 64 to be actual magnitude in per bin?
Please say one example to do it
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 01:28 pm
Your means is if my 2n=128
I must magnitude divid to 64 to be actual magnitude in per bin?
Yes.

I can't explain it quickly without a good mathematical foundation. It is not an easy topic. You should probably do your own research to try and grasp the mathematics behind all of it.
Or just blindly do what everyone else does, without understanding it, that'll probably work just fine in this case.

What do you want to do with the result?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 02:07 pm
I want to make a sound level meter that show result in dB A_weighting
For get a weighing must first analyze sound and then wighted
There are a equiption that convert adc to Vrms and then dB
dB =20log(Vrms/0.0063)+94-sensivity mic-gain
If i can Vrms in per bin .i can calculate dB per bin and then i can weight them and calculate overall SPl in dBA
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 02:28 pm
I already explained how to get the magnitude of the frequency bins. You're interested in the power spectral density, which can be estimated by the magnitude squared.

To convert it to a logarithmic scale, just take the logarithm of the results. This is the power in Bels. Multiply by ten to get decibels.

Now you're still stuck in ADC units. You have to scale everything by a factor of 5V/1024 to convert it to Volts (or Watts). Just add 20*log(5.0/1024) to the result.

Remember: actual magnitude squared of (a+bi) = |a+bi|²/n²  = (a²+b²)/n². No need to take the square root. Just use a factor of 10 before your logarithm instead of 20 (because 20 log(x) = 10 log(x²)).

Then add 94 and the mic gain to set your reference level and compensate for the microphone's sensitivity.

Edit: where did you get that factor 1/0.0063 and 94?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 02:36 pm
 20 log(x) = 10 log(x²)).

X is magnitude?
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 02:37 pm
Yes. But that's a mathematical identity that holds true for all (positive) x.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 02:43 pm
0.0063 get from sensivity of microphone
If mic sensivity be -44dBV the by under equiption you can calculated
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 02:48 pm
In that case, why do you add those other two terms?
Keep in mind that 20 log(x/y) = 10 log(x²) - 20 log(y).
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 02:51 pm
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?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 02:58 pm
Like this
K=analogread(A0)
Vrms=(k*5/1023)*0.707
dB=20log(Vrms/0.0063)+94-44-gain

Then dB enter fft lib and show dB per bin
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 03:01 pm
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?
That won't help. You have to do the conversion either way. And if you do it before the FFT, you'll lose a lot of precision. On top of that you would have to divide, which is many times slower than the subtraction you have to do after the log.

No:
dB = 10 log (magnitude ²) - c

Where c is the compensation for voltage reference, ADC resolution, amplification and microphone sensitivity. It is constant, so you only have to calculate it once.
magnitude² = (a²+b²)/n²
And FFT[k] = a+bi for frequency bin k.

As for the Vpeak to VRMS conversion: I don't know, honestly, I'd have to work that out on a piece of paper and verify in MATLAB or Octave.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 03:10 pm
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
??
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 03:15 pm
https://github.com/kosme/arduinoFFT/blob/d8c22a897e637bb1719dfbef84f83a279c634eef/src/arduinoFFT.cpp#L165 (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.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 03:18 pm
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?
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 03:23 pm
Yes. But instead of calculating magnitude[k] ² as sqrt(vReal[k]² + vImag[k]²)², calculate it directly as vReal[k]² + vImag[k]².
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 03:25 pm
Is this a personal project? Is it an assignment for your studies? What's your background in mathematics and DSP?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 03:30 pm
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
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 05, 2018, 03:35 pm
Why in 0 Hz magnitude is maximum and in low frequency  magnitude is greater than middle and hight frequency ?
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 03:36 pm
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.
Title: Re: Question about magnitude
Post by: PieterP on Jun 05, 2018, 03:37 pm
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).
Title: Re: Question about magnitude
Post by: DVDdoug on Jun 05, 2018, 07:51 pm
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.
Title: Re: Question about magnitude
Post by: MarkT on Jun 05, 2018, 11:30 pm
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...
Title: Re: Question about magnitude
Post by: DVDdoug on Jun 06, 2018, 03:29 am
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.
Title: Re: Question about magnitude
Post by: PieterP on Jun 06, 2018, 09:36 am
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 (https://pims.grc.nasa.gov/plots/user/acoustics/FrequencyWeightingEquations.pdf))

You could either filter it in the analog domain, using op-amps and analog filters:
http://sound.whsites.net/project17.htm (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 (http://sound.whsites.net/articles/a-weighting.html)

You might find people who know more about this topic than myself on StackOverflow Signal Processing.
Title: Re: Question about magnitude
Post by: PieterP on Jun 06, 2018, 10:41 am
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.

(http://forum.arduino.cc/index.php?action=dlattach;topic=551490.0;attach=261039)
Title: Re: Question about magnitude
Post by: MarkT on Jun 06, 2018, 01:15 pm
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.
Title: A question
Post by: Noisecontrol on Jun 14, 2018, 03:06 pm
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 ?
Title: Re: A question
Post by: TolpuddleSartre on Jun 14, 2018, 03:46 pm
Quote
Maximum adc is 1024
No, 1023.
Title: Fft result to voltage
Post by: Noisecontrol on Jun 14, 2018, 03:50 pm
How can i fft result ( magnitude)convert to voltage in per frequency bin?
Title: Re: Fft result to voltage
Post by: vffgaston on Jun 14, 2018, 03:54 pm
...fft result ...
¿Fast Fourier Transform?
Title: Re: Fft result to voltage
Post by: Noisecontrol on Jun 14, 2018, 04:02 pm
¿Fast Fourier Transform?
Yes
Title: Re: Fft result to voltage
Post by: DVDdoug on Jun 14, 2018, 04:41 pm
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, Audacity (https://www.audacityteam.org/) 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.   
Title: Re: Fft result to voltage
Post by: Noisecontrol on Jun 14, 2018, 05:01 pm
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
Title: Re: Fft result to voltage
Post by: jremington on Jun 14, 2018, 05:38 pm
Quote
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?

Code: [Select]
    analogWrite(pin,bin_value);
Title: Re: A question
Post by: jremington on Jun 14, 2018, 05:53 pm
Quote
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:
Code: [Select]

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

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
Title: Re: Fft result to voltage
Post by: Noisecontrol on Jun 14, 2018, 06:21 pm
Presumably you mean DAC, which standard Arduinos do not have, but why would anyone bother to document something so simple?

Code: [Select]
    analogWrite(pin,bin_value);
No i want to convert fft results in per bin to voltage
Title: Re: Fft result to voltage
Post by: jremington on Jun 14, 2018, 06:31 pm
Quote
No i want to convert fft results in per bin to voltage
Explain this comment, and explain why you think analogWrite() does not do what you want.
Title: Re: Fft result to voltage
Post by: PieterP on Jun 14, 2018, 06:34 pm
We've been over this in your previous thread (http://forum.arduino.cc/index.php?topic=551490.15).

You even started a third thread (http://forum.arduino.cc/index.php?topic=553150.0) on the topic.

Please don't cross-post!

You have to correct for a couple of things:


Here's a MATLAB/Octave script that does exactly that, together with the result, to get an understanding of what's going on. See line 58 for the actual conversion.
Code: [Select]
%% Setup

close all;

N = 128;  % 128 samples → 128 frequency bins
samples = (0:N-1)';

f_s = 256;     % 256 Hz sample frequency

f   = 64;      % Sine wave with a frequency of 64 Hz
A   = 1.25;    % and amplitude of 1.25 V peak

V_bias = 2.5;
V_ref = 5;

ADC_bits = 10;
ADC_factor = 2^ADC_bits;

t = samples / f_s;     % Generate a vector with time

sine_V = A*sin(2*pi*f*t); % Sine wave in volts
sine_V = sine_V + V_bias; % Bias
sine = sine_V * ADC_factor / V_ref; % Sine wave as sampled by the Arduino

subplot(2,2,1);
plot(samples, sine, '-o');
axis([0 N 0 ADC_factor])
title('Original 1.25 V peak, 64 Hz sine wave (ADC Units)');

%% DC offset correction

sine = sine - V_bias * ADC_factor / V_ref; % Subtract bias again

%% Windowing

window = hamming(N);
mean_window = mean(window);
windowed_sine = window.*sine; % Apply window function

subplot(2,2,3);
hold on;
plot(samples, windowed_sine, '-o');
plot(samples, ADC_factor * window / 2, '-k');
plot(samples, -ADC_factor * window / 2, '-k');
title('Sine wave after applying window');
axis([0 N -ADC_factor/2 ADC_factor/2])

%% FFT

fft_sine = fft(windowed_sine);
freq = samples * f_s / N;

subplot(2,2,2);
stem(freq, abs(fft_sine));
axis([0 f_s 0 inf]);
title('Magnitude per frequency bin after FFT');

corrected_fft = fft_sine / N * 2 / mean_window * V_ref / ADC_factor;
subplot(2,2,4);
half = length(freq) / 2;
stem(freq(1:half), abs(corrected_fft(1:half)));
axis([0 f_s / 2 0 inf]);
title('Magnitude per frequency bin after FFT (corrected)');


Here's the result:
(http://forum.arduino.cc/index.php?action=dlattach;topic=551490.0;attach=262243)

If you want the RMS voltage, I already gave you the formula in your previous thread.

If you're using a dB scale, express the divisions as a sum of constant logarithms, using the identities log(x*y) = log(x)+log(y) and log(x/y) = log(x) - log(y).

Pieter
Title: Re: Question about magnitude
Post by: Coding Badly on Jun 14, 2018, 07:19 pm

Threads merged.  Again.

Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 14, 2018, 08:17 pm
You have to correct for a couple of things:
  • Subtract the bias voltage (expressed in ADC units) from the sampled signal
  • Use the complex modulus of the FFT result to get the magnitude
  • Divide by the number of samples to correct for the FFT processing gain
  • Multiply by 2 to account for magnitude "lost" in negative part of the spectrum
  • Divide by the average amplitude of the windowing function
  • Convert the magnitude in ADC units to a voltage (*5/1024)

If you have source code of this process for arduino please share it.
I dont know MATLAB code
Title: Re: Question about magnitude
Post by: PieterP on Jun 14, 2018, 08:38 pm
If you have source code of this process for arduino please share it.
I dont know MATLAB code
I don't have the Arduino code for this, and I can't test it.
The principle is explained in my post, you can look at the MATLAB implementation for inspiration.
You should be able to read it, even if you don't know the exact syntax. Line 58 is the most important line.
Can you explain what you don't understand?

Like I said before, using FFT doesn't seem to be the standard way to perform A-weighting, you should probably look into digital filters instead.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 14, 2018, 09:42 pm
corrected_fft = fft_sine / N * 2 / mean_window * V_ref / ADC_factor;

 What is fft_sin and N and mean_window and v_ref and adc factor?

fft_sin is magnituid in per bin?
N is samples for example 128?
mean_window what is it and how calculated?
V_ref is 5 or 3.3 volt?
Adc factor how calculated?
Title: Re: Question about magnitude
Post by: PieterP on Jun 14, 2018, 10:25 pm
They're defined above.

fft_sine is the result of the FFT, either as complex number, or the modulus of that complex number.
N is the number of bins (or the number of samples).
mean_window is the average value of the window function you're using.
V_ref is the ADC reference voltage, it depends on what Arduino you're using and how it's configured.
ADC_factor = 2^10 = 1024 if you're using the internal 10-bit ADC.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 14, 2018, 10:49 pm
For calculate mean window i must get avarage Vreal of window function ?
Title: Re: Question about magnitude
Post by: PieterP on Jun 14, 2018, 11:01 pm
The window function is real by definition. But yes.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 14, 2018, 11:37 pm
Please explain about fft_sin
Is fft _sin complex number like A+jB?
Title: Re: Question about magnitude
Post by: PieterP on Jun 14, 2018, 11:41 pm
It's more efficient if you calculate the modulus first, but from a mathematical standpoint it doesn't matter, because |r(a+bi)| = r|a+bi|.

It is the result of the FFT, and you want the magnitude, so you take the modulus. Then you multiply that modulus by the aforementioned correction factors.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 12:05 am
I didnt understand
My english is not good please say simple to do it
Sin_fft is equal to magnitude or not?
If not how can i calculate sin_fft
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 12:07 am
It is the magnitude of the results of the FFT.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 08:02 am
Then magnitude per bin is equal  to sin_fft
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 09:05 am
Yes.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 09:25 am
About ADC reference voltage, 
I use arduino uno and i want to use 5 volt pin
How much is v_ref?
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 09:38 am
Then V_ref is 5V.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 09:52 am
After calculating correct_fft, the value of correct_fft will be in terms of voltage in per bin?
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 10:01 am
Yes. But because of windowing and discretization, you'll get non-zero values in neighboring bins.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 10:22 am
Yes. But because of windowing and discretization, you'll get non-zero values in neighboring bins.
I didnt understand you
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 10:38 am
Take a look at the image I posted earlier. You start with a 64 Hz sine wave of 1.25 V peak. The corrected FFT shows an amplitude of 1.25 in the 64 Hz bin, as you would expect, but the 62 Hz and 66 Hz bins are not zero.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 10:45 am
Understood your means
What is reason of it?
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 10:51 am
Because of the windowing, in this case. But you get the same problem if your input frequency is not an integer multiple of the bin frequency. There's not much you can do about it.

Are you still trying to do A-weighting?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 10:54 am
Maybe because of a slight oscillation in the main frequency. If the distance between frequencies increases, this problem can be solved
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 11:00 am
I try to analize sound and then caculated dB flat in per bin if it be corrected by a reffrence sound level meter,I can convert dB flat to A weighting and test it.but the hardest part of this project make a amplifire microphon and messurment adc and convert to voltage in per bin by fft.
I try and show my code to you to help me about it
Thanks a lot
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 11:13 am
A-weighting is normally done in the time-domain, using analog filters. Newer devices use digital filters. I couldn't find any online references on using FFT for A-weighting.
If your goal is to create a working A-weighting system, I'd use digital filters.
If you want to learn about DSP and the Fourier transform, to try a new approach to A-weighting, I think you'll have to study the maths behind it first.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 11:27 am
I find a circuit for a weighting
Is it your means?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 11:41 am
If you see some sound level meter aplication that analized sound in dBA  like audiotools , i think it a-weighting by fft cuz there are no any circuit to do a_weighting in mobile
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 11:51 am
I'm pretty sure that it uses digital filters. You can "convert" analog filters to digital filters. The bilinear transform does exactly that, for example. It's a first-order approximation, but it should do the trick.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 12:34 pm
How a android mobile do digital filter?
Title: Re: Question about magnitude
Post by: PieterP on Jun 15, 2018, 12:43 pm
Probably using cascaded digital BiQuad filters.
You factor the discrete-time transfer function into second-order polynomials (both the numerator and the denominator), and then you use the coefficients of these polynomials as the coefficients of the BiQuad filters.

Or you could calculate the convolution of the difference equation explicitly. But I think that could result in numeric instability.

Either way, it's going to be much easier than using an FFT.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 12:59 pm
Can do it by aurdino?
How can i find sample of it in arduino code?
Title: Re: Question about magnitude
Post by: MarkT on Jun 15, 2018, 02:01 pm
Understood your means
What is reason of it?

The fourier transform is only mathematically defined for periodic waveforms (that repeat for ever)
The DFT (of which FFT is an implementation) is only meaningful if the signal wraps around to the
beginning seamlessly - otherwise you have to use a window to reduce (but not eliminate) wrap-around
artifacts.

The best window is probably Kaiser-Bessel.  It takes a tuning parameter so you can select the properties
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 15, 2018, 03:30 pm
Can do bilinear transform by aurdino?
How can i find sample of it in arduino code?
Title: Re: Question about magnitude
Post by: MarkT on Jun 15, 2018, 03:43 pm
Can do bilinear transform by aurdino?
How can i find sample of it in arduino code?
No, you do this as filter design time - the easiest way to design digital filters
is to find an online calculator, but normally they only exist for low-pass, band-pass
or high-pass, not a specific weighting function.

So the idea is find an analog A-weighting filter, put its poles and zeroes through
the bilinear transform to get Z-transform poles and zeroes, and feed that into
a digital filter tool.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 17, 2018, 09:03 pm
Hello peiter
I do that formula but didnt convert magnitude to voltage
Title: Re: Question about magnitude
Post by: PieterP on Jun 17, 2018, 09:06 pm
There's nothing I can do without more information. Post your exact code.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 19, 2018, 06:01 pm
Hello
I use this code for anlaize a sin wave with 300 Hz
Why the bin is not correct cuz when i want to calculate freqency  by this equiption fs*bin/N
Frequency is not correct
19200*20/64=6000 Hz but my freqency sin wave was 300Hz!!!


Code: [Select]


#define LIN_OUT 1
 #define FFT_N 64
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#include <FFT.h> // include the library


void setup() {
  Serial.begin(115200); // output on the serial port
  //19200khz
  sbi(ADCSRA, ADPS2);
  sbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);

}

void loop() { 
  int i,k;
  float f1=300; 
   //the two input frequencies (bin values)
  for (i = 0 ; i < FFT_N ; i++)
  {
    k=1000*sin(2*PI*f1*i/FFT_N);
    fft_input[2*i] = k; // put real data into even bins
    //Serial.println(k);
    fft_input[2*i+1] = 0; // set odd bins to 0
  }
  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");
  while(1); //wait here
}




And output

Code: [Select]


bin  amplitude
0   2
1   0
2   0
3   0
4   2
5   0
6   0
7   0
8   1
9   0
10   0
11   0
12   2
13   0
14   0
15   0
16   0
17   0
18   0
19   0
20   500
21   0
22   0
23   0
24   1
25   0
26   0
27   0
28   0
29   0
30   0
31   0
Done

Title: Re: Question about magnitude
Post by: PieterP on Jun 19, 2018, 06:09 pm
The result is correct, your original sine wave is not. You have to divide by the sampling rate, not by the number of samples.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 19, 2018, 06:17 pm
Please write equiption of it for calculate frequency


Where sin wave is not corrected?
Title: Re: Question about magnitude
Post by: PieterP on Jun 19, 2018, 06:20 pm
It's in the MATLAB script already.

In Arduino code:
Code: [Select]
int k = 1000 * sin(2*PI*f1*i/19200.0);
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 19, 2018, 06:27 pm
Thanks a lot it is ok

Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 19, 2018, 07:49 pm
Hello again
I change code to recive signal by a microphone sensor. It show amplitude and frequncy but i dont know why when i make a tone for example 1000 hz arduino show max amplitude in 525 hz or when send a tone with 2000 hz it show max amplitude in 975 Hz or with tone 8000 ,it show 3975
Do i must freqency multiply 2?

Code: [Select]


#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#include <FHT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
    //19200khz
  sbi(ADCSRA, ADPS2);
  sbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);
}

void loop() {
 // { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    sei();
    Serial.println("start");
    for (byte i = 0 ; i < FHT_N/2 ; i++) {
   Serial.print(i*19200/FHT_N); Serial.print("/");
      Serial.println(fht_log_out[i]); // send out the data
    }
 // } while(1);
}

Title: Re: Question about magnitude
Post by: PieterP on Jun 19, 2018, 09:30 pm
Your ADC configuration is all wrong. You're sampling at the wrong rate, because you reset the ADC configuration after the first measurement. Try this:
Code: [Select]
#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#include <FHT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  ADCSRB = 0; // Free running mode
  ADMUX = (DEFAULT << 6) | 0; // A0
  sbi(ADCSRA, ADEN); // Enable ADC
  sbi(ADCSRA, ADATE); // Auto trigger
  sbi(ADCSRA, ADSC); // Start conversion
  // 19.231 kHz
  sbi(ADCSRA, ADPS2);
  sbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);
}

void loop() {
  do {
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while (!(ADCSRA & _BV(ADIF))); // wait for adc to be ready
      sbi(ADCSRA, ADIF); // Clear interrupt flag
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    sei();
    for (uint8_t i = 0 ; i < FHT_N / 2 ; i++) {
      Serial.print(i * 19231UL / FHT_N); Serial.print(" Hz:\t");
      Serial.println(fht_log_out[i]); // send out the data
    }
  } while(0);
  while(1);
}


By the way, you need a strong anti-aliasing filter, especially at these low sampling rates.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 19, 2018, 10:11 pm
Filter For what range frequency to remve?
What is UL in calculate frequncy that you wrote?
Title: Re: Question about magnitude
Post by: PieterP on Jun 19, 2018, 10:19 pm
Everything above half the sampling rate must be attenuated as much as possible. Read up on the Nyquist-Shannon theorem.

UL means unsigned long. An int would overflow.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 20, 2018, 08:10 pm
Hello
Peiter thanks for your help
Your code was correct
Now i could calculated correction factor for in per bin and convert dB to dBA

Code: [Select]


0 Hz: AMP:0.65 C:0.00 AMP(A):0.00
75 Hz: AMP:0.60 C:0.00 AMP(A):0.00
150 Hz: AMP:0.20 C:0.04 AMP(A):0.01
225 Hz: AMP:0.12 C:0.11 AMP(A):0.01
300 Hz: AMP:0.10 C:0.20 AMP(A):0.02
375 Hz: AMP:0.12 C:0.30 AMP(A):0.04
450 Hz: AMP:0.12 C:0.40 AMP(A):0.05
525 Hz: AMP:0.00 C:0.51 AMP(A):0.00
600 Hz: AMP:0.09 C:0.61 AMP(A):0.05
676 Hz: AMP:0.11 C:0.70 AMP(A):0.08
751 Hz: AMP:0.06 C:0.78 AMP(A):0.05
826 Hz: AMP:0.11 C:0.86 AMP(A):0.09
901 Hz: AMP:0.00 C:0.92 AMP(A):0.00
976 Hz: AMP:0.36 C:0.98 AMP(A):0.36
1051 Hz: AMP:0.41 C:1.03 AMP(A):0.42
1126 Hz: AMP:0.35 C:1.08 AMP(A):0.38
1201 Hz: AMP:0.11 C:1.12 AMP(A):0.13
1277 Hz: AMP:0.13 C:1.15 AMP(A):0.15
1352 Hz: AMP:0.09 C:1.18 AMP(A):0.10
1427 Hz: AMP:0.15 C:1.21 AMP(A):0.18
1502 Hz: AMP:0.14 C:1.23 AMP(A):0.17
1577 Hz: AMP:0.11 C:1.25 AMP(A):0.14
1652 Hz: AMP:0.14 C:1.27 AMP(A):0.17
1727 Hz: AMP:0.05 C:1.28 AMP(A):0.07
1802 Hz: AMP:0.10 C:1.29 AMP(A):0.13
1878 Hz: AMP:0.09 C:1.31 AMP(A):0.11
1953 Hz: AMP:0.08 C:1.31 AMP(A):0.10
2028 Hz: AMP:0.10 C:1.32 AMP(A):0.13
2103 Hz: AMP:0.03 C:1.33 AMP(A):0.03
2178 Hz: AMP:0.08 C:1.33 AMP(A):0.11
2253 Hz: AMP:0.12 C:1.34 AMP(A):0.16
2328 Hz: AMP:0.00 C:1.34 AMP(A):0.00
2403 Hz: AMP:0.14 C:1.34 AMP(A):0.19
2478 Hz: AMP:0.03 C:1.34 AMP(A):0.03
2554 Hz: AMP:0.06 C:1.34 AMP(A):0.08
2629 Hz: AMP:0.06 C:1.34 AMP(A):0.08
2704 Hz: AMP:0.00 C:1.34 AMP(A):0.00
2779 Hz: AMP:0.06 C:1.34 AMP(A):0.08
2854 Hz: AMP:0.00 C:1.33 AMP(A):0.00
2929 Hz: AMP:0.11 C:1.33 AMP(A):0.15
3004 Hz: AMP:0.05 C:1.33 AMP(A):0.07
3079 Hz: AMP:0.15 C:1.32 AMP(A):0.20
3155 Hz: AMP:0.12 C:1.32 AMP(A):0.16
3230 Hz: AMP:0.10 C:1.31 AMP(A):0.13
3305 Hz: AMP:0.00 C:1.31 AMP(A):0.00
3380 Hz: AMP:0.09 C:1.30 AMP(A):0.11
3455 Hz: AMP:0.06 C:1.30 AMP(A):0.08
3530 Hz: AMP:0.11 C:1.29 AMP(A):0.15
3605 Hz: AMP:0.05 C:1.29 AMP(A):0.07
3680 Hz: AMP:0.03 C:1.28 AMP(A):0.03
3756 Hz: AMP:0.10 C:1.27 AMP(A):0.12
3831 Hz: AMP:0.00 C:1.27 AMP(A):0.00
3906 Hz: AMP:0.10 C:1.26 AMP(A):0.13
3981 Hz: AMP:0.06 C:1.25 AMP(A):0.08
4056 Hz: AMP:0.10 C:1.24 AMP(A):0.13
4131 Hz: AMP:0.08 C:1.24 AMP(A):0.10
4206 Hz: AMP:0.09 C:1.23 AMP(A):0.11
4281 Hz: AMP:0.06 C:1.22 AMP(A):0.07
4357 Hz: AMP:0.08 C:1.21 AMP(A):0.10
4432 Hz: AMP:0.10 C:1.20 AMP(A):0.12
4507 Hz: AMP:0.08 C:1.19 AMP(A):0.09
4582 Hz: AMP:0.11 C:1.19 AMP(A):0.13
4657 Hz: AMP:0.00 C:1.18 AMP(A):0.00
4732 Hz: AMP:0.06 C:1.17 AMP(A):0.07
4807 Hz: AMP:0.00 C:1.16 AMP(A):0.00
4882 Hz: AMP:0.06 C:1.15 AMP(A):0.07
4957 Hz: AMP:0.00 C:1.14 AMP(A):0.00
5033 Hz: AMP:0.00 C:1.13 AMP(A):0.00
5108 Hz: AMP:0.05 C:1.12 AMP(A):0.06
5183 Hz: AMP:0.10 C:1.11 AMP(A):0.11
5258 Hz: AMP:0.14 C:1.10 AMP(A):0.16
5333 Hz: AMP:0.00 C:1.10 AMP(A):0.00
5408 Hz: AMP:0.03 C:1.09 AMP(A):0.03
5483 Hz: AMP:0.10 C:1.08 AMP(A):0.10
5558 Hz: AMP:0.08 C:1.07 AMP(A):0.08
5634 Hz: AMP:0.11 C:1.06 AMP(A):0.11
5709 Hz: AMP:0.08 C:1.05 AMP(A):0.08
5784 Hz: AMP:0.14 C:1.04 AMP(A):0.14
5859 Hz: AMP:0.06 C:1.03 AMP(A):0.06
5934 Hz: AMP:0.09 C:1.02 AMP(A):0.09
6009 Hz: AMP:0.00 C:1.01 AMP(A):0.00
6084 Hz: AMP:0.10 C:1.00 AMP(A):0.10
6159 Hz: AMP:0.00 C:0.99 AMP(A):0.00
6235 Hz: AMP:0.03 C:0.98 AMP(A):0.03
6310 Hz: AMP:0.06 C:0.97 AMP(A):0.06
6385 Hz: AMP:0.00 C:0.96 AMP(A):0.00
6460 Hz: AMP:0.03 C:0.95 AMP(A):0.02
6535 Hz: AMP:0.06 C:0.94 AMP(A):0.06
6610 Hz: AMP:0.05 C:0.94 AMP(A):0.05
6685 Hz: AMP:0.05 C:0.93 AMP(A):0.05
6760 Hz: AMP:0.14 C:0.92 AMP(A):0.12
6836 Hz: AMP:0.10 C:0.91 AMP(A):0.09
6911 Hz: AMP:0.12 C:0.90 AMP(A):0.11
6986 Hz: AMP:0.06 C:0.89 AMP(A):0.05
7061 Hz: AMP:0.08 C:0.88 AMP(A):0.07
7136 Hz: AMP:0.03 C:0.87 AMP(A):0.02
7211 Hz: AMP:0.10 C:0.86 AMP(A):0.09
7286 Hz: AMP:0.06 C:0.85 AMP(A):0.05
7361 Hz: AMP:0.09 C:0.84 AMP(A):0.07
7436 Hz: AMP:0.00 C:0.83 AMP(A):0.00
7512 Hz: AMP:0.03 C:0.83 AMP(A):0.02
7587 Hz: AMP:0.00 C:0.82 AMP(A):0.00
7662 Hz: AMP:0.05 C:0.81 AMP(A):0.04
7737 Hz: AMP:0.03 C:0.80 AMP(A):0.02
7812 Hz: AMP:0.11 C:0.79 AMP(A):0.08
7887 Hz: AMP:0.05 C:0.78 AMP(A):0.04
7962 Hz: AMP:0.08 C:0.77 AMP(A):0.06
8037 Hz: AMP:0.05 C:0.76 AMP(A):0.04
8113 Hz: AMP:0.00 C:0.76 AMP(A):0.00
8188 Hz: AMP:0.08 C:0.75 AMP(A):0.06
8263 Hz: AMP:0.03 C:0.74 AMP(A):0.02
8338 Hz: AMP:0.00 C:0.73 AMP(A):0.00
8413 Hz: AMP:0.00 C:0.72 AMP(A):0.00
8488 Hz: AMP:0.05 C:0.71 AMP(A):0.04
8563 Hz: AMP:0.00 C:0.71 AMP(A):0.00
8638 Hz: AMP:0.00 C:0.70 AMP(A):0.00
8714 Hz: AMP:0.06 C:0.69 AMP(A):0.04
8789 Hz: AMP:0.06 C:0.68 AMP(A):0.04
8864 Hz: AMP:0.06 C:0.67 AMP(A):0.04
8939 Hz: AMP:0.10 C:0.67 AMP(A):0.07
9014 Hz: AMP:0.09 C:0.66 AMP(A):0.06
9089 Hz: AMP:0.11 C:0.65 AMP(A):0.07
9164 Hz: AMP:0.10 C:0.64 AMP(A):0.06
9239 Hz: AMP:0.06 C:0.64 AMP(A):0.04
9315 Hz: AMP:0.06 C:0.63 AMP(A):0.04
9390 Hz: AMP:0.06 C:0.62 AMP(A):0.04
9465 Hz: AMP:0.00 C:0.61 AMP(A):0.00
9540 Hz: AMP:0.06 C:0.61 AMP(A):0.04



 :(
Title: Re: Question about magnitude
Post by: PieterP on Jun 20, 2018, 08:31 pm
What is your question?
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 20, 2018, 08:52 pm
I want to know in th source code ,amplitude that caculated is in range 0 to 1023 or Not
Title: Re: Question about magnitude
Post by: PieterP on Jun 20, 2018, 09:11 pm
No. It's in the documentation (http://wiki.openmusiclabs.com/wiki/FHTFunctions).
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 20, 2018, 10:02 pm
Why in the sin wave example code if amplitude multiplay 2 it become equal peak amplitude .
Do in this code if amplitude *2 it become peak amp?
Title: Re: Question about magnitude
Post by: PieterP on Jun 20, 2018, 10:52 pm
I don't understand your question.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 22, 2018, 02:24 pm
Hello pieter
I change code to this and use 3.3 V of ardino pin

Code: [Select]

#define LIN_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#include <FHT.h> // include the library
const double a12200 = pow(12200,2);
const double a206 = pow(20.6,2);
const double a1077 = pow(107.7,2);
const double a7379 = pow(737.9,2);
const double CORR = 0;

const int GAIN = 1;

int f;
double RA,CF,f2,f4,C,ADCNUM;


void setup() {
  Serial.begin(115200); // use the serial port
  ADCSRB = 0; // Free running mode
  ADMUX = (DEFAULT << 6) | 0; // A0
  sbi(ADCSRA, ADEN); // Enable ADC
  sbi(ADCSRA, ADATE); // Auto trigger
  sbi(ADCSRA, ADSC); // Start conversion
  // 19.231 kHz
  sbi(ADCSRA, ADPS2);
  sbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);
}

void loop() {
 do {
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while (!(ADCSRA & _BV(ADIF))); // wait for adc to be ready
      sbi(ADCSRA, ADIF); // Clear interrupt flag
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put re3l data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_lin(); // take the output of the fht
    sei();
    for (uint8_t i = 0 ; i < FHT_N / 2 ; i++) {
      f=i * 19231UL / FHT_N;
      Serial.print(f);
      Serial.print(" HZ:");
      Serial.println(fht_lin_out[i]); // send out the data
    }
  } while(0);
  while(1);
}




Result is for frequency 1051 Hz is 2928

Code: [Select]


0 HZ:16000
75 HZ:7936
150 HZ:23
225 HZ:36
300 HZ:6
375 HZ:11
450 HZ:9
525 HZ:30
600 HZ:20
676 HZ:30
751 HZ:4
826 HZ:19
901 HZ:59
976 HZ:1664
1051 HZ:2928
1126 HZ:1296
1201 HZ:29
1277 HZ:20
1352 HZ:17
1427 HZ:31
1502 HZ:10
1577 HZ:21
1652 HZ:20
1727 HZ:24
1802 HZ:11
1878 HZ:14
1953 HZ:46
2028 HZ:780
2103 HZ:1224
2178 HZ:468
2253 HZ:23
2328 HZ:17
2403 HZ:7
2478 HZ:5
2554 HZ:12
2629 HZ:13
2704 HZ:19
2779 HZ:17
2854 HZ:12
2929 HZ:15
3004 HZ:13
3079 HZ:81
3155 HZ:130
3230 HZ:54
3305 HZ:12
3380 HZ:26
3455 HZ:20
3530 HZ:38
3605 HZ:17
3680 HZ:36
3756 HZ:32
3831 HZ:20
3906 HZ:13
3981 HZ:4
4056 HZ:55
4131 HZ:370
4206 HZ:468
4281 HZ:135
4357 HZ:26
4432 HZ:16
4507 HZ:16
4582 HZ:7
4657 HZ:26
4732 HZ:27
4807 HZ:13
4882 HZ:3
4957 HZ:12
5033 HZ:8
5108 HZ:28
5183 HZ:178
5258 HZ:197
5333 HZ:46
5408 HZ:8
5483 HZ:9
5558 HZ:26
5634 HZ:46
5709 HZ:17
5784 HZ:9
5859 HZ:26
5934 HZ:6
6009 HZ:9
6084 HZ:1
6159 HZ:20
6235 HZ:72
6310 HZ:74
6385 HZ:10
6460 HZ:13
6535 HZ:11
6610 HZ:36
6685 HZ:25
6760 HZ:35
6836 HZ:20
6911 HZ:29
6986 HZ:6
7061 HZ:17
7136 HZ:13
7211 HZ:19
7286 HZ:59
7361 HZ:52
7436 HZ:2
7512 HZ:17
7587 HZ:7
7662 HZ:12
7737 HZ:44
7812 HZ:42
7887 HZ:6
7962 HZ:6
8037 HZ:5
8113 HZ:8
8188 HZ:8
8263 HZ:20
8338 HZ:44
8413 HZ:29
8488 HZ:1
8563 HZ:3
8638 HZ:9
8714 HZ:44
8789 HZ:51
8864 HZ:18
8939 HZ:10
9014 HZ:14
9089 HZ:12
9164 HZ:8
9239 HZ:10
9315 HZ:31
9390 HZ:36
9465 HZ:17
9540 HZ:9




I dont know how this number change to voltage
Please help me and say what is furmula for do it and write it for me


Title: Re: Question about magnitude
Post by: PieterP on Jun 22, 2018, 03:23 pm
I dont know how this number change to voltage
Please help me and say what is furmula for do it and write it for me
No. I cannot keep on holding your hand like this. I already gave you the formulas you need, and the documentation of the FHT library tells you what the different functions do to the output, how to interpret it, and the mathematical formulas used to calculate these results.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 22, 2018, 06:58 pm
Why k value in above code is biger than 1024?
Code: [Select]

fht_input[i] = k; // put real data into bins
Title: Re: Question about magnitude
Post by: PieterP on Jun 22, 2018, 07:05 pm
Write down mathematically what happens with k, then you know why.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 22, 2018, 08:44 pm
Write down mathematically what happens with k, then you know why.
My math is bad
I wish to have good math
I have to leave this project after one month effort .it doesnt have any thrive
Title: Re: Question about magnitude
Post by: PieterP on Jun 22, 2018, 08:47 pm
Whining about it won't help. Trying will.
Title: Re: Question about magnitude
Post by: Noisecontrol on Jun 23, 2018, 04:22 am
I think k is 16 bit thus range of it is 0 to 65536
Thus per 1 ADC  is equal voltage/65536
For example for 5 volt is equal 0.000076 volt
Is it true?
Title: Re: Question about magnitude
Post by: Noisecontrol on Aug 05, 2018, 08:27 pm
Hello
Finally make sound level meter after 4 month
It show dBA
Leq
Sone
Phone
Ta
NRR
O