[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