:: Re: [Frei0r] "rgbnoise" plugin
Góra strony
Delete this message
Reply to this message
Autor: Marko Cebokli
Data:  
Dla: Minimalistic plugin API for video effects
Temat: Re: [Frei0r] "rgbnoise" plugin
On Friday, September 28, 2012 05:54:07 PM Steinar H. Gunderson wrote:
> On Fri, Sep 28, 2012 at 06:50:30PM +0300, Janne Liljeblad wrote:
> >> 1. If you really want to compute three Gaussian noise values per pixel,



Since I am currently trying out various denoising algorithms for future Frei0r
plugins, I needed to make myself a noise generator, which can produce
different types of noise, to test them.

It uses a very fast shift register feedback type pseudo random generator.
For one iteration, it needs two memory reads, one bitwise XOR an one memory
write, plus cicular buffer pointer handling. I effectively runs 32 shift
registers in parallel, to get 32 bit random numbers.

Source code follows below.

Note that the Gaussian generator needs to generate 12 random numbers, and
division, and is a bit slow. I did it this way, to get good statistics for
testing, but I think you could just take 12 values from different parts of the
ring buffer and shift - the statistics will be miserable, but I doubt it will
make any visual difference.

In the long run, I intend to make a noise adding plugin using thisrandom
generator, that will be able to make many different types of noise, like
white, pink, blue, uniform, Gaussian, binary, salt&pepper, etc

Marko Cebokli

//GENERIRANJE PSEVDONAKLJUCNEGA SUMA
//PREDPOSTAVLJA 32 BITNE INT SPREMENLJIVKE

typedef struct
    {
    int b[256];        //circ buf za sh reg
    int p;            //kazalec v sh reg
    } prbb;


//----------------------------------------------------------
//generates uniformly distributed 32 bit pseudo random integers
//using 32 parallel offset LFSR prb generators of length 127
//at 1 GHz repeats itself after cca 5390000000000000000000 years
//generates n new values in each LFSR, that is n new 32bit int's
//n<=256, otherwise overwrites old values! (buffer size)
//(n>256 can be used for "flushing")
//call prime_prbg() before use.
void prbg(prbb *b, int n)
{
int i;

for (i=0;i<n;i++)
    {
    b->p=(b->p+1)&0xFF;
    b->b[(b->p+127)&0xFF] = b->b[(b->p+1)&0xFF] ^ b->b[b->p];
    }
}


//----------------------------------------------------------
//prime the LFSR generators for prbg()
//uses a 31 bit long auxiliary LFSR
//needs seed!=0    (zero seed will result output of zeros only)
//only lower 31 bits of seed are used
void prime_prbg(prbb *b, int seed)
{
int i,j,pr,x;


if (seed==0)
    {
    printf("ERROR!  Cannot prime with zero seed!!\n");
    }


pr=seed;
for (i=0;i<256;i++)
    {
    for (j=0;j<200;j++)
        {
        if ((pr&0x40000000)!=0)
            {if ((pr&0x08000000)!=0) x=0; else x=1;}
        else
            {if ((pr&0x08000000)!=0) x=1; else x=0;}
        pr=(pr<<1)+x;
        }
    b->b[i]=pr;
    }
b->p=0;
prbg(b,1024);
}


//----------------------------------------------------------
//makes approx gaussian noise from unifomly distributed
//32 bit integers generated by prbg()
//Zero mean, rms=1.0, out to +-6*rms
float gausnois(prbb *b)
{
int i,j;
float n;

n=0.0;
prbg(b,12);
for (i=0;i<12;i++)
    {
    j=b->p-11+i;
    if (j<0) j=j+256;
    if (j>=256) j=j-256;
    n=n+(float)b->b[j];
    }
return n/4294967296.0;
}