我正在尝试编写一个通用的加法合成c程序,它将生成一个复杂的正弦曲线,该正弦曲线是由一个单个包络后的任意频率的纯正弦波序列产生的。 输入文件将具有这种性质
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
我希望我的程序在最后一个断点处生成一个WAV文件,其中所有正弦波将以给定频率生成,按比例缩放到所列出的%贡献,并加在一起以产生最终声音
我试图尝试一些c编程,但我自然不是C编程,所以这就是我到目前为止所做的:
#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);
}
}
}
但是,我不确定我是否正确行事。关于如何解决这个问题的任何想法并继续下去?
答案 0 :(得分:2)
当我开始注意到越来越多的细节时,评论开始变得烦人的阅读(但确保你仍然回答我编译的Hello World问题),所以我将它们合并到这个答案中并将其更新为我看到更多:
frequency
仅使用一次,此时只有0.0
。那是你想要的吗?i
已初始化为0
,而sampleNumber
也已在0
开始。因此,while
条件(i < sampleNumber)
永远不会执行i
永远不会增加,但您有if ( i <= 1000 )
条件,因此会始终评估true
sampleRate
初始化为0.0
,其上的第一个操作是除以它,显然,这不是快乐时光n
循环中的for
从未声明(int n; for (n = ....)
为例。sample_buffer = (float*) malloc(samples * sizeof(float));
行,samples
最有可能是sampleNumber
,对吗?永远不会定义samples
答案 1 :(得分:1)
我同意AKA4749,还有一件事你应该做的事情:在添加样品时剪裁样品或者你会失真:
if ( sample[i] > 1 ) sample[i] = 1;
else if ( sample[i] < -1 ) sample[i] = -1;