[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: How is the IIgs beep generated?
Mitchell Spector wrote:
"Michael J. Mahon" <mjmahon@aol.com> wrote:
Mitchell Spector wrote:
Hmm, tried it on my Apple IIGS a moments ago (would have
tried it on the Apple IIc I rescued from a recycling center a few
weeks ago, but I just put it into storage with my other Apple II's).
Well, it's quite similar to the IIGS "bonk" yet not at all the
same. It still has that very distinctive Apple II speaker sound.
Difficult to describe, but I hear "Bonkzzzzzzt", "Bonkzzzzzt"
rather than a crisp and very defined "Bonk".
The more I listen to the GS's bell, the more I'm convinced
it's not something that can be reproduced on an Apple IIe.
Example, set the pitch in the Sound Control Panel to the
highest level. Try listening to it over and over, I've never
in all my years of Apple II gaming, programming and tinkering
heard a sound like that from the speaker (excluding, say,
digitized audio, though even then it wouldn't be as clear).
I don't know what parameters you were using, but...
Parameters? All I did was download the Applesoft BASIC
program you wrote (the second revision) and ran it as-is on
my Apple IIc (managed to dig it out over the weekend and
had a listen). It runs through the sound scale from high to
low. I didn't play with any of the parameters.
If you LISTed the program, you'd see that--like most sound routines--
the parameters are POKEd into page 0 prior to the CALL that actually
produces the sound.
At the time that I posted, I didn't have access to a IIgs, and
so didn't know what the actual frequency and duration of the
"bonk" was.
I just happened to get access to a IIgs this weekend.
The correct parameters for the default IIgs "bonk" are:
POKE 6,83
POKE 7,2
CALL 768
That reproduces it quite well. The volume is about 2/3 the max
volume of a raw beep, but the ear doesn't really care. ;-)
It's a similar approximation of the GS "bonk" bell (especially
the lower tones), but certainly not the same. :)
Try POKEing the parameters I suggested and give it a listen.
After listening to them side by side, I'll bet it's the best
approximation that can be produced with Apple II hardware.
I'm still curious how the tone is produced. Maybe it's standard
speaker toggling that is then filtered or enhanced somehow using
something unique to the GS's audio circurity?
The IIgs routine uses completely standard speaker toggling, combined
with linear decreases in speaker volume throughout the tone--which
only the IIgs hardware supports.
My routine does exactly the same thing, based on 21.3kHz pulse-width-
modulation. Many people (particularly those "of an age" ;-) cannot
hear the 21.3kHz pulses at all, but only the modulation, which is at
the "bonk" frequency. Ideally, one would use a low-pass filter to
remove all traces of the 21.3kHz "carrier", but we're trying to use
standard hardware...
I'm guessing that the primary difference is that on the IIgs, the
speaker is driven by an audio amplifier from the actual speaker toggle
logic level, while on all other Apple II's, the speaker is driven by
a Darlington driver with a peculiar AC-coupled, DC-clamped input.
The difference is increased when the toggling is low frequency.
The PWM approach assumes that the Apple II clock is constant
frequency, but that is not strictly true, since there is a stretched
cycle every horizontal line, or 62 cycles. This introduces a 15kHz
sub-cycle timing variation, causing an audible beat which is most
apparent under conditions of very low modulation (near silence).
The code I use to generate the "bonk" sound is:
**********************************************************
* *
* "Bonk" sound routine for Apple II *
* *
* Copyright Michael J. Mahon, 12/08/2009 *
* *
* Uses 21.3kHz PWM to synthesize a squarewave sound of *
* diminishing volume, mimicing the "bonk" IIgs sound. *
* *
* The PWM pulses are generated in 46-cycle loops, with *
* the high duty cycle pulses varying between 7 cycles *
* and 37 cycles, and the low duty cycle pulses always *
* 7 cycles. *
* *
* Sound generaton begins at maximum duty cycle (volume) *
* and diminshes by 1/15 on each volume step, until the *
* volume has been reduced to zero (equal high and low *
* duty cycle half-periods). *
* *
* Input parameters are: *
* 'hperiod' = Half-period of tone in 46-cycle samples *
* 'vperiods' = Tone (full) periods per volume step *
* *
* Since 15 volume steps are required to diminish the *
* volume to zero, the total sound duration is 15 times *
* 'vperiods' cycles of the generated tone. *
* *
**********************************************************
* Page zero data
hperiod equ $06 ; Half-period in samples (<129)
vperiods equ $07 ; Periods until vol step
vctr equ $08 ; Volume step counter
* Hardware definitions
SPKR equ $C030 ; Apple II speaker toggle
org $300
* Initialize
BONK lda #15 ; Init to 15 steps
sta vctr ; of dimishing volume.
lda #0 ; Init modified branches.
sta vinc+1
lda #hiduty-vdec-2 ; Point to hiduty
sta vdec+1
ldy hperiod ; Samples in half-period
dey ; minus 1.
tya ; Save half-period count.
ldx vperiods ; Countdown to volume step.
* Generate high duty-cycle half of squarewave
nop ; String of NOPs is target
nop ; of varying 'vdec' branch.
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
hidutym2 nop
hiduty sta SPKR ; Toggle speaker hi
vinc bpl *+2 ; <modified: 0..15> (always)
nop ; String of NOPs is target
nop ; of varying 'vinc' branch.
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
sta SPKR ; Toggle speaker lo
dey ; Count down half-period
vdec bpl hiduty ; <modified>
* Generate first low duty-cycle half cycle of squarewave
sta SPKR ; Toggle speaker hi
bpl *+2 ; (always)
sta SPKR ; Toggle speaker lo
dex ; Time to dec volume?
bne dnostep ; -No, delay then rejoin.
dec vctr ; -Yes, volume = zero?
beq return ; -Yes, return.
dec vdec+1 ; -No, decrease duty
inc vinc+1 ; cycle (volume).
ldx vperiods ; Reload vol step counter
nostep tay ; Reload half-period ctr
bne lodutym4 ; >0, gen more low pulses.
beq hidutym2 ; (always)
lodutym6 nop ; Kill 2 cycles
lodutym4 nop ; Kill 2 cycles
nop ; Kill 2 cycles
sta SPKR ; Toggle speaker hi
bpl *+2 ; (always)
sta SPKR ; Toggle speaker lo
jsr return ; Kill 12
jsr return ; Kill 12
dey ; Half-period expired?
bpl lodutym6 ; -No, keep looping.
tay ; -Yes, reset for hi loop
bpl hidutym2 ; (always)
dnostep jsr return ; Kill 18 cycles
nop
nop
nop
bne nostep ; and rejoin...
return rts
This code produces pulses in loops that are exactly 46 cycles long,
and varies the volume of the modulation by changing the "on" time
of the "high pulse" to the speaker from 37 cycles down to 7 cycles
in 15 steps of 2 cycles.
The parameters determine the audible frequency--the rate of switching
between the high duty cycle and the low duty cycle--and the number of
(audible) periods between decrements in volume.
-michael
NadaNet and AppleCrate II: parallel computing for Apple II computers!
Home page: http://home.comcast.net/~mjmahon
"The wastebasket is our most important design
tool--and it's seriously underused."