LancePutnam / Gamma

Generic (Sound) Synthesis Library
Other
458 stars 54 forks source link

CSine<> Amplitude drift #44

Open mhetrick opened 8 years ago

mhetrick commented 8 years ago

We're having issues with CSine<> changing amplitude very slowly over time, even with decay = -1. We're experiencing audible amplitude drift after 30+ minutes.

mhetrick commented 8 years ago

As a workaround, it appears that the amplitude drift doesn't occur when using CSine double.

LancePutnam commented 8 years ago

Yes, for very long decays, double precision is required. For no decay, since single precision may be faster (it is on all my machines), another workaround may be to normalize 'val' every so often. Since I can't think of an automatic way to prevent drift that doesn't incur extra overhead (on each sample), I've added a note to the CSine comment section.

mhetrick commented 8 years ago

We have no decay on ours. It runs away after 30 minutes with single precision. It turns out that double precision didn't fix it either, as it runs away after a longer period of time (even with no decay).

We'll look into automatic normalization and see if we can fix it that way without too much overhead.

mhetrick commented 8 years ago

Automatic normalization has fixed it for us.

However, new bug: Higher frequencies cause the sine wave to decay instead of increase in amplitude (even with decay = -1). I believe this is occurring with frequencies > (Nyquist/2.0).

Try the following:

`

include "../AudioApp.h"

include "Gamma/Delay.h"

include "Gamma/Filter.h"

include "Gamma/Oscillator.h"

using namespace gam;

typedef gam::Complex complex;

int main() {

int counter = 0;
complex val;
CSine<float> cSine;
gam::Domain::master().spu(44100);
cSine.freq(14000);

printf("Ten Samples at init\n");

for (int i = 0; i < 10; ++i)
{
    val = cSine();
    printf("value: %f %f\n", val.real(), val.imag());
}

for (int i = 0; i < 900000000; ++i)
{
    cSine();
}

printf("Ten Samples after 900000000\n");

for (int i = 0; i < 10; ++i)
{
    val = cSine();
    printf("value: %f %f\n", val.real(), val.imag());
}

} `