sine wave generation in c++ - c++

I am trying to generate a set of points, which when plotted as a graph represent a sine wave of 1 cycle. The requirements are :
a sine wave of 1 cycle
lower limit = 29491
upper limit = 36043
no of points = 100
Amplitude = 3276
zero offset = 32767
Code :
int main()
{
ofstream outfile;
outfile.open("data.dat",ios::trunc | ios::out);
for(int i=0;i<100;i++)
{
outfile << int(3276*sin(i)+32767) << "\n";
}
outfile.close();
return 0;
}
I am generating and storing the points in a file. When these points are plotted I get the following graph.
But I only need one cycle. How can I do this?

taking into the formula of sine wave:
y(t) = A * sin(2 * PI * f * t + shift)
where:
A = the amplitude, the peak deviation of the function from zero.
f = the ordinary frequency, the number of oscillations (cycles)
t = time
shift = phase shift
would be:
y[t] = AMPLITUDE * sin (2 * M_PI * 0.15 * t + 0) + ZERO_OFFSET;
^^^ f = 15 cycles / NUM_POINTS = 0.15 Hz
To have one full-cycle, loop from y[0:t) where t is the time or number of points it takes to have a full cycle (i.e. wavelength)

It appears you need 100 samples for one cycle, so you probably need this:
...
#define _USE_MATH_DEFINES
#include <math.h>
...
#define NB_OF_SAMPLES 100
...
double angle = 0.0;
for (int i = 0; i < NB_OF_SAMPLES; i++)
{
outfile << int(3276 * sin(angle) + 32767) << "\n";
angle += (2 * M_PI) / NB_OF_SAMPLES;
}
...
Or better:
#define NB_OF_SAMPLES 100
#define OFFSET 3276
#define AMPLITUDE 32767
...
double angle = 0.0;
for (int i = 0; i < NB_OF_SAMPLES; i++)
{
outfile << int(AMPLITUDE * sin(angle) + OFFSET) << "\n";
angle += (2 * M_PI) / NB_OF_SAMPLES;
}
...

A full cycle consists of 360 degrees. samples needed is 100.
So step size is 3.6
int main()
{
ofstream outfile;
outfile.open("data.dat",ios::trunc | ios::out);
for(int i=0;i<101;i++)
{
float rads = M_PI/180;
outfile << (float)(3276*sin(3.6*i*rads)+32767) << endl;
}
outfile.close();
return 0;
}
If number of samples is 200, then step size if 360/200 = 1.8
int main()
{
ofstream outfile;
outfile.open("data.dat",ios::trunc | ios::out);
for(int i=0;i<201;i++)
{
float rads = M_PI/180;
outfile << (float)(3276*sin(1.8*i*rads)+32767) << endl;
}
outfile.close();
return 0;
}
Output:

You need to change the for loop to iterate from 0 to 2(pi). That is one cycle for the sine wave. You might also want to change the loop counter to a double instead of integer and increment by 0.1 or something instead.
screenshot from WolframAlpha.com

The maths sine function std::sin takes its argument in radians:
arg - value representing angle in radians, of a floating-point or
Integral type
If you need 1 cycle and 100 points then, knowing that there are 2pi radians in one cycle, you need something like
double rads;
for(int i=1;i<=100;i++)
{
rads = 2.0*M_PI*i/100;
// your expression in terms of std::sin(rads)
}
If, on the off chance your compiler/library doesn't have M_PI out of the box, then look here for flags that should make it available.
One thing that hasn't been touched on is the exact interval that you should generate. If you need the closed interval [0,2pi] then you will need to adjust your step sizes. I've given a half-open interval (0,2pi] and #Michael Walz has given the other half-open interval [0,2pi).

Related

Audio samples to musical note detection issue

