🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.os.msdos.programmer
Article #2582

Re: IBM Sound

#2582
From: Everett Kaser
Date: Mon, 08 Oct 1990 17:38
289 lines
8369 bytes
Here's the code I use these days for doing sound in games (and most anything
else).  I write most of my code in C with a little assembly language thrown
in to spice up the mixture.  You should be able to adapt this code to most any
language/situation.  Basically, it takes over INT 1C, the interrupt called by
the 18.2 HZ timer tick.  The routine 'timerint' gets called 18.2 times a
second during the execution of the rest of your program.  Every time it gets
called, it increments a word called "TimePass", which can be set to 0 (or any
other value) by your program at any time.  Then, you can go into a loop waiting
for TimePass to reach a particular value.  This is an easy way to do simple
wait loops that will keep your code from running too fast on a REALLY fast
machine.  Additionally, 'timerint' looks at a flag called "BeepTime" which
contains the duration (in 1/18.2 seconds counts) of the current beep sequence.
If "BeepTime" is 0, there's no beep currently being executed.  Otherwise,
BeepTime is decremented.  If the decrement doesn't go to 0, 'timerint' returns
to your program.  When BeepTime decrements to 0, the next frequency/duration
pair is fetched from the integer array, the frequency count is sent to Timer2
while the duration count is stored in BeepTime.  When a frequency count of 0
is encountered, this signals the end of the beep sequence.  This allows
multiple-tone/complex sounds to be done, in the "background", while other
processing (video stuff, computation, etc) goes on at its own pace in the
"foreground".  You set up the beep sequence pointer using the BeepSeq function,
passing as an argument the address of the array of integers, which contains
pairs of frequency/duration values.  The frequency is value is actually the
counter value which gets stored into Timer2.  Hence, a value of 500 is a pretty
high pitched tone, whereas a value of 10,000 to 15,000 is a pretty low pitched
tone.  Again, one duration count is equal to 1/18.2 seconds.  So, a duration of
3 is about equal to 1/6 of a second, 9 is about equal to 1/2 second, etc.

Additionally, there is a variable called "BeepFlg" which can be set to 0 to
turn off all BeepSeq sound without having tests at every location from which
BeepSeq is called.  If you have any questions about all of this, feel free to
send me email, or give me a call.

Everett Kaser                   Hewlett-Packard Company
...hplabs!hp-pcd!everett        work: (503) 750-3569   Corvallis, Oregon
everett%hpcvra@hplabs.hp.com    home: (503) 928-5259   Albany, Oregon

---------------------- beginning of C module ----------------------------
/************************************************************************
 *									*
 ************************************************************************/

extern	int	BeepFlg, TimePass;

/************************************************************************
 *									*
 ************************************************************************/

int	ill_action[] = {10000, 2,0,0};
int	s1[] = {5000,1, 10000,1, 4000,1, 1000,1, 500,1, 0,0};
int	s2[] = {10000, 1,  8000, 1, 6000, 1,0,0};
int	s3[] = {500,1,8000,1,750,1,8000,1,1000,1,0,0};
int	s4[] = {15000,1,12000,1,9000,1,7000,1,3000,1,1000,1,300,1,100,1,0,0};
int	s5[] = {2000,4,200,1,0,0};
int	s6[] = {1000,1,8000,1,0,0};

/************************************************************************
 *									*
 ************************************************************************/
void	main(int argc, char *argv[], char *envp[]) {

	int	i;

	TakeTimer();		/* take over INT 1C 18.2 Hz timer tick */

	while( (i=getch()) != 27 ) {	/* while not ESC key */
		switch( i ) {
		 case '1':
			BeepSeq(s1);
			break;
		 case '2':
			BeepSeq(s2);
			break;
		 case '3':
			BeepSeq(s3);
			break;
		 case '4':
			BeepSeq(s4);
			break;
		 case '5':
			BeepSeq(s5);
			break;
		 case '6':
			BeepSeq(s6);
			break;
		 default:
			BeepSeq(ill_action);
			break;
		}
	}

	BeepOff();	/* make sure beeper is off before giving up Timer int */
	GiveTimer();	/* release INT 1C vector */
	exit(0);	/* return ERRORLEVEL = 0 */
}
------------------------------ end of C module -----------------------------
---------------------------- beginning of ASM module -----------------------
;************************************************************************
;* Copyright 1989 Everett Kaser.  All rights reserved.			*
;************************************************************************

