DSPRelated.com
Forums

Generation of digital white noise in Blackfin Fixed Point Processors

Started by bademiya July 18, 2006
Hi.

I am trying to generate digital white noise from a bunch of uniform random
numbers. However, when i write my code as belows for random number
generation between -1 and 1, it takes a long time to process the data.

        for(i = 0; i < 5000; i++){
	    data[i] = 2 * (((double)rand() / (double)RAND_MAX) - 0.5);
  	}
I understand its due to the fact that Blackfin processors are fixed-point
processors and by declaring the data as double, i am actually using a lot
of processor power. I have looked through and realised that i'm actually
required to change my data into the fractional format (i.e. Q.15 format).
However, i understand that division is not possible in fixed-point
processors. How do i resolve this issue?

Amit.
bademiya wrote:
> Hi. > > I am trying to generate digital white noise from a bunch of uniform random > numbers. However, when i write my code as belows for random number > generation between -1 and 1, it takes a long time to process the data. > > for(i = 0; i < 5000; i++){ > data[i] = 2 * (((double)rand() / (double)RAND_MAX) - 0.5); > } > I understand its due to the fact that Blackfin processors are fixed-point > processors and by declaring the data as double, i am actually using a lot > of processor power. I have looked through and realised that i'm actually > required to change my data into the fractional format (i.e. Q.15 format). > However, i understand that division is not possible in fixed-point > processors. How do i resolve this issue?
Google. For example, try "fixed-point division". --Randy
bademiya wrote:

