2

単一のエンベロープに続く任意の周波数の純粋な正弦波のシーケンスから作成された複雑な正弦波を生成する一般的な加算合成 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);
    }
}       
}

ただし、これを正しく行っているかどうかはよくわかりません。これを修正して続行する方法についてのアイデアはありますか?

4

2 に答える 2

2

ますます細部に気付き始めたので、コメントを読むのが面倒になり始めました(ただし、コンパイル中の Hello World の質問にまだ回答していることを確認してください)。そのため、それらをこの回答にまとめて、さらに表示されるように更新します。 :

  1. 現在、frequencyは 1 回だけ使用され、その時点では は 1 回のみ0.0です。それはあなたが望むものですか?
  2. iは に初期化され0、 からsampleNumberも開始され0ます。したがって、while条件(i < sampleNumber)は決して実行されません
  3. iインクリメントされることはありませんが、if ( i <= 1000 )条件があるため、常に評価されますtrue
  4. sampleRateは に初期化されて0.0おり、それに対する最初の操作はそれで除算することであり、これは明らかに幸せな時間ではありません
  5. 明らかに衒学的ですが、n一番下のforループは決して宣言されません (int n; for (n = ....)例として.
  6. あなたのsample_buffer = (float*) malloc(samples * sizeof(float));行では、samplesおそらくそうsampleNumberであるべきですよね?samples定義されていません
于 2012-10-22T19:36:02.940 に答える
1

私はAKA4749に同意し、もう1つすべきことがあります。サンプルを追加するときにサンプルをクリップするか、歪みが発生することです。

if ( sample[i] > 1 ) sample[i] = 1;
else if ( sample[i] < -1 ) sample[i] = -1;
于 2012-10-22T19:48:19.823 に答える