page	60,132
title	TIMER/BEEPER/KEYBOARD routines
;
	.MODEL	COMPACT, C

;************************************************************************
;************************************************************************
; DATA SEGMENT
;************************************************************************
;************************************************************************
	.FARDATA MiscData

	public	TimePass
	public	BeepFlg
;
TimePass	dw	0
;
BeepFlg		dw	1
;
BeepTime	dw	0
BeepPtrOff	dw	0
BeepPtrSeg	dw	0
;
	.CODE
	assume	DS:MiscData

;************************************************************************
; take_timer();
;************************************************************************

old1coff	dw	?
old1cseg	dw	?

TakeTimer	PROC	uses DS ES SI DI
	mov	ax,351ch		; get old timer interrupt vector
	int	21h
	mov	cs:[old1cseg],es
	mov	cs:[old1coff],bx	; save it
	push	cs
	pop	ds
	lea	dx,timerint
	mov	ax,251ch		; take it
	int	21h

	mov	ax,MiscData
	mov	ds,ax

	ret
TakeTimer	endp

;************************************************************************
; give_timer();
;************************************************************************

GiveTimer	PROC	uses DS ES SI DI
	mov	ds,cs:[old1cseg]
	mov	dx,cs:[old1coff]
	mov	ax,251ch		; give it
	int	21h
	ret
GiveTimer	endp

;************************************************************************
; beep_seq(listptr);
;************************************************************************

BeepSeq		PROC	uses DS ES, listptr:dword
	mov	ax,MiscData
	mov	ds,ax

	cmp	BeepFlg,0
	jz	bsret

	les	dx,listptr	; get ptr to beep sequence
	mov	BeepPtrOff,dx	; save it
	mov	BeepPtrSeg,es

	call	beepsub
bsret:
	ret
BeepSeq		endp

;************************************************************************
; BeepOff();
;************************************************************************

BeepOff	PROC	uses DS
	mov	ax,MiscData
	mov	ds,ax

	mov	BeepTime,0
	in	al,61h			; else turn beeper off
	and	al,0fch
	out	61h,al
	ret
BeepOff	endp

;************************************************************************

timerint:
	push	es
	push	ds
	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	di
	push	bp

	mov	ax,MiscData
	mov	ds,ax

	inc	TimePass

	mov	ax,BeepTime
	or	ax,ax
	jz	texit
	dec	BeepTime
	jnz	texit

	call	beepsub
texit:
	pop	bp
	pop	di
	pop	si
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	pop	ds
	pop	es
	jmp	dword ptr cs:old1coff

;************************************************************************

beepsub:
	les	di,dword ptr BeepPtrOff	; get ptr to beep sequence
	mov	ax,es:[di]		; get next frequency
	add	di,2
	jnc	bsok1

	mov	bx,es
	add	bh,10h
	mov	es,bx
bsok1:
	or	ax,ax			; end of list?
	jnz	freqok			; jif no

	in	al,61h			; else turn beeper off
	and	al,0fch
	out	61h,al
	ret
freqok:
	push	ax

	mov	al,0b6h
	out	43h,al

	pop	ax

	out	42h,al			; write it to timer 2

	mov	al,ah
	out	42h,al

	in	al,61h
	or	al,3
	out	61h,al

	mov	ax,es:[di]		; get duration of beep
	add	di,2
	jnc	bsok2

	mov	bx,es
	add	bh,10h
	mov	es,bx
bsok2:
	mov	BeepTime,ax
	mov	BeepPtrOff,di
	mov	BeepPtrSeg,es
	ret

;************************************************************************

@curseg	ends
	end
------------------------------- end of ASM module -----------------------
Technical Details
Message-ID: <31600004@hpcvra.CV.HP.COM>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!sdd.hp.com!hp-pcd!hpcvra!everett
References: <8919@jarthur.Claremont.EDU>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!sdd.hp.com!hp-pcd!hpcvra!everett
From: everett@hpcvra.CV.HP.COM (Everett Kaser)
Newsgroups: comp.os.msdos.programmer
Subject: Re: IBM Sound
Message-ID: <31600004@hpcvra.CV.HP.COM>
Date: 8 Oct 90 17:38:18 GMT
References: <8919@jarthur.Claremont.EDU>
Organization: Hewlett-Packard Co., Corvallis, OR, USA
Lines: 289