I am using Goertzel algorithm to get the amplitude of a certain frequency.
I am trying now to get the phase from it, and I don't know how.
Can some one explain, and show me how to get the phase of a certain-f from this code?
Also, I am using it to 16khz, with sample rate 44.1. What's the smallest length of samples that I can run it on?
double AlgorithmGoertzel( int16_t *sample,int sampleRate, double Freq, int len )
{
double realW = 2.0 * cos(2.0 * M_PI * Freq / sampleRate);
double imagW = 2.0 * sin(2.0 * M_PI * Freq / sampleRate);
double d1 = 0;
double d2 = 0;
double y;
for (int i = 0; i < len; i++) {
y=(double)(signed short)sample[i] +realW * d1 - d2;
d2 = d1;
d1 = y;
}
double rR = 0.5 * realW *d1-d2;
double rI = 0.5 * imagW *d1-d2;
return (sqrt(pow(rR, 2)+pow(rI,2)))/len;
}
Do a rectangular to polar conversion. That will give you phase and magnitude.
magnitude = sqrt ((Vreal * Vreal) + (Vimag * Vimag))
phase = atan2 (Vimag, Vreal)
I don't think the algorithm consists of multiplying the sequence by a constant, but by the complex signal exp(n*i*2pi*freq/samplerate); 0<=n<=length, and getting the average magnitude (or power of the signal).
As the complex output is R*exp(i theta), R gives the power at the given frequency and theta gives the phase. (theta == atan2 ( imag, real))
The number of samples you need to feed a Goertzel filter will be inversely proportional to your desired or required filter bandwidth. A Goertzel provides a Sinc shaped bandpass filter, with the main lobe width proportional to 2*Fs/N.
If you use a complex Goertzel, the resulting phase will be relative to some point in the filter's data window. You may thus have to calculate an offset to get phase relative to some other reference point in time.
Related
Given N points on a plane (of form (x, y)), find the circle that have maximum number of points on it ?
P.S. : The point should lie on the circumference of the circle.
What is the most efficient algorithm to solve this problem and how does it work? Which Data structures would you use to solve this problem. This was asked in one of the FANG coding interviews.
As a starting point, the simple O(N3) solution is to find the circle corresponding to each unique triple of points, while counting the number of occurrences of each circle you find.
If a circle has N points on it, then you will find it N-choose-3 times, so the circle you find most often is the one with the most points on it.
There are complications in any actual implementation, but they are different complications depending on how your points are represented and whether you want exact or approximate answers.
Case 1 : Hough Transform
In computer vision problem solving we often search for circles amongst edge information. This problem is characterised by having many data points, possibly originating from many different circles in the presence of a great deal of noise.
The usual approach to solving this problem is the Hough Transform https://en.wikipedia.org/wiki/Circle_Hough_Transform. The basic idea is to sum the evidence for the circles which can pass through each point (x, y).
We create an integer array called Hough [a, b, r] which parametrises all the possible circles that can pass through your point (x,y). This is equivalent to drawing a circle of radius 1 in the r=1 plane centred on (x,y); a circle of radius 2 in the r=2 plane centred on (x,y) etc.
Each time a circle is drawn through a point in [a, b, r] we add 1 to the corresponding value. Some points accumulate a lot of evidence. These points correspond to the circles of interest.
Image from cis.rit.edu illustrates what happens in one of the r-planes.
Doing this for each point (x,y) will generate evidence towards each of the points in [a,b,r] corresponding to the circle you seek. So just scan this array to find the point with the maximum evidence. That is your circle.
Example of Hough Transform
Knowing the radius of the circle reduces this from an O(n^3) problem to a O(n^2) problem as only one plane needs to be constructed and scanned. I have also had good results plotting the radii in a log space to give a (less accurate) O(n^2 log n) algorithm.
Case 2 : Circle Fitting
If the points are known to lie near the boundary of a single circle, and/or if the points are not very numerous and/or else we are very sure that there is very little noise then the Hough transform is a poor solution as it is computationally intensive, memory hungry and because of the raster nature of the accumulator array possibly not very accurate.
In this case we may want to fit a circle by analogy to line fitting techniques that use linear regression. A discussion of circle fitting techniques can be found in https://pdfs.semanticscholar.org/faac/44067f04abf10af7dd583fca0c35c5937f95.pdf.
A (rather simple minded) implementation of this algorithm is presented below.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
float x;
float y;
} point;
/*
* Function using a modified least squares approach to circle fitting.
*
* Reference :
*
* Umbach, D. and Jones, K. N. "A few methods for fitting circles to data",
* IEEE Trans Instrumentation and Measurement
* vol XX(Y) 2000
*
* https://pdfs.semanticscholar.org/faac/44067f04abf10af7dd583fca0c35c5937f95.pdf
*
* NOTES
*
* The code below has not been checked for numerical stability or conditioning.
*/
int circle_fit_MLS (point P[], int n, double *x_pos, double *y_pos, double *radius)
{
int i;
double sum_x=0.0, sum_y=0.0, sum_xx=0.0, sum_xy=0.0, sum_yy=0.0, sum_xyy=0.0, sum_yxx=0.0, sum_xxx=0.0, sum_yyy=0.0;
double A, B, C, D, E;
double x2, y2, xy, F, xdif, ydif;
for (i=0; i<n; i++)
{
sum_x += P[i].x;
sum_y += P[i].y;
x2 = P[i].x * P[i].x;
y2 = P[i].y * P[i].y;
xy = P[i].x * P[i].y;
sum_xx += x2;
sum_yy += y2;
sum_xy += xy;
sum_xyy += xy*P[i].y;
sum_yxx += P[i].y*x2;
sum_xxx += x2*P[i].x;
sum_yyy += y2*P[i].y;
}
A = n * sum_xx - sum_x * sum_x;
B = n * sum_xy - sum_x * sum_y;
C = n * sum_yy - sum_y * sum_y;
D = 0.5 * ( n * (sum_xyy + sum_xxx) - sum_x * sum_yy - sum_x * sum_xx);
E = 0.5 * ( n * (sum_yxx + sum_yyy) - sum_y * sum_xx - sum_y * sum_yy);
F = A*C - B*B;
*x_pos = (D*C - B*E) / F;
*y_pos = (A*E - B*D) / F;
*radius = 0;
for (i=0; i<n; i++)
{
xdif = P[i].x - *x_pos;
ydif = P[i].y - *y_pos;
*radius += sqrt(xdif * xdif + ydif * ydif);
}
*radius /= n;
return 0;
}
The main program below can be used for testing the code. Please post back any results/observations/suggestions for improvement in the comments.
int main()
{
point *P;
int n, i;
double xpos, ypos, radius;
printf ("Please enter the number of points \n> ");
scanf ("%d", &n);
P = malloc (n * sizeof(point));
for (i=0; i<n; i++)
{
printf ("x%d = ", i);
scanf ("%f", &P[i].x);
printf ("y%d = ", i);
scanf ("%f", &P[i].y);
}
circle_fit_MLS (P, n, &xpos, &ypos, &radius);
printf (" a = %f\n", xpos);
printf (" b = %f\n", ypos);
printf (" r = %f\n", radius);
}
I'm doing some work with triangulating the position of a receiver based on its distance to known points in space. I basically get a set of distances D[N] from the nearby broadcast points, and have a lookup table to give me the X, Y, and Z values for each. I need to find the X, Y, and Z points of my receiver.
I've seen that you can use trilateration to solve this problem in 2D cases, but it doesn't work for 3D. I would like to be able to use N points in order to improve accuracy, but I suppose I could also use the closest 4 points.
My issue is I have no idea how to programmatically solve the system of equations algebraically so it can be done in my program. I've seen a few solutions using things like Matlab, but I don't have the same tools.
This seems to solve the problem, if someone knows how to translate Matlab into a C language (I've never used Matlab): Determine the position of a point in 3D space given the distance to N points with known coordinates
Here is my solution in C++(should be easy to convert to plain C). It does not use any advanced algebra so it does not require any non-standard libraries. It works good when the number of points is rather big(the error gets smaller when the number of points grows), so it is better to pass all the points that you have to the solve method. It minimizes the sum of squared differences using sub-gradient descent.
const int ITER = 2000;
const double ALPHA = 2.0;
const double RATIO = 0.99;
double sqr(double a) {
return a * a;
}
struct Point {
double x;
double y;
double z;
Point(double _x=0.0, double _y=0.0, double _z=0.0): x(_x), y(_y), z(_z) {}
double dist(const Point &other) const {
return sqrt(sqr(x - other.x) + sqr(y - other.y) + sqr(z - other.z));
}
Point operator + (const Point& other) const {
return Point(x + other.x, y + other.y, z + other.z);
}
Point operator - (const Point& other) const {
return Point(x - other.x, y - other.y, z - other.z);
}
Point operator * (const double mul) const {
return Point(x * mul, y * mul, z * mul);
}
};
Point solve(const vector<Point>& given, const vector<double>& dist) {
Point res;
double alpha = ALPHA;
for (int iter = 0; iter < ITER; iter++) {
Point delta;
for (int i = 0; i < given.size(); i++) {
double d = res.dist(given[i]);
Point diff = (given[i] - res) * (alpha * (d - dist[i]) / max(dist[i], d));
delta = delta + diff;
}
delta = delta * (1.0 / given.size());
alpha *= RATIO;
res = res + delta;
}
return res;
}
Here is an answer for using Matlab (which is not what you are asking for), which uses the Nelder-Mead simplex optimization algorithm. Because you do not have access to Matlab, you could use R (freely available). The code above is easily translatable to R and in R you can use the Nelder-Mead algorithm (to replace 'fminsearch' using the neldermead package. For differences between R and Matlab (and Octave), see: http://cran.r-project.org/doc/contrib/R-and-octave.txt
function Ate=GetCoordinate(Atr,Dte)
% Atr = coordinates for known points
% Dte = distances for receiver to each row in Atr
% At5e = coordinate for receiver
[~,ii]=sort(Dte,'ascend');
Ate=mean(Atr(ii(1:4),:)); % (reasonable) start point
[Ate,~]=fminsearch(#(Ate) ED(Ate,Atr,Dte),Ate); % Uses Nelder-Mead simplex algorithm to find optimum
end
function d=ED(Ate,Atr,Dte) % calculates the sum of the squared difference between the measured distances and distances based on coordinate Ate (for receiver)
for k=1:size(Dte,1)
d(k,1)=sqrt((Atr(k,:)-Ate)*(Atr(k,:)-Ate)'); % Euclidean distance
end
d=sqrt(sum((Dte-d).^2));
end
In image processing, specifically in fingerprint recognition, I have to apply a two-dimensional low pass filter with a unit integral.
What does this unit integral mean? Also, if I choose a Gaussian filter, what sigma to use?
Unit integral means that the total area of the mask or kernel should be 1. For example, a 3 x 3 averaging filter means that every coefficient in your mask should be 1/9. When you sum up all of the elements in the mask it adds to 1.
The Gaussian filter inherently has a unit integral / unit area of 1. If you use MATLAB, the fspecial command with the gaussian flag has its mask normalized.
However, if you want to create the Gaussian mask yourself, you can use the following equation:
Bear in mind that (x,y) are the locations inside the mask with respect to the centre. As such, if you have a 5 x 5 mask, then at row = 2, col = 2, x = 0 and y = 0. However, the above equation does not generate a unit area of 1. It is theoretically equal to 1 if you integrate over the entire 2D plane. Because we are truncating the Gaussian function, the area is not 1. As such, once you generate all of your coefficients, you need to make sure that the total area is 1 by summing up every single element in the mask. Then, you take this number and divide every single element in your mask by this number. In fact when you generate the Gaussian mask, it's not important to multiply the exponential term by the scale factor in the equation. By ensuring that the sum of the mask is equal to 1, the scale is effectively removed. You can just use the exponential term instead to shave off some calculations.
In terms of the sigma that is completely up to you. Usually people go with the half width of 3*sigma rule, so the total width spanning from left to right in 1D is 6*sigma + 1 (including the centre). In order to figure out what sigma you want specifically, people figure out how wide the smallest feature is in the image, set that as the width then figure out the sigma from there. For example, if the biggest width is 13, then rearranging for sigma in the equation gives you 2. In other words:
13 = 6*sigma + 1
12 = 6*sigma
sigma = 2
As such, you'd set your sigma to 2 and make the mask 13 x 13. For more information about the 3*sigma rule, check out my post on the topic here: By which measures should I set the size of my Gaussian filter in MATLAB?
Once you create that mask, use any convolution method you wish to Gaussian filter your image.
Here's another post that may help you if you can use MATLAB.
How to make a Gaussian filter in Matlab
If you need to use another language like C or Java, then you could create a Gaussian mask in the following way:
C / C++
#define WIDTH 13
float sigma = ((float)WIDTH - 1.0f) / 6.0f;
int half_width = (int)(WIDTH / 2.0);
float mask[WIDTH][WIDTH];
float scale = 0.0f;
for (int i = -half_width; i <= half_width; i++) {
for(int j = -half_width; j <= half_width; j++) {
mask[i+half_width][j+half_width] = expf( -((float)(i*i + j*j) / (2.0*sigma*sigma)) );
scale += mask[i+half_width][j+half_width];
}
}
for (int i = 0; i < WIDTH; i++)
for (int j = 0; j < WIDTH; j++)
mask[i][j] /= scale;
Java
int WIDTH = 13;
float sigma = ((float)WIDTH - 1.0f) / 6.0f);
int half_width = Math.floor((float)WIDTH / 2.0f);
float[][] mask = new float[WIDTH][WIDTH];
float scale = 0.0f;
for (int i = -half_width; i <= half_width; i++) {
for (int j = -half_width; j <= half_width; j++) {
mask[i+half_width][j+half_width] = (float) Math.exp( -((double)(i*i + j*j) / (2.0*sigma*sigma)) );
scale += mask[i+half_width][j+half_width];
}
}
for (int i = 0; i < WIDTH; i++)
for (int j = 0; j < WIDTH; j++)
mask[i][j] /= scale;
As I noted before, notice that in the code I didn't have to divide by 2*pi*sigma^2. Again, the reason why is because when you normalize the kernel, this constant factor gets cancelled out anyway, so there's no need to add any additional overhead when computing the mask coefficients.
I'm writing a c program to generate a sinusoidal wave that slowly ramps up frequency from f1 to f2 for a giving time interval.
I have written this c program to ramp the frequency from 0 to 10 Hz but the problem is that the frequency changes after completion of 360 degrees. If I try to change the frequency between 0 and 360 degree that the transition is not smooth and it is abrupt.
This is the equation the sin that I have used y = Amplitude*sin(freq*phase)
int main(int argc, char *argv[]) {
double y, freq,phase;
int count; // for convenience of plotting in matlab so all the waves are spread on x axis.
for (freq = 0; freq < 10; freq+=1) {
for (phase = 0; phase < 360; phase++) { // phase is 360 degrees
y = 3 * sin((count*6.283185)+(freq*(phase*(3.14159/180))));
printf("%f %f %f \n", freq, phase, y);
}
count++;
}
return EXIT_SUCCESS;
}
How do I change frequency smoothly for a given time period?
should I be looking into Fourier transformations?
if you want angular frequency (w=2 pi f) to vary linearly with time then dw/dt = a and w = w0 + (wn-w0)*t/tn (where t goes from 0 to tn, w goes from w0 to wn). phase is the integral of that, so phase = w0 t + (wn-w0)*t^2/(2tn) (as oli says):
void sweep(double f_start, double f_end, double interval, int n_steps) {
for (int i = 0; i < n_steps; ++i) {
double delta = i / (float)n_steps;
double t = interval * delta;
double phase = 2 * PI * t * (f_start + (f_end - f_start) * delta / 2);
while (phase > 2 * PI) phase -= 2 * PI; // optional
printf("%f %f %f", t, phase * 180 / PI, 3 * sin(phase));
}
}
(where interval is tn and delta is t/tn).
here's the output for the equivalent python code (1-10Hz over 5 seconds):
from math import pi, sin
def sweep(f_start, f_end, interval, n_steps):
for i in range(n_steps):
delta = i / float(n_steps)
t = interval * delta
phase = 2 * pi * t * (f_start + (f_end - f_start) * delta / 2)
print t, phase * 180 / pi, 3 * sin(phase)
sweep(1, 10, 5, 1000)
ps incidentally, if you're listening to this (or looking at it - anything that involves human perception) i suspect you don't want a linear increase, but an exponential one. but that's a different question...
How do I change frequency smoothly for a given time period?
A smooth sinusoid requires continuous phase. Phase is the integral of frequency, so if you have a linear function for frequency (i.e. a constant-rate increase from f1 to f2), then phase will be a quadratic function of time.
You can figure out the maths with pen and paper, or I can tell you that the resulting waveform is called a linear chirp.
Should I be looking into Fourier transformations?
The Fourier transform of a linear chirp is itself a linear chirp, so probably no.
It should be fairly simple. Rather than thinking of varying the frequency, think of making an object spin faster and faster. The angular distance it has traveled might be X after N seconds, but will be more that 2X (maybe 4X) after 2N seconds. So come up with a formula for the angular distance (eg, alpha = k1 * T + k2 * T**2) and take the sine of that angular distance to find the value of the waveform at any time T.
+ (void) appendChirp:(int[])sampleData size:(int)len
withStartFrequency:(double)startFreq withEndFrequency:(double)endFreq
withGain:(double)gain {
double sampleRate = 44100.0;
for (int i = 0; i < len; i++) {
double progress = (double)i / (double)len;
double frequency = startFreq + (progress * (endFreq - startFreq));
double waveLength = 1.0 / frequency;
double timePos = (double)i / sampleRate;
double pos = timePos / waveLength;
double val = sin(pos * 2.0 * M_PI); // -1 to +1
sampleData[i] += (int)(val * 32767.0 * gain);
}
}
I'm using linear interpolation for animating an object between two 2d coordinates on the screen. This is pretty close to what I want, but because of rounding, I get a jagged motion. In ASCII art:
ooo
ooo
ooo
oo
Notice how it walks in a Manhattan grid, instead of taking 45 degree turns. What I'd like is linear interpolation along the line which Bresenham's algorithm would have created:
oo
oo
oo
oo
For each x there is only one corresponding y. (And swap x/y for a line that is steep)
So why don't I just use Bresenham's algorithm? I certainly could, but that algorithm is iterative, and I'd like to know just one coordinate along the line.
I am going to try solving this by linearly interpolating the x coordinate, round it to the pixel grid, and then finding the corresponding y. (Again, swap x/y for steep lines). No matter how that solution pans out, though, I'd be interested in other suggestion and maybe previous experience.
Bresenham's algorithm for lines was introduced to draw a complete line a bit faster than usual approaches. It has two major advantages:
It works on integer variables
It works iteratively, which is fast, when drawing the complete line
The first advantage is not a great deal, if you calculate only some coordinates. The second advantage turns out as a disadvantage when calculating only some coordinates. So after all, there is no need to use Bresenham's algorithm.
Instead, you can use a different algorithm, which results in the same line. For example the DDA (digital differential analyzer). This is basically, the same approach you mentioned.
First step: Calculate the slope.
m = (y_end - y_start) / (x_end - x_start)
Second step: Calculate the iteration step, which is simply:
i = x - x_start
Third step: Calculate the coresponding y-value:
y = y_start + i * m
= y_start + (x - x_start) * (y_end - y_start) / (x_end - x_start)
Here's the solution I ended up with:
public static Vector2 BresenhamLerp(Vector2 a, Vector2 b, float percent)
{
if (a.x == b.x || Math.Abs(a.x - b.x) < Math.Abs(a.y - b.y))
{
// Didn't do this part yet. Basically, we just need to recurse
// with x/y swapped and swap result on return
}
Vector2 result;
result.x = Math.Round((1-percent) * a.x + percent * b.x);
float adjustedPercent = (result.x - a.x + 0.5f) / (b.x - a.x);
result.y = Math.Round((1-adjustedPercent) * a.y + adjustedPercent * b.y);
return result;
}
This is what I just figured out would work. Probably not the most beautiful interpolations, but it is just a 1-2 float additions per iteration on the line with a one-time precalculation. Works by calculating the number of steps on a manhattan matrix.
Ah, and it does not yet catch the case when the line is vertical (dx = 0)
This is the naive bresenham, but the iterations could in theory only use integers as well. If you want to get rid of the float color value, things are going to get harder because the line might be longer than the color difference, so delta-color < 1.
void Brepolate( uint8_t* pColorBuffer, uint8_t cs, float xs, float ys, float zs, uint8_t ce, float xe, float ye, float ze )
{
float nColSteps = (xe - xs) + (ye - ys);
float fColInc = ((float)cs - (float)ce) / nColSteps;
float fCol = cs;
float dx = xe - xs;
float dy = ye - ys;
float fCol = cs;
if (dx > 0.5)
{
float de = fabs( dy / dx );
float re = de - 0.5f;
uint32_t iY = ys;
uint32_t iX;
for ( uint32_t iX = xs;
iX <= xe;
iX++ )
{
uint32_t off = surf.Offset( iX, iY );
pColorBuffer[off] = fCol;
re += de;
if (re >= 0.5f)
{
iY++;
re -= 1.0f;
fCol += fColInc;
}
fCol += fColInc;
}
}
}