3

この手法を使用してオーディオシンセサイザーを実装しようとしています:

https://ccrma.stanford.edu/~stilti/papers/blit.pdf

SDL2_Mixer ライブラリを使用して、標準 C で実行しています。

これは私のBLIT関数の実装です:

double blit(double angle, double M, double P) {
    double x = M * angle / P;
    double denom = (M * sin(M_PI * angle / P));
    if (denom < 1)
        return (M / P) * cos(M_PI * x) / cos(M_PI * x / M);
    else {
        double numerator = sin(M_PI * x);
        return (M / P) * numerator / denom;
    }
}

アイデアは、紙の指示に従って、それを組み合わせて方形波を生成することです。この構成で SDL2_mixer をセットアップしました。

SDL_AudioSpec *desired, *obtained;
SDL_AudioSpec *hardware_spec;

desired = (SDL_AudioSpec*)malloc(sizeof(SDL_AudioSpec));
obtained = (SDL_AudioSpec*)malloc(sizeof(SDL_AudioSpec));

desired->freq=44100;
desired->format=AUDIO_U8;
desired->channels=1;
desired->samples=2048;
desired->callback=create_rect;
desired->userdata=NULL;

そして、ここに私のcreate_rect機能があります。バイポーラ インパルス列を作成し、その値を統合して帯域制限された rect 関数を生成します。

void create_rect(void *userdata, Uint8 *stream, int len) {
    static double angle = 0;
    static double integral = 0;
    int i = 0;
    // This is the freq of my tone
    double f1 = tone_table[current_wave.note];
    // Sample rate
    double fs = 44100;
    // Pulse
    double P = fs / f1;
    int M = 2 * floor(P / 2) + 1;

    double oldbipolar = 0;
    double bipolar = 0;
    for(i = 0; i < len; i++) {
        if (++angle > P)
            angle -= P;
        double angle2 = angle + floor(P/2);
        if (angle2 > P)
            angle2 -= P;

        bipolar = blit(angle2, M, P) - blit(angle, M, P);

        integral += (bipolar + old bipolar) * 0.5;
        oldbipolar = bipolar;
        *stream++ = (integral + 0.5) * 127;
    }
}

私の問題は、結果の波はまったく問題ありませんが、数秒後にノイズが発生し始めます。私は結果をプロットしようとしましたが、これがそれです:

標準版 もっとズームしたバージョン 批評エリア

何か案が?

編集: 統合する前のバイポーラ BLIT のプロットは次のとおりです。

ブリット スケーリングされた BLIT

4

0 に答える 0