snd_sndio.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2010 Jacob Meuser <jakemsr@sdf.lonestar.org>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include <sys/types.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <fcntl.h>
  24. #include <poll.h>
  25. #include <errno.h>
  26. #include <sndio.h>
  27. #include "../qcommon/q_shared.h"
  28. #include "../client/snd_local.h"
  29. static struct sio_hdl *hdl;
  30. static int snd_inited;
  31. unsigned char *dma_buffer;
  32. size_t dma_buffer_size, dma_ptr;
  33. qboolean
  34. SNDDMA_Init(void)
  35. {
  36. struct sio_par par;
  37. int i;
  38. if (snd_inited)
  39. return qtrue;
  40. hdl = sio_open(NULL, SIO_PLAY, 1);
  41. if (hdl == NULL) {
  42. Com_Printf("Could not open sndio device\n");
  43. return qfalse;
  44. }
  45. sio_initpar(&par);
  46. par.bits = 16;
  47. par.sig = 1;
  48. par.pchan = 2;
  49. par.rate = 44100;
  50. par.le = SIO_LE_NATIVE;
  51. par.appbufsz = par.rate / 10; /* 1/10 second latency */
  52. if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
  53. Com_Printf("Error setting audio parameters\n");
  54. sio_close(hdl);
  55. return qfalse;
  56. }
  57. if ((par.pchan != 1 && par.pchan != 2) ||
  58. !((par.bits == 16 && par.sig == 1) ||
  59. (par.bits == 8 && par.sig == 0))) {
  60. Com_Printf("Could not set appropriate audio parameters\n");
  61. sio_close(hdl);
  62. return qfalse;
  63. }
  64. dma.speed = par.rate;
  65. dma.channels = par.pchan;
  66. dma.samplebits = par.bits;
  67. dma.submission_chunk = 1;
  68. /*
  69. * find the smallest power of two larger than the buffer size
  70. * and use it as the internal buffer's size
  71. */
  72. for (i = 1; i < par.appbufsz; i <<= 2)
  73. ; /* nothing */
  74. dma.samples = i * par.pchan;
  75. dma_buffer_size = dma.samples * dma.samplebits / 8;
  76. dma_buffer = calloc(1, dma_buffer_size);
  77. if (dma_buffer == NULL) {
  78. Com_Printf("Could not allocate audio ring buffer\n");
  79. return qfalse;
  80. }
  81. dma_ptr = 0;
  82. dma.buffer = dma_buffer;
  83. if (!sio_start(hdl)) {
  84. Com_Printf("Could not start audio\n");
  85. sio_close(hdl);
  86. return qfalse;
  87. }
  88. snd_inited = qtrue;
  89. return qtrue;
  90. }
  91. void
  92. SNDDMA_Shutdown(void)
  93. {
  94. if (snd_inited == qtrue) {
  95. sio_close(hdl);
  96. snd_inited = qfalse;
  97. }
  98. free(dma_buffer);
  99. }
  100. int
  101. SNDDMA_GetDMAPos(void)
  102. {
  103. if (!snd_inited)
  104. return (0);
  105. return (dma_ptr / (dma.samplebits / 8));
  106. }
  107. void
  108. SNDDMA_Submit(void)
  109. {
  110. struct pollfd pfd;
  111. size_t count, todo, avail;
  112. int n;
  113. n = sio_pollfd(hdl, &pfd, POLLOUT);
  114. while (poll(&pfd, n, 0) < 0 && errno == EINTR)
  115. ;
  116. if (!(sio_revents(hdl, &pfd) & POLLOUT))
  117. return;
  118. avail = dma_buffer_size;
  119. while (avail > 0) {
  120. todo = dma_buffer_size - dma_ptr;
  121. if (todo > avail)
  122. todo = avail;
  123. count = sio_write(hdl, dma_buffer + dma_ptr, todo);
  124. if (count == 0)
  125. break;
  126. dma_ptr += count;
  127. if (dma_ptr >= dma_buffer_size)
  128. dma_ptr -= dma_buffer_size;
  129. avail -= count;
  130. }
  131. }
  132. void
  133. SNDDMA_BeginPainting(void)
  134. {
  135. }