Higher resolution volume

Probably the most technical forum around. It does not have to be coding related, or assembly code only. Just talk about how you can use the AY chip to do cool sounding things :)
User avatar
Twilighte
Game master
Posts: 819
Joined: Sat Jan 07, 2006 12:07 am
Location: Luton, UK
Contact:

Higher resolution volume

Post by Twilighte »

The problem is that the volume of a single channel is limited to 16 levels, the
possible resolve is to dither between adjacent levels to achieve an effective higher
resolution. The dithering will occur at 100hz and will take the form
of alternating volumes.

This may work extremely well at lower volumes but because the AY's volume is logarythmic
the alternation may be heard as a distortion of the volume changes at higher volumes.
However we shall see..

A falling volume from 15 to 14 would dither between the two levels

Code: Select all

15 15 15 15 14 15 15 14 15 14 15 14 14 15 14 14 14 14 14
------------___------___---___---______---_______________
The way to achieve the dithering will be to raise the resolution of the volume to 6 bit(0-63),
Extracting the real volume as the upper 4 bits leaving the 2 lower bits to specify the
dither to perform.

The 2 lower bits could use the following dithering patterns

Code: Select all

00 00000000
01 00010001
10 01010101
11 11011101
If the dither pattern was directly added to the base volume, then the base volume must not
exceed 14, lowering the range to 0-47 where 0 is 0+"00000000" and 47 is 14+"11011101".

This is ok i guess, and vastly better than 0-15.

Now for the code...

Code: Select all

#define hrVolume	$bfe0
#define OldAValue	$BFE1
#define OldXValue	$BFE2
#define via_porta	$030F
#define via_pcr	$030C

*=$B400
 .text
Driver
	;Use standard Oric IRQ and intercept at 24A
	sei
	lda #$4C	;Code for JMP
	sta $24A
	lda #<hrIRQVolumeRoutine
	sta $24B
	lda #>hrIRQVolumeRoutine
	sta $24C
	
	;Set defaults
	lda #00
	sta hrVolume
	lda #224
	sta DitherByteFrac
	
	;Re-enable irq and end
	cli
	rts
	

hrIRQVolumeRoutine
	sta OldAValue
	stx OldXValue
	
	; Progress Dither
	lda DitherByteFrac
	clc
	adc #32
	sta DitherByteFrac
	bcc skip1
	;Reload dither value
	lda hrVolume
	and #3
	tax
	lda DitherCode,x
	sta DitherBits

skip1	;Fetch higher resolution volume
	lda hrVolume
	
	;Extract actual 4 bit volume(VVVVXX)
	lsr
	lsr
	
	;Add dither 0 or 1
	lsr DitherBits
	adc #00
	
	;Send to AY Volume A
	ldx #8
	stx via_porta
	ldx #$FF
	stx via_pcr
	ldx #$DD
	stx via_pcr
	sta via_porta
	lda #$fd
	sta via_pcr
	stx via_pcr
	
	;Restore Registers and rti
	lda OldAValue
	ldx OldXValue
	rti

DitherCode
 .byt %00000000
 .byt %00010001
 .byt %01010101
 .byt %11011101
DitherByteFrac	.byt 0
DitherBits	.byt %00000000
Now from Basic you CALL #B400 then poke #BFE0 with the volume you want on Channel A only
between 0 and 47.
You can play any note using the BASIC sound commands.
The best excersize to start with is to lower the volume from 47 to 0..

Code: Select all

 10 CLOAD"HVR"
 20 CALL#B400
 30 PLAY7,0,0,0
 40 SOUND 1,100,0
 50 FOR A=47 TO 0 STEP -1
 60 POKE#BFE0,A
 70 PRINT A
 80 WAIT 10
 90 NEXT A
The Compiled code in a tap can be got here..
http://www.defence-force.org/ftp/forum/ ... os/hvr.tap
The source code (.s xa format) can be got here..
http://www.defence-force.org/ftp/forum/ ... olumeres.s

This routine has only been tested on Euphoric(Sounded pretty good but does 'hang on' a little to each real volume) at the moment. :P
If anyone could try on real Oric it would be cool to know how it sounds.
User avatar
Twilighte
Game master
Posts: 819
Joined: Sat Jan 07, 2006 12:07 am
Location: Luton, UK
Contact:

Post by Twilighte »

This same technique could be adapted to the Noise generator. On the AY the Noise generator has a 5 bit resolution and whilst this may sound high, steps can clearly be heard when "sweeping" the value :P

Once i get my Oric running next to my desktop i intend to experiement with this higher resolution with the end result being adapted to a new tracker for the creation of the music for Wurlde :P
Post Reply