We’re rewarding the question askers & reputations are being recalculated! Read more.
2 added 979 characters in body
source | link

UPDATE:

I changed the C code as follows and I now get a nice smooth sine wave but the frequency is way too low

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 * 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;
}

UPDATE:

I changed the C code as follows and I now get a nice smooth sine wave but the frequency is way too low

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 * 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;
}
1
source | link

Trouble Generating a Sine Wave in C/Matlab from Basics

this is a crosspost from stackoverflow as I figured there may be more who can help me here...

I've been writing a basic C program to generate a sine wave and write it out to STDOUT for piping into a filter which I am also going to write but I'm having issues.

I am able to generate what sounds like a good clean sine wave, but the frequency is off. When I listen to the output I am generating and compare to a true signal generators output, the frequency of mine is slightly too high.

The C code should generate raw 16 bit signed stereo wav @ 44100Hz for a frequency passed as an argument to the program, or 500Hz as default.

A matlab version of the code is here, (modded very slightly for 1 indexing in Matlab, WHY MATHWORKS WHY!?) minus the passing to STDOUT etc as I know that works fine

CHANNELS = 2; SAMPLING_RATE = 44100; NUM_SAMPLES = 512;

frequency = 1000;

%% BEGIN WHILE(1) LOOP HERE

output_buff = zeros(1,CHANNELS*NUM_SAMPLES);

for i = 1:2:CHANNELS*NUM_SAMPLES
    output_buff(i) = 30000 * sin(frequency * pi * (i-1)/NUM_SAMPLES);
    output_buff(i+1) = output_buff(i);
end

%% OUTPUT TO STDOUT AND REPEAT

I should add that this code runs (in the C version) inside a while true loop, generating a full output_buff of values, then pushing the buffer to STDOUT.

I have written some further testing code to see what's actually being generated as follows:

plot(1:CHANNELS*NUM_SAMPLES, output_buff)

output_buff = output_buff .* hanning(length(output_buff))';    
Y = fft(output_buff);    
Mag=abs(Y(1:length(output_buff)/2)).^2;    
[a,b]=max(Mag);    
% Result    
SAMPLING_RATE*b/length(output_buff)

When I run this script, I can see at the end the frequency of the generated signal is actually 1.0767e+03Hz... Close but no cigar...

I've tried tweaking some of the parameters but I have no idea what's wrong or how to make the generated frequency more accurate.

The C 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 1024
#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);

    while(1){
        for (int i = 0; i < cbBuffer; i+=NUM_CHANNELS){
            samples[i] = (int16_t) 30000 * sin(frequency * M_PI * (double)i /(double)(NUM_SAMPLES));
            samples[i+1] = samples[i];
        }

        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;
}