Frequency & amplitude - c++

I have a data (file) which contains 2 columns:
Seconds, Volts
0, -0.4238353
2.476346E-08, -0.001119718
4.952693E-08, -0.006520569
(..., thousands of similar entries in file)
4.516856E-05, -0.0002089292
How to calculate the frequency of the highest amplitude wave ? (Each wave is of fixed frequency).
Is there any difference between calculating frequency of seconds and amplitude vs. seconds and volts? Because in Frequency & amplitue there is seconds and amplitude example solved, so it might help in my case.

Your data is in the time domain, the question is about the frequency domain. Your course should have told you how the two are related. In two words: Fourier Transform. In practical programming, we use the FFT: Fast Fourier Tranform. If the input is a fixed frequency sine wave, your FFT output will have one hump. Model that as a parabola and find the peak of the parabola. (Finding the highest amplitude in the FFT is about 10 times less accurate)
The link you give is horrible; I've downvoted the nonsense answer there. In your example, time starts at t=0 and the solution given would do a 1/0.

Related

Determining total time for square wave frequency to increase from f1 to f2, with a linear rate of change

I'm trying to determine the total length of time that a square wave takes to linearly increase from frequency 1 to frequency 2.
Question 1:
If I start at, for example:
f1=0hz
f2=1000hz
step increase per cycle is 10hz
What is the total time that elapses for this linear increase of frequency to take place?
Question 2:
If I have:
f1=0hz
f2=1000hz
and I want the increase to take place over 5 seconds, for example,
how would I calculate the rate of interval increase per cycle to achieve this.
*(basically the inverse of question 1)
This is for a hobby project to make a faster stepper motor driver profile, for programming an Atmel microcontroller (in C [well, Atmel's Arduino "C"]).
Any thoughts would be helpful. Thank you in advance!
I found this sine wave that slowly ramps up frequency from f1 to f2 for a given time but this answers a slightly different question - and is for a Sine wave.
#T Brunelle,
Q1. Your time for a general frequency would be
t=(1/(delta f))*ln(f2/f1)
where f1 and f2 are start and end frequencies and (delta f) is the change per cycle. Obviously this won't work if f1 is 0, but then a zero-frequency oscillation doesn't make sense either.
This comes from solving (in practice, just multiplying together and using the chain rule):
df/d(phase)=(delta f)
and
d(phase)/dt=f
where "phase" increases by 1 each cycle.
Q2. Just invert the formula in Q1.
This assumes that the change is linear PER CYCLE (rather than PER TIME, as was in your linked page). In your case it is also independent of the waveform shape.

Predict smearing of FFT

After applying a Fourier transform to a signal, the energy of a single sine wave is often spread out across multiple bins (aka smearing). Have a look at the right side of the image below for an illustration:
I want to extract a list of peak frequencies. Just finding the highest bin is easy. But after that smearing becomes a problem.
I would like to have a heuristic which tells me if the magnitude of a specific bin is possibly the result of smearing or if there has to be another peak frequency in order to explain the signal. (It is better if I miss some than have false positives)
My naive approach would be to just calculate a few thousand examples and take the maximum of these to get an envelope curve so that any smearing is likely below that envelope.
But is there a better way to do this?
The FFT result of any rectangularly windowed pure unmodulated sinusoid is a Sinc function. This Sinc (sin(pix)/(pix)) function is only zero for all bins except one (at the peak magnitude) when the frequency of the input sinusoid has exactly an integer number of periods in the FFT width.
For all other frequencies that are not at the exact center of an FFT result bin, if you know that exact frequency and magnitude (which won't be in any single FFT bin), you can calculate all the other bins by sampling the Sinc function.
And, of course, if the input sinusoid isn't perfectly pure, but modulated in any way (amplitude, frequency or phase), this modulation will produce various sidebands in the FFT result as well.

Compute frequency of sinusoidal signal, c++

i have a sinusoidal-like shaped signal,and i would like to compute the frequency.
I tried to implement something but looks very difficult, any idea?
So far i have a vector with timestep and value, how can i get the frequency from this?
thank you
If the input signal is a perfect sinusoid, you can calculate the frequency using the time between positive 0 crossings. Find 2 consecutive instances where the signal goes from negative to positive and measure the time between, then invert this number to convert from period to frequency. Note this is only as accurate as your sample interval and it does not account for any potential aliasing.
You could try auto correlating the signal. An auto correlation can be rapidly calculated by following these steps:
Perform FFT of the audio.
Multiply each complex value with its complex conjugate.
Perform the inverse FFT of the audio.
The left most peak will always be the highest (as the signal always correlates best with itself). The second highest peak, however, can be used to calculate the sinusoid's frequency.
For example if the second peak occurs at an offset (lag) of 50 points and the sample rate is 16kHz and the window is 1 second then the end frequency is 16000 / 50 or 320Hz. You can even use interpolation to get a more accurate estimation of the peak position and thus a more accurate sinusoid frequency. This method is quite intense but is very good for estimating the frequency after significant amounts of noise have been added!

Generating a square wave for DFT

I'm working on an assignment to perform a 200 point DFT at a sampling frequency of 20kHz on a square wave of frequency 500Hz whose amplitude alternates between 0 and 20.
I'm using C++ and I have figured how to code the DFT equation, my problem is I'm having trouble representing the square wave in code using a for loop.
What I'm really still confused about is how many cycles of this square wave will be in my 200 point sample.
Thanks
The period of the square wave is 20000/500=40 points, so you'll have exactly 5 periods of the square wave in your 200-point sample (200/40=5).
One cycle of your square wave will take 1/500 seconds. Each sample will be 1/20000 seconds. A simple division should tell you how many samples each square wave will be.
Another division will tell you how many of those waves will fit in your 200 point window.
If your sampling frequency is 20,000 Hz and you have a square wave of frequency 500 Hz, this basically means that you will have 500 cycles of your wave per second, which means you will have 500 cycles in every 20,000 samples. This means that each wave cycle requires 40 samples (or points), so if you have 200 points that means you should have 5 square wave cycles within your DFT.
You can make sure you do your calculation right by including the units in your calculation. So the period has the dimension time, Hertz has the dimension of 1.0/time and samples is dimensionless.
Programatically, you can do this with boost.units. It will check your units at compile time and give you an error if you make a mistake.
It will also stop your user from entering the wrong units into your code. For example, by entering 20 instead of 20000 for the frequency (thinking you were measuring in kHz)
Your interface will then be something like
using namespace boost::units;
set_period(quantity<si::time> period);
The user will have to enter the time in seconds,
set_period(5*si::seconds)

Parameters to improve a music frequency analyzer

I'm using a FFT on audio data to output an analyzer, like you'd see in Winamp or Windows Media Player. However the output doesn't look that great. I'm plotting using a logarithmic scale and I average the linear results from the FFT into the corresponding logarithmic bins. As an example, I'm using bins like:
16k,8k,4k,2k,1k,500,250,125,62,31,15 [hz]
Then I plot the magnitude (dB) against frequency [hz]. The graph definitely 'reacts' to the music, and I can see the response of a drum sample or a high pitched voice. But the graph is very 'saturated' close to the lower frequencies, and overall doesn't look much like what you see in applications, which tend to be more evenly distributed. I feel that apps that display visual output tend to do different things to the data to make it look better.
What things could I do to the data to make it look more like the typical music player app?
Some useful information:
I downsample to single channel, 32kHz, and specify a time window of 35ms. That means the FFT gets ~1100 points. I vary these values to experiment (ie tried 16kHz, and increasing/decreasing interval length) but I get similar results.
With an FFT of 1100 points, you probably aren't able to capture the low frequencies with a lot of frequency resolution.
Think about it, 30 Hz corresponds to a period of 33ms, which at 32kHz is roughly 1000 samples. So you'll only be able to capture about 1 period in this time.
Thus, you'll need a longer FFT window to capture those low frequencies with sharp frequency resolution.
You'll likely need a time window of 4000 samples or more to start getting noticeably more frequency resolution at the low frequencies. This will be fine too, since you'll still get about 8-10 spectrum updates per second.
One option too, if you want very fast updates for the high frequency bins but good frequency resolution at the low frequencies, is to update the high frequency bins more quickly (such as with the windows you're currently using) but compute the low frequency bins less often (and with larger windows necessary for the good freq. resolution.)
I think a lot of these applications have variable FFT bins.
What you could do is start with very wide evenly spaced FFT bins like you have and then keep track of the number of elements that are placed in each FFT bin. If some of the bins are not used significantly at all (usually the higher frequencies) then widen those bins so that they are larger (and thus have more frequency entries) and shring the low frequency bins.
I have worked on projects were we just spend a lot of time tuning bins for specific input sources but it is much nicer to have the software adjust in real time.
A typical visualizer would use constant-Q bandpass filters, not a single FFT.
You could emulate a set of constant-Q bandpass filters by multiplying the FFT results by a set of constant-Q filter responses in the frequency domain, then sum. For low frequencies, you should use an FFT longer than the significant impulse response of the lowest frequency filter. For high frequencies, you can use shorter FFTs for better responsiveness. You can slide any length FFTs along at any desired update rate by overlapping (re-using) data, or you might consider interpolation. You might also want to pre-window each FFT to reduce "spectral leakage" between frequency bands.