I'm trying to setup a pipeline allowing me to detect musical notes from audio samples, but the input layer where I identify the frequency content of the samples does not land on the expected values. In the example below I...
build what I expect to be a 440Hz (A4) sine wave in the FFTW input buffer
apply the Hamming window function
lookup the first half the output bins to find the 4 top values and their frequency
void GenerateSinWave(fftw_complex* outputArray, int N, double frequency, double samplingRate)
{
double sampleDurationSeconds = 1.0 / samplingRate;
for (int i = 0; i < N; ++i)
{
double sampleTime = i * sampleDurationSeconds;
outputArray[i][0] = sin(M_2_PI * frequency * sampleTime);
}
}
void HammingWindow(fftw_complex* array, int N)
{
static const double a0 = 25.0 / 46.0;
static const double a1 = 1 - a0;
for (int i = 0; i < N; ++i)
array[i][0] *= a0 - a1 * cos((M_2_PI * i) / N);
}
int main()
{
const int N = 4096;
double samplingRate = 44100;
double A4Frequency = 440;
fftw_complex in[N] = { 0 };
fftw_complex out[N] = { 0 };
fftw_plan plan = fftw_plan_dft_1d(N, 0, 0, FFTW_FORWARD, FFTW_ESTIMATE);
GenerateSinWave(in, N, A4Frequency, samplingRate);
HammingWindow(in, N);
fftw_execute_dft(plan, in, out);
// Find the 4 top values
double binHzRange = samplingRate / N;
for (int i = 0; i < 4; ++i)
{
double maxValue = 0;
int maxBin = 0;
for (int bin = 0; bin < (N/2); ++bin)
{
if (out[bin][0] > maxValue)
{
maxValue = out[bin][0];
maxBin = bin;
}
}
out[maxBin][0] = 0; // remove value for next pass
double binMidFreq = (maxBin * binHzRange) + (binHzRange / 2);
std::cout << (i + 1) << " -> Freq: " << binMidFreq << " Hz - Value: " << maxValue << "\n";
}
fftw_destroy_plan(plan);
}
I was expecting something close to 440 or lower/higher harmonics, however the results are far from that:
1 -> Freq: 48.4497Hz - Value: 110.263
2 -> Freq: 59.2163Hz - Value: 19.2777
3 -> Freq: 69.9829Hz - Value: 5.68717
4 -> Freq: 80.7495Hz - Value: 2.97571
This flow is mostly inspired by this other SO answer. I feel that my lack of knowledge about signal processing might be in cause! My sin wave generation and window function seem to be ok, but audio analysis and FFTW are full of mysteries...
Any insight about how to improve my usage of FFTW, approach signal processing or simply write better code is appreciated!
EDIT: fixed integer division leading to Hamming a0 parameter always being 0. Results changed a little, but still far of the expected 440 Hz
I think you've misunderstood the M_2_PI constant in your GenerateSinWave function. M_2_PI is defined as 2.0 / PI.
You should be using 2 * M_PI instead.
This mistake will mean that your generated signal has a frequency of only around 45 Hz. This should be close to the output frequencies you are seeing.
The same constant needs correcting in your HammingWindow function too.

How do I end this while loop with a precision of 0.00001 ([C++],[Taylor Series])?

