|
|
1.1 root 1: /*-----------------------------------------------------------------------------
2: Talking BIOS device driver for the AT&T PC6300.
3: Copyright (C) Karl Dahlke 1987
4: This software may be freely used and distributed
5: for any non-profit purpose.
6: *-----------------------------------------------------------------------------
7: */
8:
9: /* noises.c: generate sounds */
10:
11: #ifndef MSDOS
12: #include <sys/io.h>
13: #endif
14: #include "speech.h"
15:
16: #define DRAINTICKS 770 /* how long till the squawker's internal buffer is drained */
17:
18: #define SF_LEN 32 /* length of sound fifo */
19:
20: long lbolt;
21: extern int mmticks;
22:
23: /* sound control variables, console only */
24: int sdtm_click = 1000;
25: int sdtm_charwait = 7200;
26: int sdtm_topcr = 370;
27: int sdtm_botcr = 50;
28: int sdtm_inccr = 3;
29: int sdnoises = 1, sdtones = 0;
30:
31: static short sf_fifo[SF_LEN];
32: static int sf_head, sf_tail;
33: static long wait_lbolt;
34:
35: static freqset(freq)
36: int freq;
37: {
38: short istate;
39: istate = sphi();
40: if(freq < 0) /* turn off tone */
41: outb(0x61, inb(0x61) & ~1);
42: else {
43: outb(0x43, 0xb6);
44: outb(0x42, freq);
45: outb(0x42, (freq>>8));
46: outb(0x61, inb(0x61) | 3);
47: }
48: spl(istate);
49: } /* freqset */
50:
51: static putfifo(p)
52: short *p;
53: {
54: short istate;
55: int i;
56:
57: istate = sphi();
58: i = sf_head;
59: while(*p) {
60: sf_fifo[i++] = *p++;
61: if(i == SF_LEN) i = 0;
62: if(i == sf_tail) goto done;
63: }
64: sf_head = i;
65:
66: done: spl(istate);
67: } /* putfifo */
68:
69: chkfifo()
70: {
71: int i;
72: short freq;
73: long l;
74:
75: if(wait_lbolt) {
76: l = lbolt - wait_lbolt;
77: if(l >= 0 || l <= -1000) {
78: freqset(-1);
79: wait_lbolt = 0;
80: }
81: }
82:
83: if(!wait_lbolt) {
84: if((i = sf_tail) != sf_head) {
85: freq = sf_fifo[i++];
86: if(i == SF_LEN) i = 0;
87: l = sf_fifo[i++];
88: if(i == SF_LEN) i = 0;
89: sf_tail = i;
90: freqset(freq);
91: wait_lbolt = lbolt + l;
92: }
93: }
94:
95: #ifndef MSDOS
96: if(wait_lbolt) mmticks = 1; /* higher resolution */
97: #endif
98: } /* chkfifo */
99:
100: /* generate a sound based on the passed parameter */
101: /* should only be called when the session runs on the console */
102: sdsound(sound)
103: {
104: short *snd_array;
105: static short startsnd[] = {
106: 2000,2,1800,2,1700,2,1500,2,1400,2,1300,2,1200,2,1000,2,900,2,800,2,700,2,500,2,0,0};
107: static short bellsnd[] = {662,5,0,0};
108: static short boundsnd[] = {376,3,316,3,0,0};
109: static short offsnd[] = {4800,3,0,0};
110: static short onsnd[] = {2000,10,0,0};
111: static short buzzsnd[] = {8000,20,0,0};
112: static short *soundlist[] = {
113: 0, 0, 0, bellsnd, boundsnd, offsnd, onsnd, buzzsnd, startsnd};
114:
115: if(!sdnoises) return;
116:
117: snd_array = soundlist[sound];
118: if(snd_array)
119: putfifo(snd_array);
120: if(sound == 2) sdcrsnd();
121: if(sound == 1) sdclick();
122: } /* sdsound */
123:
124: /* under Coherent, we return an integer that indicates whether
125: * the mmtime() function should take a real time break before processing
126: * this or subsequent characters.
127: * Sometimes the time to wait before creating the click of the next
128: * character extends beyond the next system clock interrupt.
129: * In this case, there is no point in hogging the CPU.
130: * Return 1 to indicate that this character should be held,
131: * and acted upon once the mmtime() function is reinvoked
132: * at the next system clock interrupt, unless of course there
133: * is something else ready to run, such as my wife's word processor
134: * or a cron job.
135: * A return of 0 means we waited the proper amount of time and made the
136: * corresponding noise, and we are ready to receive the next character.
137: * If we are running musical output, the tone must persist for approx
138: * a tenth of a second. Return 2 to indicate this. */
139: int sdcharsnd(c)
140: char c;
141: {
142: /* lr_notes[i] = 1193181/(1000*1.02^(i+1)) */
143: static short lr_notes[] = {
144: 1168,1146,1124,1102,1080,1060,1038,1018,1000,980,960,942,924,906,888,872,
145: 854,838,822,806,790,774,760,744,730,716,702,688,674,662,648,636,
146: 624,612,600,588,576,566,554,544,532,522,512,502,492,482,474,464,
147: 454,446,438,428,420,412,404,396,388,380,374,366,358,352,344,338};
148:
149: /* make sound accompanying this character */
150: if(sdtones) {
151: #ifdef MSDOS
152: while(wait_lbolt || sf_head != sf_tail) ;
153: #endif
154:
155: if(c == 13) sdsound(2);
156: if(c >= 96) c -= 32;
157: if(c > ' ') freqset(lr_notes[c-' ']);
158: #ifdef MSDOS
159: wait_lbolt = lbolt + 3;
160: #endif
161: return 8;
162: } /* sdtones */
163:
164: if(sdnoises) {
165: switch(c) {
166: case 7: sdsound(3); break;
167: case 13: sdsound(2); break;
168: default:
169: if(c > ' ')
170: sdsound(1);
171: break;
172: }
173: #ifdef MSDOS
174: sdpause(sdtm_charwait - sdtm_click);
175: #endif
176: return 4;
177: } /* noises on */
178:
179: return 0;
180: } /* sdcharsnd */
181:
182: /* sound for turning a mode on or off, from within a deferred function */
183: sdonoff(onoff)
184: {
185: if(!sdsession)
186: sdsound(5+onoff);
187: } /* sdonoff */
188:
189: draincheck(o)
190: struct SDCONTROL *o;
191: {
192: long l;
193:
194: if(o->drain_lbolt) {
195: l = lbolt - o->drain_lbolt;
196: if(l < 0 && l > -1000)
197: return 1; /* still waiting */
198: o->drain_lbolt = 0;
199: }
200:
201: return 0;
202: } /* draincheck */
203:
204: drainset(o)
205: struct SDCONTROL *o;
206: {
207: o->drain_lbolt = lbolt + DRAINTICKS;
208: } /* drainset */
209:
210: #ifndef MSDOS
211: /* return nonzero if we need to take a real time break */
212: mmgo1(c)
213: int c;
214: {
215: int rc; /* return value */
216: IO iob;
217:
218: /* set up for mmgo() */
219: iob.io_seg = IOSYS;
220: iob.io_ioc = 1;
221: iob.io.vbase = &c;
222: iob.io_flag = 0;
223:
224: mmticks = 1;
225:
226: rc = sdoutchar(0, c);
227:
228: if(rc & 2) {
229: int c1 = c;
230: c = '\33';
231: mmgo(&iob);
232: c = c1;
233: }
234:
235: if(rc & 1) mmgo(&iob);
236:
237: if(rc & 8) {
238: mmticks = 8;
239: return 0;
240: }
241:
242: if(rc & 4) {
243: mmticks = 1;
244: return 0;
245: }
246:
247: return 1;
248: } /* mmgo1 */
249:
250: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.