draw a sine wave using c?
Why are we incrementing the angle and how this angle is relevant to graph
The sine function takes an angle as argument, typically in radiant. The program implements the angle in degrees, so it's getting scaled to radiant the moment is gets passed to sin()
.
The sine function is periodical to (repeats itself after) 2*pi or 360 degrees:
+---------+---------+------------+
| angle | sin(angle) |
+---------+---------+ |
| Radiant | Degrees | |
+---------+---------+------------+
| 0 | 0 | 0 |
+---------+---------+------------+
| 1/2*pi | 90 | 1 |
+---------+---------+------------+
| pi | 180 | 0 |
+---------+---------+------------+
| 3/2*pi | 270 | -1 |
+---------+---------+------------+
| 2*pi | 360 | 0 |
+---------+---------+------------+
| 5/2*pi | 450 | 1 |
+---------+---------+------------+
| 3*pi | 540 | 0 |
+---------+---------+------------+
| 7/2*pi | 630 | -1 |
+---------+---------+------------+
| 4*pi | 720 | 0 |
+---------+---------+------------+
| ... | ... | ... |
and so on ...
changed the value of angle to 0 and the wave became a straight line
The result of sin(0)
is 0
.
For the mathematical derivation you might like to have a look here.
Trouble Generating a Sine Wave in C/Matlab from Basics
So turns out I had a few things wrong. My for loop was using the number of bytes in the output buffer, not the number of elements in the buffer. I was overlooking the relevance of the wav file sampling rate in generating the sine wave, and the discontinuity in using the loop variable was causing strange artifacts.
The final working code is as follows:
#include <sys/types.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#define M_PI 3.1415926535897932384626433832795L
#define NUM_CHANNELS 2
#define NUM_SAMPLES 512
#define SAMPLE_RATE 44100
double frequency = 500.0;
int main(int argc, char *argv[])
{
if (argc >= 2){
frequency = atof(argv[1]);
}
int16_t samples[NUM_CHANNELS * NUM_SAMPLES];
unsigned cbBuffer=sizeof(samples);
int counter = 0;
while(1){
for (int i = 0; i < NUM_CHANNELS * NUM_SAMPLES; i+=NUM_CHANNELS){
samples[i] = (int16_t) 3000 * sin(frequency * 2 * M_PI * (double)counter /(double)(SAMPLE_RATE));
samples[i+1] = samples[i];
counter++;
}
int done=write(STDOUT_FILENO, samples, cbBuffer);
if(done<0){
fprintf(stderr, "%s : Write to stdout failed, error=%s.", argv[0], strerror(errno));
exit(1);
}else if(done!=cbBuffer){
fprintf(stderr, "%s : Could not read requested number of bytes from stream.\n", argv[0]);
}
}
return 0;
}
Generating sine wave array in C with noise
(For reference)
You first have to seed the random-number generator using srand()
, to which you should pass a unique value at every program-run.
Your code, modified for correctness:
#include <math.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand((unsigned)time(NULL));
int i;
double buffer[10000];
for(i = 0; i < 10000; i++)
{
buffer[i] = sin(2000 * (2 * M_PI) * i / 6000) + sqrt(0.01) * rand();
}
/* ... */
return 0;
}
3D ASCII Sine wave generator generates weird sine waves
The value of amplitudeHeight should be 2.5 to account for the number of symbols. You're clipping the wave where the amplitude goes from 0..20 and taking the mod 5.
Related Topics
How to Add a Background Image to the Qmainwindow
The Definitive C++ Book Guide and List
Difference Between #Include ≪Filename≫ and #Include "Filename"
How to Test Whether Stringstream Operator≫≫ Has Parsed a Bad Type and Skip It
What Is a "Translation Unit" in C++
#Pragma Once VS Include Guards
What Do Single Quotes Do in C++ When Used on Multiple Characters
Generating Random Integer from a Range
What Is a "Span" and When Should I Use One
A Positive Lambda: '+[]{}' - What Sorcery Is This
Combining Multiple for Loops into Single Iterator
What Is an Undefined Reference/Unresolved External Symbol Error and How to Fix It
Capture Characters from Standard Input Without Waiting For Enter to Be Pressed
How to Iterate Over the Elements of an Std::Tuple