|
|
1.1 root 1: #include <unistd.h>
2: #include <fcntl.h>
3: #include <stdlib.h>
4: #include <sys/types.h>
5: #include <sys/ioctl.h>
6: #include <sys/mman.h>
7: #include <sys/shm.h>
8: #include <sys/wait.h>
9: #include <linux/soundcard.h>
10: #include <stdio.h>
11: #include "quakedef.h"
12:
13: int audio_fd;
14: dma_t the_shm;
15: int snd_inited;
16:
17: static int tryrates[] = { 44100, 22050, 11025, 8000 };
18:
19: extern int desired_speed;
20: extern int desired_bits;
21: extern int desired_num_channels;
22:
23: qboolean SNDDMA_Init(void)
24: {
25:
26: int rc;
27: int fmt;
28: int tmp;
29: int i;
30: char *s;
31: struct audio_buf_info info;
32: int caps;
33:
34: snd_inited = 0;
35:
36: // open /dev/dsp, confirm capability to mmap, and get size of dma buffer
37:
38: audio_fd = open("/dev/dsp", O_RDWR);
39: if (audio_fd < 0)
40: {
41: perror("/dev/dsp");
42: Con_Printf("Could not open /dev/dsp\n");
43: return 0;
44: }
45:
46: rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
47: if (rc < 0)
48: {
49: perror("/dev/dsp");
50: Con_Printf("Could not reset /dev/dsp\n");
51: close(audio_fd);
52: return 0;
53: }
54:
55: if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
56: {
57: perror("/dev/dsp");
58: Con_Printf("Sound driver too old\n");
59: close(audio_fd);
60: return 0;
61: }
62:
63: if (!(caps & DSP_CAP_TRIGGER)
64: || !(caps & DSP_CAP_MMAP))
65: {
66: Con_Printf("Sorry but your soundcard can't do this\n");
67: close(audio_fd);
68: // return dmasim_Init();
69: return 0;
70: }
71:
72: if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
73: {
74: perror("GETOSPACE");
75: Con_Printf("Um, can't do GETOSPACE?\n");
76: close(audio_fd);
77: return 0;
78: }
79:
80: shm = &the_shm;
81: shm->splitbuffer = 0;
82:
83: // set sample bits & speed
84:
85: s = getenv("QUAKE_SOUND_SAMPLEBITS");
86: if (s) shm->samplebits = atoi(s);
87: else
88: {
89: ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
90: if (fmt & AFMT_S16_LE) shm->samplebits = 16;
91: else if (fmt & AFMT_U8) shm->samplebits = 8;
92: }
93:
94: s = getenv("QUAKE_SOUND_SPEED");
95: if (s) shm->speed = atoi(s);
96: else
97: {
98: shm->speed = desired_speed;
99: if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed))
100: {
101: for (i=0 ; i<sizeof(tryrates)/4 ; i++)
102: if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
103: shm->speed = tryrates[i];
104: }
105: }
106:
107: s = getenv("QUAKE_SOUND_CHANNELS");
108: if (s) shm->channels = atoi(s);
109: else shm->channels = 2;
110:
111: shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8);
112: shm->submission_chunk = 1;
113:
114: // memory map the dma buffer
115:
116: shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal
117: * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
118: if (!shm->buffer)
119: {
120: perror("/dev/dsp");
121: Con_Printf("Could not mmap /dev/dsp\n");
122: close(audio_fd);
123: return 0;
124: }
125:
126: rc = ioctl(audio_fd, SOUND_PCM_WRITE_CHANNELS, &shm->channels);
127: if (rc < 0)
128: {
129: perror("/dev/dsp");
130: Con_Printf("Could not set /dev/dsp to stereo=%d", shm->channels);
131: close(audio_fd);
132: return 0;
133: }
134:
135: rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
136: if (rc < 0)
137: {
138: perror("/dev/dsp");
139: Con_Printf("Could not set /dev/dsp speed to %d", shm->speed);
140: close(audio_fd);
141: return 0;
142: }
143:
144: if (shm->samplebits == 16)
145: {
146: rc = AFMT_S16_LE;
147: rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
148: if (rc < 0)
149: {
150: perror("/dev/dsp");
151: Con_Printf("Could not support 16-bit data. Try 8-bit.\n");
152: close(audio_fd);
153: return 0;
154: }
155: }
156: else if (shm->samplebits == 8)
157: {
158: rc = AFMT_U8;
159: rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
160: if (rc < 0)
161: {
162: perror("/dev/dsp");
163: Con_Printf("Could not support 8-bit data.\n");
164: close(audio_fd);
165: return 0;
166: }
167: }
168: else
169: {
170: perror("/dev/dsp");
171: Con_Printf("%d-bit sound not supported.", shm->samplebits);
172: close(audio_fd);
173: return 0;
174: }
175:
176: // toggle the trigger & start her up
177:
178: tmp = 0;
179: ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
180: tmp = PCM_ENABLE_OUTPUT;
181: ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
182:
183: shm->samplepos = 0;
184:
185: snd_inited = 1;
186: return 1;
187:
188: }
189:
190: int SNDDMA_GetDMAPos(void)
191: {
192:
193: struct count_info count;
194:
195: if (!snd_inited) return 0;
196:
197: if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
198: {
199: perror("/dev/dsp");
200: Con_Printf("Uh, sound dead.\n");
201: close(audio_fd);
202: snd_inited = 0;
203: return 0;
204: }
205: // shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
206: // fprintf(stderr, "%d \r", count.ptr);
207: shm->samplepos = count.ptr / (shm->samplebits / 8);
208:
209: return shm->samplepos;
210:
211: }
212:
213: void SNDDMA_Shutdown(void)
214: {
215: if (snd_inited)
216: {
217: close(audio_fd);
218: snd_inited = 0;
219: }
220: }
221:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.