snd_linux.c 5.0 KB

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