> Hi. > > I am trying to generate digital white noise from a bunch of uniform random > numbers. However, when i write my code as belows for random number > generation between -1 and 1, it takes a long time to process the data. > > for(i = 0; i < 5000; i++){ > data[i] = 2 * (((double)rand() / (double)RAND_MAX) - 0.5); > } > I understand its due to the fact that Blackfin processors are fixed-point > processors and by declaring the data as double, i am actually using a lot > of processor power.
If the numbers in data[] really must be in the range [-1..+1], then double arithmertic is a must. You can speed this up by using multiplication instead of division: double fact = 1.0/RAND_MAX; for(i = 0; i < 5000; i++) { data[i] = 2 * (((double)rand() * fact - 0.5); } However, I'm very sure that the data go to a DAC with 8 or more bits, so an integer division should be good enough for the generation of noise: const int dac_bits = 8; /* or 12 or 16 or whatever the documentation says) */ const int range = 1 << dac_bits; const int max_amplitude = range / 2; const int fact = (double)range / (double)RAND_MAX; for(i = 0; i < 5000; i++) { data[i] = rand() * fact - max_amplitude; /* make sure that data[i] is within valid range though! */ ... } bye Andreas -- Andreas H&#4294967295;nnebeck | email: acmh@gmx.de ----- privat ---- | www : http://www.huennebeck-online.de Fax/Anrufbeantworter: 0721/151-284301 GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc PGP-Key: http://www.huennebeck-online.de/public_keys/pgp_andreas.asc
bademiya wrote:
> Hi. > > I am trying to generate digital white noise from a bunch of uniform random > numbers. However, when i write my code as belows for random number > generation between -1 and 1, it takes a long time to process the data. > > for(i = 0; i < 5000; i++){ > data[i] = 2 * (((double)rand() / (double)RAND_MAX) - 0.5); > } > I understand its due to the fact that Blackfin processors are fixed-point > processors and by declaring the data as double, i am actually using a lot > of processor power. I have looked through and realised that i'm actually > required to change my data into the fractional format (i.e. Q.15 format). > However, i understand that division is not possible in fixed-point > processors. How do i resolve this issue?
You can do fixed-point division on the Blackfin. It's not as straightforward as multiplication, though. It's covered in the documentation. You'll need to use assembler. Leon
bademiya wrote:
> I understand its due to the fact that Blackfin processors are fixed-point > processors and by declaring the data as double, i am actually using a lot > of processor power. I have looked through and realised that i'm actually > required to change my data into the fractional format (i.e. Q.15 format).
Fractional format ist just plain integers. 32767 means .999969482421875, and -32768 means -1.0. So, for fractional format, all you need to do is generate values between -32768 and +32767.
> However, i understand that division is not possible in fixed-point > processors. How do i resolve this issue?
You don't need division. Use a PRNG of your choice (with at least 16 bits output, standard rand() may only give you 15 bits), and pick a few bits from the inside. Here's a really simple one: int32_t seed = 0; int16_t my_rand() { seed = 134775813 * seed + 1; // PRNG return (int16_t) (seed >> 16); // pick upper bits } (The magic numbers 134775813 and 1 want to be chosen carefully, the above ones are stolen from the Turbo Pascal runtime library :-) I know it works fine for things like shuffling cards, but haven't tried yet how it sounds.) If you want smaller range, there's still no need to divide. To obtain a random number in range [0,N), generate a random number in range [0,2**B), multiply by N, and shift right B. To generate a random number between [-N,N), do the same with [-2**B,2**B): int16_t my_rand_range(int16_t range) { // returns value between -range (inclusive) // and +range (exclusive) return (my_rand() * range) >> 15; } "Multiply and shift right 15" is exactly the operation behind a fractional-mode multiplication (mult_fr1x16 from <fract.h>, if memory serves me right). If you keep using doubles, using the ldexp function may also be a win, but you should measure it first: ldexp is sort-of a floating-point shift operation, and it is comparatively fast. 'ldexp(my_rand(), -15)' gives you random numbers from [-1.0, +1.0). Stefan
Randy Yates wrote:
> bademiya wrote: >> Hi. >> >> I am trying to generate digital white noise from a bunch of uniform random >> numbers. However, when i write my code as belows for random number >> generation between -1 and 1, it takes a long time to process the data. >> >> for(i = 0; i < 5000; i++){ >> data[i] = 2 * (((double)rand() / (double)RAND_MAX) - 0.5); >> } >> I understand its due to the fact that Blackfin processors are fixed-point >> processors and by declaring the data as double, i am actually using a lot >> of processor power. I have looked through and realised that i'm actually >> required to change my data into the fractional format (i.e. Q.15 format). >> However, i understand that division is not possible in fixed-point >> processors. How do i resolve this issue? > > Google. For example, try "fixed-point division".
Bademiya, Write a decent (it needn't be excellent) single-precision RNG. A linear congruential RNG is simple and fast. A standard integer routine will provide outputs from -1 to (almost)1 if you construe the integer (0 to 65535) output as signed Q.15. To completely avoid DC bias, check for $FFFF and repeat the call to rand() if you find it. How to design an LC RNG is at http://tinyurl.com/gz73p. Not all that fit the criteria there are equally good, so find a recommended set of coefficients if you can. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
>bademiya wrote: > >> Hi. >> >> I am trying to generate digital white noise from a bunch of uniform
random
>> numbers. However, when i write my code as belows for random number >> generation between -1 and 1, it takes a long time to process the data. >> >> for(i = 0; i < 5000; i++){ >> data[i] = 2 * (((double)rand() / (double)RAND_MAX) - 0.5); >> } >> I understand its due to the fact that Blackfin processors are
fixed-point
>> processors and by declaring the data as double, i am actually using a
lot
>> of processor power. > >If the numbers in data[] really must be in the range [-1..+1], then >double arithmertic is a must. You can speed this up by using >multiplication instead of division: > >double fact = 1.0/RAND_MAX; >for(i = 0; i < 5000; i++) { > data[i] = 2 * (((double)rand() * fact - 0.5); >} > >However, I'm very sure that the data go to a DAC with 8 or more bits, >so an integer division should be good enough for the generation of
noise:
> >const int dac_bits = 8; /* or 12 or 16 or whatever the documentation
says) */
>const int range = 1 << dac_bits; >const int max_amplitude = range / 2; >const int fact = (double)range / (double)RAND_MAX; >for(i = 0; i < 5000; i++) { > data[i] = rand() * fact - max_amplitude; > /* make sure that data[i] is within valid range though! */ > ... >} > >bye >Andreas >-- >Andreas H&#4294967295;nnebeck | email: acmh@gmx.de >----- privat ---- | www : http://www.huennebeck-online.de >Fax/Anrufbeantworter: 0721/151-284301 >GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc >PGP-Key: http://www.huennebeck-online.de/public_keys/pgp_andreas.asc > >
Thanks! So in this case, do i declare data[] as a double variable or an interger? Amit.
bademiya wrote:

>>However, I'm very sure that the data go to a DAC with 8 or more bits, >>so an integer division should be good enough for the generation of > noise: >> >>const int dac_bits = 8; /* or 12 or 16 or whatever the documentation says) */ >>const int range = 1 << dac_bits; >>const int max_amplitude = range / 2; >>const int fact = (double)range / (double)RAND_MAX; >>for(i = 0; i < 5000; i++) { >> data[i] = rand() * fact - max_amplitude; >> /* make sure that data[i] is within valid range though! */ >> ... >>} > > So in this case, do i declare data[] as a double variable or an interger?
integer, of course. bye Andreas -- Andreas H&#4294967295;nnebeck | email: acmh@gmx.de ----- privat ---- | www : http://www.huennebeck-online.de Fax/Anrufbeantworter: 0721/151-284301 GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc PGP-Key: http://www.huennebeck-online.de/public_keys/pgp_andreas.asc