I'm working on this program that approximates a taylor series function. I have to approximate it so that the taylor series function stops approximating the sin function with a precision of .00001. In other words,the absolute value of the last approximation minus the current approximation equals less than or equal to 0.00001. It also approximates each angle from 0 to 360 degrees in 15 degree increments. My logic seems to be correct, but I cannot figure out why i am getting garbage values. Any help is appreciated!
#include <math.h>
#include <iomanip>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <cmath>
double fact(int x){
int F = 1;
for(int i = 1; i <= x; i++){
F*=i;
}
return F;
}
double degreesToRadians(double angle_in_degrees){
double rad = (angle_in_degrees*M_PI)/180;
return rad;
}
using namespace std;
double mySine(double x){
int current =99999;
double comSin=x;
double prev=0;
int counter1 = 3;
int counter2 = 1;
while(current>0.00001){
prev = comSin;
if((counter2 % 2) == 0){
comSin += (pow(x,(counter1))/(fact(counter1)));
}else{
comSin -= (pow(x,(counter1))/(fact(counter1)));
}
current=abs(prev-comSin);
cout<<current<<endl;
counter1+=2;
counter2+=1;
}
return comSin;
}
using namespace std;
int main(){
cout<<"Angle\tSine"<<endl;
for (int i = 0; i<=360; i+=15){
cout<<i<<"\t"<<mySine(degreesToRadians(i));
}
}
Here is an example which illustrates how to go about doing this.
Using the pow function and calculating the factorial at each iteration is very inefficient -- these can often be maintained as running values which are updated alongside the sum during each iteration.
In this case, each iteration's addend is the product of two factors: a power of x and a (reciprocal) factorial. To get from one iteration's power factor to the next iteration's, just multiply by x*x. To get from one iteration's factorial factor to the next iteration's, just multiply by ((2*n+1) + 1) * ((2*n+1) + 2), before incrementing n (the iteration number).
And because these two factors are updated multiplicatively, they do not need to exist as separate running values, they can exists as a single running product. This also helps avoid precision problems -- both the power factor and the factorial can become large very quickly, but the ratio of their values goes to zero relatively gradually and is well-behaved as a running value.
So this example maintains these running values, updated at each iteration:
"sum" (of course)
"prod", the ratio: pow(x, 2n+1) / factorial 2n+1
"tnp1", the value of 2*n+1 (used in the factorial update)
The running update value, "prod" is negated every iteration in order to to factor in the (-1)^n.
I also included the function "XlatedSine". When x is too far away from zero, the sum requires more iterations for an accurate result, which takes longer to run and also can require more precision than our floating-point values can provide. When the magnitude of x goes beyond PI, "XlatedSine" finds another x, close to zero, with an equivalent value for sin(x), then uses this shifted x in a call to MaclaurinSine.
#include <iostream>
#include <iomanip>
// Importing cmath seemed wrong LOL, so define Abs and PI
static double Abs(double x) { return x < 0 ? -x : x; }
const double PI = 3.14159265358979323846;
// Taylor series about x==0 for sin(x):
//
// Sum(n=[0...oo]) { ((-1)^n) * (x^(2*n+1)) / (2*n + 1)! }
//
double MaclaurinSine(double x) {
const double xsq = x*x; // cached constant x squared
int tnp1 = 3; // 2*n+1 | n==1
double prod = xsq*x / 6; // pow(x, 2*n+1) / (2*n+1)! | n==1
double sum = x; // sum after n==0
for(;;) {
prod = -prod;
sum += prod;
static const double MinUpdate = 0.00001; // try zero -- the factorial will always dominate the power of x, eventually
if(Abs(prod) <= MinUpdate) {
return sum;
}
// Update the two factors in prod
prod *= xsq; // add 2 to the power factor's exponent
prod /= (tnp1 + 1) * (tnp1 + 2); // update the factorial factor by two iterations
tnp1 += 2;
}
}
// XlatedSine translates x to an angle close to zero which will produce the equivalent result.
double XlatedSine(double x) {
if(Abs(x) >= PI) {
// Use int casting to do an fmod PI (but symmetric about zero).
// Keep in mind that a really big x could overflow the int,
// however such a large double value will have lost so much precision
// at a sub-PI-sized scale that doing this in a legit fashion
// would also disappoint.
const int p = static_cast<int>(x / PI);
x -= PI * p;
if(p % 2) {
x = -x;
}
}
return MaclaurinSine(x);
}
double DegreesToRadians(double angle_deg) {
return PI / 180 * angle_deg;
}
int main() {
std::cout<<"Angle\tSine\n" << std::setprecision(12);
for(int i = 0; i<=360; i+=15) {
std::cout << i << "\t" << MaclaurinSine(DegreesToRadians(i)) << "\n";
//std::cout << i << "\t" << XlatedSine(DegreesToRadians(i)) << "\n";
}
}

finding pi - using Machin's formula. Different iterations are giving same result

