Article View: comp.os.msdos.programmer
Article #2582Re: IBM Sound
From: Everett Kaser
Date: Mon, 08 Oct 1990 17:38
Date: Mon, 08 Oct 1990 17:38
289 lines
8369 bytes
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!everettReferences:
<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