[sdiy] Simplest random source

Seb Francis seb at is-uk.com
Sat Nov 16 05:21:51 CET 2002


Thank you Harry, Magnus, Charlie for an analog solution :)  I really would like to do it this way if I can find a small enough circuit that works - after all I have the A/D for free as part of the PIC, and I've just got this feeling that electrons are a whole lot more random than digital logic.  I'll have a play with some of the suggested circuits (but in the morning Zzzz!).


Scott Gravenhorst wrote:

> My hint would be to use the microprocessor to emulate a shiftregister with
> XOR feedback.  Easy to do this in hardware too.

However since so many people have suggested software I've given it a second thought, and have been playing a little with Scott's suggestion.  I found this circuit using a 4006 and 3 XOR gates:
http://www.analog-synth.de/synths/mod2/trigdiv/dig_noise.gif

As a quick test I implemented it in TCL (source at the end), and it does indeed look to give good random numbers.  The next stage is to convert these to MIDI pitch bend messages to test out what the sequence really *sounds* like :)

The only drawback is lots of CPU cycles.  The shift register "clock" must cycle 16 times to get a 16bit random number.  Ok, so the DAC is only 14bit, and probably 12bit would be enough, but still thats a lot of cycles (I guess at least 120 instructions @ ~10 per cycle).

If you try and take a random number after each clock, by shifting the last random number by 1 bit and adding on the next shift-reg-xor output bit, the number series is still fairly random, but not as good - high and low numbers seem to clump together.  Again, the sound test will give much more clue than looking at a bunch of numbers.

Seb

P.S. If you want to run this source on normal tcl / tclsh, replace "out" with "puts -nonewline".


set shift1 0x01
set shift2 0x01
set shift3 0x01
set shift4 0x01

set buffer ""

for {set i 0} {$i < 5000} {incr i} {

 ## Output shift register contents
 #binary scan [binary format I1 $shift1] B* res
 #out ' [string range $res 28 end]'=
 #binary scan [binary format I1 $shift2] B* res
 #out '[string range $res 27 end]'=
 #binary scan [binary format I1 $shift3] B* res
 #out ' [string range $res 28 end]'=
 #binary scan [binary format I1 $shift4] B* res
 #out '[string range $res 27 end]'\n

 ## Shift each register
 set shift1 [expr {$shift1<<1}]
 set shift2 [expr {$shift2<<1}]
 set shift3 [expr {$shift3<<1}]
 set shift4 [expr {$shift4<<1}]

 ## Shift reg 1 bit4 -> xorB2
 set xorB2 [expr { ($shift1 & 0x10) == 0x10 } ]

 ## Shift reg 2 bit5 -> Shift reg 1 bit 0
 set shift1 [expr { $shift1 | (($shift2 & 0x20) == 0x20) } ]

 ## Shift reg 3 bit4 -> xorA2 + Shift reg 2 bit 0
 set xorA2 [expr { ($shift3 & 0x10) == 0x10 } ]
 set shift2 [expr { $shift2 | (($shift3 & 0x10) == 0x10) } ]

 ## Shift reg 4 bit5 -> xorB1 + Shift reg 3 bit 0
 set xorB1 [expr { ($shift4 & 0x20) == 0x20 } ]
 set shift3 [expr { $shift3 | (($shift4 & 0x20) == 0x20) } ]

 ## XOR bits together
 set bitout [expr { (($xorB1 ^ $xorB2) ^ 1) ^ $xorA2 }]

 ## XOR output -> Shift reg 4 bit 0
 set shift4 [expr { $shift4 | $bitout } ]

 append buffer $bitout

 ## Once we have 16bits, output number
 if {[string length $buffer] == 16} {
  #out "$buffer "
  binary scan [binary format B* $buffer] H* res
  out $res
  if {[info exists aNums($buffer)]} {
   out " (repeat)"
  }
  out \n
  set aNums($buffer) {}
  ## Empty buffer
  set buffer ""
 }
}




##################
## Alternative ending .. (shifting old random number left and adding 1 bit at a time)
##################

 set buffer $bitout[string range $buffer 0 14]

 ## Output number
 #out "$buffer "
 binary scan [binary format B* $buffer] H* res
 out $res
 if {[info exists aNums($buffer)]} {
  out " (repeat)"
 }
 out \n
 set aNums($buffer) {}
}




More information about the Synth-diy mailing list