I've written a few programs to find pi, this one being the most advanced. I used Machin's formula, pi/4 = 4(arc-tan(1/5)) - (arc-tan(1/239)).
The problem is that however many iterations I do, I get the same result, and I can't seem to understand why.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double arctan_series(int x, double y) // x is the # of iterations while y is the number
{
double pi = y;
double temp_Pi;
for (int i = 1, j = 3; i < x; i++, j += 2)
{
temp_Pi = pow(y, j) / j; //the actual value of the iteration
if (i % 2 != 0) // for every odd iteration that subtracts
{
pi -= temp_Pi;
}
else // for every even iteration that adds
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
double calculations(int x) // x is the # of iterations
{
double value_1, value_2, answer;
value_1 = arctan_series(x, 0.2);
value_2 = arctan_series(x, 1.0 / 239.0);
answer = (4 * value_1) - (value_2);
return answer;
}
int main()
{
double pi;
int iteration_num;
cout << "Enter the number of iterations: ";
cin >> iteration_num;
pi = calculations(iteration_num);
cout << "Pi has the value of: " << setprecision(100) << fixed << pi << endl;
return 0;
}
I have not been able to reproduce your issue, but here is a bit cleaned up code with a few C++11 idioms and better variable names.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
// double arctan_series(int x, double y) // x is the # of iterations while y is the number
// then why not name the parameters accoringly? In math we usually use x for the parameter.
// prefer C++11 and the auto notation wherever possible
auto arctan_series(int iterations, double x) -> double
{
// note, that we don't need any temporaries here.
// note, that this loop will never run, when iterations = 1
// is that really what was intended?
for (int i = 1, j = 3; i < iterations; i++, j += 2)
{
// declare variables as late as possible and always initialize them
auto t = pow(x, j) / j;
// in such simple cases I prefer ?: over if-else. Your milage may vary
x += (i % 2 != 0) ? -t : t;
}
return x * 4;
}
// double calculations(int x) // x is the # of iterations
// then why not name the parameter accordingly
// BTW rename the function to what it is supposed to do
auto approximate_pi(int iterations) -> double
{
// we don't need all of these temporaries. Just write one expression.
return 4 * arctan_series(iterations, 0.2) - arctan_series(iterations, 1.0 / 239.0);
}
auto main(int, char**) -> int
{
cout << "Enter the number of iterations: ";
// in C++ you should declare variables as late as possible
// and always initialize them.
int iteration_num = 0;
cin >> iteration_num;
cout << "Pi has the value of: "
<< setprecision(100) << fixed
<< approximate_pi(iteration_num) << endl;
return 0;
}
When you remove my explanatory comments, you'll see, that the resulting code is a lot more concise, easier to read, and therefore easier to maintain.
I tried a bit:
Enter the number of iterations: 3
Pi has the value of: 3.1416210293250346197169164952356368303298950195312500000000000000000000000000000000000000000000000000
Enter the number of iterations: 2
Pi has the value of: 3.1405970293260603298790556436870247125625610351562500000000000000000000000000000000000000000000000000
Enter the number of iterations: 7
Pi has the value of: 3.1415926536235549981768144789384678006172180175781250000000000000000000000000000000000000000000000000
Enter the number of iterations: 42
Pi has the value of: 3.1415926535897940041763831686694175004959106445312500000000000000000000000000000000000000000000000000
As you see, I obviously get different results for different numbers of iterations.
That method converges very quickly. You'll get more accuracy if you start with the smallest numbers first. Since 5^23 > 2^53 (the number of bits in the mantissa of a double), probably the maximum number of iterations is 12 (13 won't make any difference). You'll get more accuracy starting with the smaller numbers. The changed lines have comments:
double arctan_series(int x, double y)
{
double pi = y;
double temp_Pi;
for (int i = 1, j = x*2-1; i < x; i++, j -= 2) // changed this line
{
temp_Pi = pow(y, j) / j;
if ((j & 2) != 0) // changed this line
{
pi -= temp_Pi;
}
else
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
For doubles, there is no point in setting precision > 18.
If you want an alternative formula that takes more iterations to converge, use pi/4 = arc-tan(1/2) + arc-tan(1/3), which will take about 24 iterations.
This is another way if some of you are interested. The loop calculates the integral of the function : sqrt(1-x²)
Which represents a semicircle of radius 1. Then we multiply by two the area. Finally we got the surface of the circle which is PI.
#include <iomanip>
#include <cmath>
#define f(x) sqrt(1-pow(x,2))
double integral(int a, int b, int p)
{
double d=pow(10, -p), s=0;
for (double x=a ; x+d<=b ; x+=d)
{
s+=f(x)+f(x+d);
}
s*=d/2.0;
return s;
}
int main()
{
cout << "PI=" << setprecision (9) << 2.0*integral(-1,1,6) << endl;
}

Need floating point precision, GUI gui uses int

I have a flow layout. Inside it I have about 900 tables. Each table is stacked one on top of the other. I have a slider which resizes them and thus causes the flow layout to resize too.
The problem is, the tables should be linearly resizing. Their base size is 200x200. So when scale = 1.0, the w and h of the tables is 200.
I resize by a fixed amount each time making them 4% bigger each time. This means I would expect them to grow by 8 pixels each time. What happens is, every few resizes, the tables grow by 9 pixels. I use doubles everywhere. I have tried rounding, floor and ceil but the problem persists. What could I do so that they always grow by the correct amount?
void LobbyTableManager::changeTableScale( double scale )
{
setTableScale(scale);
}
void LobbyTableManager::setTableScale( double scale )
{
scale += 0.3;
scale *= 2.0;
std::cout << scale << std::endl;
agui::Gui* gotGui = getGui();
float scrollRel = m_vScroll->getRelativeValue();
setScale(scale);
rescaleTables();
resizeFlow();
...
double LobbyTableManager::getTableScale() const
{
return (getInnerWidth() / 700.0) * getScale();
}
void LobbyFilterManager::valueChanged( agui::Slider* source,int val )
{
if(source == m_magnifySlider)
{
DISPATCH_LOBBY_EVENT
{
(*it)->changeTableScale((double)val / source->getRange());
}
}
}
void LobbyTableManager::renderBG( GraphicsContext* g, agui::Rectangle& absRect, agui::Rectangle& childRect )
{
int cx, cy, cw, ch;
g->getClippingRect(cx,cy,cw,ch);
g->setClippingRect(absRect.getX(),absRect.getY(),absRect.getWidth(),absRect.getHeight());
float scale = 0.35f;
int w = m_bgSprite->getWidth() * getTableScale() * scale;
int h = m_bgSprite->getHeight() * getTableScale() * scale;
int numX = ceil(absRect.getWidth() / (float)w) + 2;
int numY = ceil(absRect.getHeight() / (float)h) + 2;
float offsetX = m_activeTables[0]->getLocation().getX() - w;
float offsetY = m_activeTables[0]->getLocation().getY() - h;
int startY = childRect.getY() + 1;
if(moo)
{
std::cout << "TS: " << getTableScale() << " Scr: " << m_vScroll->getValue() << " LOC: " << childRect.getY() << " H: " << h << std::endl;
}
if(moo)
{
std::cout << "S=" << startY << ",";
}
int numAttempts = 0;
while(startY + h < absRect.getY() && numAttempts < 1000)
{
startY += h;
if(moo)
{
std::cout << startY << ",";
}
numAttempts++;
}
if(moo)
{
std::cout << "\n";
moo = false;
}
g->holdDrawing();
for(int i = 0; i < numX; ++i)
{
for(int j = 0; j < numY; ++j)
{
g->drawScaledSprite(m_bgSprite,0,0,m_bgSprite->getWidth(),m_bgSprite->getHeight(),
absRect.getX() + (i * w) + (offsetX),absRect.getY() + (j * h) + startY,w,h,0);
}
}
g->unholdDrawing();
g->setClippingRect(cx,cy,cw,ch);
}
void LobbyTable::rescale( double scale )
{
setScale(scale);
float os = getObjectScale();
double x = m_baseHeight * os;
if((int)(x + 0.5) > (int)x)
{
x++;
}
int oldH = getHeight();
setSize(m_baseWidth * os, floor(x));
...
I added the related code. The slider sends a value changed which is multiplied to get a 4 percent increase (or 8 percent if slider moves 2 values etc...) then the tables are rescaled with this.
The first 3 are when the table size increased by 9, the 4th time it increased by 8px. But the scale factor increases by 0.04 each time.
Why is the 4th time inconsistant?
the pattern seems like 8,8,8,9,9,9,8,8,8,9,9,9...
It increases by 1 pixel more for a few and then decreases by 1 ten increases by 1 etc, thats my issue...
I still don't see the "add 4%" code there (in a form I can understand, anyway), but from your description I think I see the problem: adding 4% twice is not adding 8%. It is adding 8.16% (1.04 * 1.04 == 1.0816). Do that a few more times and you'll start getting 9 pixel jumps. Do it a lot more times and your jumps will get much bigger (they will be 16 pixel jumps when the size gets up to 400x400). Which, IMHO is how I like my scaling to happen.

how to find necessary multiplier for loop?

#include <iostream>
using namespace std;
int main() {
float result = 50.0f;
float multiplier = 0.5f;
float fixed_multiplier = 1.0f - multiplier * 0.001f;
for (int i = 0; i < 1000; ++i) {
result *= fixed_multiplier;
}
cout << result << endl; // 30.322 -- want approximately 25
}
After the 1000 iterations, I want result to equal multiplier*result (result==25). How do I find what I need to modify multiplier (in fixed_multiplier) to get the desired result?
Your for loop is summarized by this mathematical equation:
result * fixed_multiplier ^ 1000 = result * multiplier
You can solve this equation to find your answer.
You can get the same result in C using the pow function:
fixed_multiplier = pow(multiplier, 0.001);
You have the following relationship:
result_out = result * fixed_multiplier^1000
where ^ denotes "to the power of". Simple algebra gives you this:
fixed_multiplier = (result_out / result) ^ (1/1000)