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 int snd_inited; 15 16 static int tryrates[] = { 11025, 22051, 44100, 8000 }; 17 18 qboolean SNDDMA_Init(void) 19 { 20 21 int rc; 22 int fmt; 23 int tmp; 24 int i; 25 char *s; 26 struct audio_buf_info info; 27 int caps; 28 29 snd_inited = 0; 30 31 // open /dev/dsp, confirm capability to mmap, and get size of dma buffer 32 33 audio_fd = open("/dev/dsp", O_RDWR); 34 if (audio_fd < 0) 35 { 36 perror("/dev/dsp"); 37 Con_Printf("Could not open /dev/dsp\n"); 38 return 0; 39 } 40 41 rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0); 42 if (rc < 0) 43 { 44 perror("/dev/dsp"); 45 Con_Printf("Could not reset /dev/dsp\n"); 46 close(audio_fd); 47 return 0; 48 } 49 50 if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1) 51 { 52 perror("/dev/dsp"); 53 Con_Printf("Sound driver too old\n"); 54 close(audio_fd); 55 return 0; 56 } 57 58 if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) 59 { 60 Con_Printf("Sorry but your soundcard can't do this\n"); 61 close(audio_fd); 62 return 0; 63 } 64 65 if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) 66 { 67 perror("GETOSPACE"); 68 Con_Printf("Um, can't do GETOSPACE?\n"); 69 close(audio_fd); 70 return 0; 71 } 72 73 shm = &sn; 74 shm->splitbuffer = 0; 75 76 // set sample bits & speed 77 78 s = getenv("QUAKE_SOUND_SAMPLEBITS"); 79 if (s) shm->samplebits = atoi(s); 80 else if ((i = COM_CheckParm("-sndbits")) != 0) 81 shm->samplebits = atoi(com_argv[i+1]); 82 if (shm->samplebits != 16 && shm->samplebits != 8) 83 { 84 ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt); 85 if (fmt & AFMT_S16_LE) shm->samplebits = 16; 86 else if (fmt & AFMT_U8) shm->samplebits = 8; 87 } 88 89 s = getenv("QUAKE_SOUND_SPEED"); 90 if (s) shm->speed = atoi(s); 91 else if ((i = COM_CheckParm("-sndspeed")) != 0) 92 shm->speed = atoi(com_argv[i+1]); 93 else 94 { 95 for (i=0 ; i<sizeof(tryrates)/4 ; i++) 96 if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break; 97 shm->speed = tryrates[i]; 98 } 99 100 s = getenv("QUAKE_SOUND_CHANNELS"); 101 if (s) shm->channels = atoi(s); 102 else if ((i = COM_CheckParm("-sndmono")) != 0) 103 shm->channels = 1; 104 else if ((i = COM_CheckParm("-sndstereo")) != 0) 105 shm->channels = 2; 106 else shm->channels = 2; 107 108 shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8); 109 shm->submission_chunk = 1; 110 111 // memory map the dma buffer 112 113 shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal 114 * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0); 115 if (!shm->buffer) 116 { 117 perror("/dev/dsp"); 118 Con_Printf("Could not mmap /dev/dsp\n"); 119 close(audio_fd); 120 return 0; 121 } 122 123 tmp = 0; 124 if (shm->channels == 2) 125 tmp = 1; 126 rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp); 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 if (tmp) 135 shm->channels = 2; 136 else 137 shm->channels = 1; 138 139 rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed); 140 if (rc < 0) 141 { 142 perror("/dev/dsp"); 143 Con_Printf("Could not set /dev/dsp speed to %d", shm->speed); 144 close(audio_fd); 145 return 0; 146 } 147 148 if (shm->samplebits == 16) 149 { 150 rc = AFMT_S16_LE; 151 rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc); 152 if (rc < 0) 153 { 154 perror("/dev/dsp"); 155 Con_Printf("Could not support 16-bit data. Try 8-bit.\n"); 156 close(audio_fd); 157 return 0; 158 } 159 } 160 else if (shm->samplebits == 8) 161 { 162 rc = AFMT_U8; 163 rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc); 164 if (rc < 0) 165 { 166 perror("/dev/dsp"); 167 Con_Printf("Could not support 8-bit data.\n"); 168 close(audio_fd); 169 return 0; 170 } 171 } 172 else 173 { 174 perror("/dev/dsp"); 175 Con_Printf("%d-bit sound not supported.", shm->samplebits); 176 close(audio_fd); 177 return 0; 178 } 179 180 // toggle the trigger & start her up 181 182 tmp = 0; 183 rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); 184 if (rc < 0) 185 { 186 perror("/dev/dsp"); 187 Con_Printf("Could not toggle.\n"); 188 close(audio_fd); 189 return 0; 190 } 191 tmp = PCM_ENABLE_OUTPUT; 192 rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); 193 if (rc < 0) 194 { 195 perror("/dev/dsp"); 196 Con_Printf("Could not toggle.\n"); 197 close(audio_fd); 198 return 0; 199 } 200 201 shm->samplepos = 0; 202 203 snd_inited = 1; 204 return 1; 205 206 } 207 208 int SNDDMA_GetDMAPos(void) 209 { 210 211 struct count_info count; 212 213 if (!snd_inited) return 0; 214 215 if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) 216 { 217 perror("/dev/dsp"); 218 Con_Printf("Uh, sound dead.\n"); 219 close(audio_fd); 220 snd_inited = 0; 221 return 0; 222 } 223 // shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1); 224 // fprintf(stderr, "%d \r", count.ptr); 225 shm->samplepos = count.ptr / (shm->samplebits / 8); 226 227 return shm->samplepos; 228 229 } 230 231 void SNDDMA_Shutdown(void) 232 { 233 if (snd_inited) 234 { 235 close(audio_fd); 236 snd_inited = 0; 237 } 238 } 239 240 /* 241 ============== 242 SNDDMA_Submit 243 244 Send sound to device if buffer isn't really the dma buffer 245 =============== 246 */ 247 void SNDDMA_Submit(void) 248 { 249 } 250 251