lda #8
sta $d418 This code toggles the low bit of the output.
lda #9
sta $d418
Over an average of time, this is the same as:
lda #8.5 But we can't really do this.
sta $d418
This idea can be used to easily do 5 bit sound. Basically, we take a
5 bit sample, shift right, then add 0. If bit 0 was high,
it will increment the 4 bit number. Then as this adding takes place,
toggling bit 0, it will average out to give half a bit.
This is actually called pulse width modulation. It is a good example for illustrating sample dithering. For example, you can play TRUE 16 bit sound, even with one bit. To do this, take the 16 bit sample, add a 12 bit random number, then play the high 4 bits of this result. Also remember the clipping problem as mentioned above.
There are some more advanced technical issues to this. The kind of random number you choose affects the results. You need a triangle density function for perfect linearity (ie., for no distortion). This is the relationship of random numbers in the sequence, and does not affect the probability distribution, which should be equal. The choice of density function is a tradeoff between added noise and linearity. I used pulse density function in my demo, which is non-filtered random numbers, and it's ok but I can still hear some noise pumping.
Memory map:
3: start page of sample
4: end page of sample
5: sample period (remmber to play twice normal speed)
fb,fc: pointer to sample
start lda 3
sta $fc
lda #0
sta $fb ; initialize sample pointer
lda #$b
sta $d011 ; blank screen for better timing
sei ; disable interrupts for better timing
play lda ($fb),y
lsr
sta $d418 ; push sample
ldx 5
d dex
bne d
pha
nop
adc #0
cmp #$10
beq s1
sta $d418
bpl s
s1 nop
nop
nop
s pla
ldx 5
d1 dex
bne d1
iny
bne play
inc fc
lda fc
cmp 4
bne play
lda #$1b
sta $d011
cli
end rts