General additive synthesis program
Domanda
I'm attempting to write a general additive synthesis c program that will generate a complex sinusoid created from a sequence of pure sine waves of arbitrary frequency following a single envelope. The input file will be something of this nature
F0 P0 // a list of up to 100 floats indicating frequencies and
F1 P1 // % contribution of this frequency to the sound
F2 P2
....
-1 // sentinal value to indicate end of frequency list
B0 A0 // first breakpoint
B1 A1
... // There can be an arbitary number of breakpoints
I want my program to generate a WAV file up to the last breakpoint where all the sine waves will be generated at the given frequencies, scaled to the % contribution as listed, and added together to make the final sound
I've attempted to try some of the c programming out but I'm not naturally a C programming so this is what I've done so far:
#include <stdio.h>
#include <stdlib.h>
#include <portsf.h>
#include <math.h>
#ifndef M_PI
#define M_PI (3.141592654)
#endif
// Additive Synthesis
PSF_PROPS props;
props.srate = 44100;
props.chans = 2;
props.samptype = PSF_SAMP_IEEE_FLOAT;
props.format = PSF_STDWAVE;
props.chformat = STDWAVE;
float* frame;
int sampleNumber;
double angleIncrement;
double frequency;
double sampleRate;
int i;
int twopi = 2.0 * M_PI;
ofd = psf_sndCreate(argv[2],&props,0,0,PSF_CREATE_RDWR);
int main (int argc, char* argv[]) {
sampleNumber = 0;
angleIncrement = twopi * frequency/sampleRate;
while (i < sampleNumber) {
frame[0] = frame[1] = sin(sampleNumber * angleIncrement);
sampleNumber++;
if (fwrite(&sampleout,sizeof(float),1,rawfile) !=1) {
printf("Error writing to output file.\n");
return 1;
}
if (i <=1000)
fprintf(bpfile, "%ld\t%f\n", i, frame);
phase += angleIncrement;
if (phase >= twopi)
phase -= twopi;
}
phase_offset = -1 * PI / 2;
sample_buffer = (float*) malloc(samples * sizeof(float));
// sample_buffer set back to 0
memset(sample_buffer, 0, sizeof(float)*sampleNumber);
// go through the number of harmonics
for (i = 1; i <= NHARMS; i++) {
amp = 1.0 / i;
// go through number of sinusoid components
for (n = 0; n < sampleNumber; n++) {
sample_buffer[n] += amp * cos(i * angleIncrement * n + phase_offset);
}
}
}
However, I'm not really sure if I'm doing this right at all. Any ideas on how I can fix this and proceed?
Soluzione
As I've started noticing more and more little details, the comments start getting annoying to read (but make sure you still answer my compiling Hello World question), so I've coalesced them into this answer and will update it as I see more:
- as of right now,
frequency
is used only once, and at that time is only0.0
ever. is that what you want? i
is initalized to0
, andsampleNumber
is also started at0
. Thus thewhile
condition(i < sampleNumber)
will never executei
is never incremented yet you have aif ( i <= 1000 )
condition, which will thus always evaluatetrue
sampleRate
is initialized to0.0
, and the first operation on it is to divide by it, which, obviously, is not happy times- Obviously pedantic, but the
n
in the bottom mostfor
loop is never declared (int n; for (n = ....)
as an example. - in your
sample_buffer = (float*) malloc(samples * sizeof(float));
line,samples
should most probably besampleNumber
, right?samples
is never defined
Altri suggerimenti
I agree with AKA4749, and have one more thing you should do: clip the samples when you add them or you get distortion:
if ( sample[i] > 1 ) sample[i] = 1;
else if ( sample[i] < -1 ) sample[i] = -1;