snd_linux.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include <unistd.h>
  16. #include <fcntl.h>
  17. #include <stdlib.h>
  18. #include <sys/types.h>
  19. #include <sys/ioctl.h>
  20. #include <sys/mman.h>
  21. #include <sys/shm.h>
  22. #include <sys/wait.h>
  23. #include <linux/soundcard.h>
  24. #include <stdio.h>
  25. #include "quakedef.h"
  26. int audio_fd;
  27. int snd_inited;
  28. static int tryrates[] = { 11025, 22051, 44100, 8000 };
  29. qboolean SNDDMA_Init(void)
  30. {
  31. int rc;
  32. int fmt;
  33. int tmp;
  34. int i;
  35. char *s;
  36. struct audio_buf_info info;
  37. int caps;
  38. snd_inited = 0;
  39. // open /dev/dsp, confirm capability to mmap, and get size of dma buffer
  40. audio_fd = open("/dev/dsp", O_RDWR);
  41. if (audio_fd < 0)
  42. {
  43. perror("/dev/dsp");
  44. Con_Printf("Could not open /dev/dsp\n");
  45. return 0;
  46. }
  47. rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
  48. if (rc < 0)
  49. {
  50. perror("/dev/dsp");
  51. Con_Printf("Could not reset /dev/dsp\n");
  52. close(audio_fd);
  53. return 0;
  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. if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
  63. {
  64. Con_Printf("Sorry but your soundcard can't do this\n");
  65. close(audio_fd);
  66. return 0;
  67. }
  68. if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
  69. {
  70. perror("GETOSPACE");
  71. Con_Printf("Um, can't do GETOSPACE?\n");
  72. close(audio_fd);
  73. return 0;
  74. }
  75. shm = &sn;
  76. shm->splitbuffer = 0;
  77. // set sample bits & speed
  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. s = getenv("QUAKE_SOUND_SPEED");
  89. if (s) shm->speed = atoi(s);
  90. else if ((i = COM_CheckParm("-sndspeed")) != 0)
  91. shm->speed = atoi(com_argv[i+1]);
  92. else
  93. {
  94. for (i=0 ; i<sizeof(tryrates)/4 ; i++)
  95. if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
  96. shm->speed = tryrates[i];
  97. }
  98. s = getenv("QUAKE_SOUND_CHANNELS");
  99. if (s) shm->channels = atoi(s);
  100. else if ((i = COM_CheckParm("-sndmono")) != 0)
  101. shm->channels = 1;
  102. else if ((i = COM_CheckParm("-sndstereo")) != 0)
  103. shm->channels = 2;
  104. else shm->channels = 2;
  105. shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8);
  106. shm->submission_chunk = 1;
  107. // memory map the dma buffer
  108. shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal
  109. * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
  110. if (!shm->buffer || shm->buffer == (unsigned char *)-1)
  111. {
  112. perror("/dev/dsp");
  113. Con_Printf("Could not mmap /dev/dsp\n");
  114. close(audio_fd);
  115. return 0;
  116. }
  117. tmp = 0;
  118. if (shm->channels == 2)
  119. tmp = 1;
  120. rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
  121. if (rc < 0)
  122. {
  123. perror("/dev/dsp");
  124. Con_Printf("Could not set /dev/dsp to stereo=%d", shm->channels);
  125. close(audio_fd);
  126. return 0;
  127. }
  128. if (tmp)
  129. shm->channels = 2;
  130. else
  131. shm->channels = 1;
  132. rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
  133. if (rc < 0)
  134. {
  135. perror("/dev/dsp");
  136. Con_Printf("Could not set /dev/dsp speed to %d", shm->speed);
  137. close(audio_fd);
  138. return 0;
  139. }
  140. if (shm->samplebits == 16)
  141. {
  142. rc = AFMT_S16_LE;
  143. rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
  144. if (rc < 0)
  145. {
  146. perror("/dev/dsp");
  147. Con_Printf("Could not support 16-bit data. Try 8-bit.\n");
  148. close(audio_fd);
  149. return 0;
  150. }
  151. }
  152. else if (shm->samplebits == 8)
  153. {
  154. rc = AFMT_U8;
  155. rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
  156. if (rc < 0)
  157. {
  158. perror("/dev/dsp");
  159. Con_Printf("Could not support 8-bit data.\n");
  160. close(audio_fd);
  161. return 0;
  162. }
  163. }
  164. else
  165. {
  166. perror("/dev/dsp");
  167. Con_Printf("%d-bit sound not supported.", shm->samplebits);
  168. close(audio_fd);
  169. return 0;
  170. }
  171. // toggle the trigger & start her up
  172. tmp = 0;
  173. rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
  174. if (rc < 0)
  175. {
  176. perror("/dev/dsp");
  177. Con_Printf("Could not toggle.\n");
  178. close(audio_fd);
  179. return 0;
  180. }
  181. tmp = PCM_ENABLE_OUTPUT;
  182. rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
  183. if (rc < 0)
  184. {
  185. perror("/dev/dsp");
  186. Con_Printf("Could not toggle.\n");
  187. close(audio_fd);
  188. return 0;
  189. }
  190. shm->samplepos = 0;
  191. snd_inited = 1;
  192. return 1;
  193. }
  194. int SNDDMA_GetDMAPos(void)
  195. {
  196. struct count_info count;
  197. if (!snd_inited) return 0;
  198. if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
  199. {
  200. perror("/dev/dsp");
  201. Con_Printf("Uh, sound dead.\n");
  202. close(audio_fd);
  203. snd_inited = 0;
  204. return 0;
  205. }
  206. // shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
  207. // fprintf(stderr, "%d \r", count.ptr);
  208. shm->samplepos = count.ptr / (shm->samplebits / 8);
  209. return shm->samplepos;
  210. }
  211. void SNDDMA_Shutdown(void)
  212. {
  213. if (snd_inited)
  214. {
  215. close(audio_fd);
  216. snd_inited = 0;
  217. }
  218. }
  219. /*
  220. ==============
  221. SNDDMA_Submit
  222. Send sound to device if buffer isn't really the dma buffer
  223. ===============
  224. */
  225. void SNDDMA_Submit(void)
  226. {
  227. }