0
$\begingroup$

I want to control the amplitude of a signal I'm creating from a user drawn spectrum by scaling the magnitude values in the frequency domain. Here is my scenario.

  • Sample rate $F_s= 44100\textrm{ Hz}$
  • FFT size $NFFT = 512$
  • Desired waveform frequency: $86.1328125\textrm{ Hz}$ ($44100/512$ so a single cycle)

My user input screen has the magnitudes presented like a bar chart and they are all stored as values with a range of $0.0$ to $1.0$.

How do I scale these in the frequency domain so that the output signal is a $0\textrm{ dB}$ signal?

$\endgroup$
  • $\begingroup$ Can you please clarify your question? Are you trying to understand what you should scale a "free-hand" sketch of frequency domain coefficients so that the output signal has a p-p amplitude of 1? That would depend on the scaling factor effected by your FFT library too $\endgroup$ – A_A Jun 30 '17 at 1:40
1
$\begingroup$

You can use Parseval's theorem for DFT. $$ \sum_{n=0}^{N-1} |x[n]|^2 = \frac{1}{N} \sum_{к=0}^{N-1} |X[n]|^2 $$ Where $$x[n]$$ - n-th signal sample, $$X[n]$$ - n-th value of the DFT of the signal

$\endgroup$
  • $\begingroup$ Thanks Andrei. I've encountered this a lot in trying to solve this but I'm not certain I understand how to apply the right hand side. Is it correct to apply it to the the spectrum in rectangular form? I think I understand the basic concept which is that frequency domain spectrum is equivalent to the output signal. I just don't understand the mathematic notation enough to convert it to c++. $\endgroup$ – cixelsyd Jun 29 '17 at 19:37
  • $\begingroup$ Matlab code:mathworks.com/matlabcentral/newsreader/view_thread/… $\endgroup$ – Andrei Keino Jun 30 '17 at 2:38
  • $\begingroup$ Math notation: en.wikipedia.org/wiki/Summation $\endgroup$ – Andrei Keino Jun 30 '17 at 3:30
1
$\begingroup$
% Parseval's theorem in matlab
close all;
format long;
Fs=40;f=4;Ts=1/Fs;=2;t=0:Ts:T-Ts;N=length(t);
x=2*cos(2*pi*f*t);
fx=fft(x);
figure,
subplot(1,2,1), area(t,abs(x.^2)),title(' Time Domain');
subplot(1,2,2),area(abs(fx)), title(' Frequency Domain');

E1_timedomain=sum(abs(x.^2))
E1_frequdomain=sum(abs(fx.^2))/N

Energy_Of_Signal = sum(x.^2)
Energy_Of_Signal_DFT = sum(abs(fx).^2) / length(fx)

// Parseval's theorem in C++ - pesudocode    

vector<double> x; // signal vector
GetSignal(x); // acquire signal
vector<Complex> fx; // DFT of signal vector
GetDFT(x, fx); // get the DFT of signal
double sumX = 0, sumFx = 0;
assert(x.size() == fx.size()); // length of x and fx are equal
for(int i = 0; i < x.size(); i++)
{
    sumX += x[i] * x[i];
    sumFx += fx[i].real() * fx[i].real() + fx[i].imag() * fx[i].imag(); // or sumFx += fx[i].abs() * fx[i].abs();
}
assert(sumX == sumFx / (double)fx.size()); // Parseval's theorem

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.