[sdiy] converting white noise to pink noise
Tom Wiltshire
tom at electricdruid.net
Fri Mar 7 12:09:33 CET 2008
On 7 Mar 2008, at 02:07, Dave Manley wrote:
>
> It is probably worth mentioning that it is easy to derive the next
> state for an arbitrary shift. You end up with specific functions
> per bit. In hardware this allows shifts by N bits per clock, which
> can be very useful.
>
> In software I guess you're stuck with iterating N times to get the
> Nth value, unless you had some special instructions that allowed
> bit selects without shifting/masking, or somehow made bit
> operations more efficient in some other way (multiple tapsmasks
> ANDed with current state combined with even/odd parity instructions?).
You can combine a number of iterations into one shift if you're
careful about where the taps are. On 16F PIC I've done a 32-bit LFSR
which shifts one full byte each time, which is much quicker since you
don't need shifts. Instead you can just move the whole byte to a new
location.
The trick is making sure that the XORed bits don't affect the part
that is being moved. For many tap positions this is the case, since
you can take taps from one end, and put the XORd result back in at
the beginning.
Example below for dsPIC ("RMG" stands for 'Random Modulation
Generator" in case you were wondering). The example uses a 64-bit
LFSR and shifts one entire word (16-bits) each time, so generates a
new 16-bit number each time through the code.
Regards,
Tom
;...........................................................
; PRIVATE ROUTINE: RMG_CalculateNoise
; This deals with the internal 64-bit Noise LFSR.
; Callling the routine causes a shift in the register and
; a new 16-bit output value to be placed in RMG_NOISE
;
; Note that during the rlc shifting, high bits from W3 finish
; up in W2. This isn't what we want, but as we only use W3,
; it doesn't matter.
;
; Also note that the taps used are from a XNOR shifter, so
; I invert my XOR result before putting it back into the LFSR.
;
; Register Usage
;................
; W0 Working Storage
; W1 Working Storage
; W2 Copy of LFSR2
; W3 Copy of LFSR3
;...........................................................
RMG_CalculateNoise:
; Copy the top two words where the XOR bits come from
mov RMG_LFSR2, W2
mov RMG_LFSR3, W3
; Now do the shifts to get the XOR words
rlc W2, W2
rlc W3, W3 ; Get bit 63
; XOR bits 64 and 63 into W0
mov RMG_LFSR3, W0 ; Get bit 64
xor W3, W0, W0
; Do more shifts
rlc W2, W2
rlc W3, W3 ; Bit 62 (unused)
rlc W2, W2
rlc W3, W3 ; Get bit 61
; XOR Bit 61 with the result from earlier
xor W3, W0, W0
; Do more shifts
rlc W2, W2
rlc W3, W3 ; Bit 60
; XOR Bit 60 with the result from earlier
xor W3, W0, W0
; Shift the whole register one word over
mov RMG_LFSR2, W1 ; Get word 2
mov W1, RMG_LFSR3 ; Put it in word 3
mov RMG_LFSR1, W1 ; Get word 1
mov W1, RMG_LFSR2 ; Put it in word 2
mov RMG_LFSR0, W1 ; Get word 0
mov W1, RMG_LFSR1 ; Put it in word 1
; Turn the XOR result into a XNOR
com W0, W0
; Move the XNOR result to the LSW
mov W0, RMG_LFSR0
; Read the top word as our result
mov RMG_LFSR3, W0
mov W0, RMG_NOISE
return
More information about the Synth-diy
mailing list