[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