3

I'm trying to implement a audio synthesizer using this technique:

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

I'm doing it in standard C, using SDL2_Mixer library.

This is my BLIT function implementation:

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

The idea is to combine it to generate a square wave, following the paper instructions. I setted up SDL2_mixer with this configuration:

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;

And here's my create_rect function. It creates a bipolar impulse train, then it integrates it's value to generate a band-limited rect function.

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

My problem is: the resulting wave is quite ok, but after few seconds it starts to make noises. I tried to plot the result, and here's it:

Standard version More zoomed version Critique area

Any idea?

EDIT: Here's a plot of the bipolar BLIT before integrating it:

BLIT Scaled BLIT

ProGM
  • 6,949
  • 4
  • 33
  • 52
  • Do you have some method to guarantee the input values to your BLIT function are within acceptable limits? For the most obvious example, problems would occur if was 'P' were allowed to be passed as 0. Are there any other parameter limits that should be considered? userdata is also a curiosity. is its content somehow validated before being allowed into these algorithms? Perhaps should be Pre-filtered for data points that do not fall within acceptable limits. – ryyker Jan 28 '15 at 18:41
  • @ryyker I tried to add some checks on P values, checking if it's > 0, but really it was ok. userdata is a parameter of SDL_Mixer, and I don't use it at all (it's used to pass additional parameters to my callback function, but I don't need it...). I also added a plot of the bipolar impulse train before integrating it... – ProGM Jan 28 '15 at 19:06
  • 1
    I've up-clicked your question just because in the context of what you are doing, it is presented very well. However, I wonder if you are limiting the number responses you will get by the quantity of information you are providing. I wonder if you can scope it down to address the core relevance of the problem? For what it is worth, I do not currently see a problem anywhere in the C code you have provided. And as long as the input file contains no noise or errors, the code should be predictable. – ryyker Jan 29 '15 at 00:01

0 Answers0