snd_irix.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include <dmedia/dmedia.h>
  2. #include <dmedia/audio.h>
  3. #include "../client/client.h"
  4. #include "../client/snd_loc.h"
  5. /*
  6. ==================
  7. SNDDM_Init
  8. Try to find a sound device to mix for.
  9. Returns false if nothing is found.
  10. Returns true and fills in the "dma" structure with information for the mixer.
  11. ==================
  12. */
  13. // must be power of two!
  14. #define QSND_SKID 2
  15. #define QSND_BUFFER_FRAMES 8192
  16. #define QSND_BUFFER_SIZE (QSND_BUFFER_FRAMES*2)
  17. #define UST_TO_BUFFPOS(ust) ((int)((ust) & (QSND_BUFFER_FRAMES - 1)) << 1)
  18. cvar_t *s_loadas8bit;
  19. cvar_t *s_khz;
  20. cvar_t *sndchannels;
  21. short int dma_buffer[QSND_BUFFER_SIZE];
  22. ALport sgisnd_aport = NULL;
  23. long long sgisnd_startframe;
  24. double sgisnd_frames_per_ns;
  25. long long sgisnd_lastframewritten = 0;
  26. qboolean SNDDMA_Init(void)
  27. {
  28. ALconfig ac = NULL;
  29. ALpv pvbuf[2];
  30. s_loadas8bit = Cvar_Get("s_loadas8bit", "16", CVAR_ARCHIVE);
  31. if ((int)s_loadas8bit->value)
  32. dma.samplebits = 8;
  33. else
  34. dma.samplebits = 16;
  35. if (dma.samplebits != 16) {
  36. Com_Printf("Don't currently support %i-bit data. Forcing 16-bit.\n",
  37. dma.samplebits);
  38. dma.samplebits = 16;
  39. Cvar_SetValue( "s_loadas8bit", false );
  40. }
  41. s_khz = Cvar_Get("s_khz", "0", CVAR_ARCHIVE);
  42. switch ((int)s_khz->value) {
  43. case 48:
  44. dma.speed = AL_RATE_48000;
  45. break;
  46. case 44:
  47. dma.speed = AL_RATE_44100;
  48. break;
  49. case 32:
  50. dma.speed = AL_RATE_32000;
  51. break;
  52. case 22:
  53. dma.speed = AL_RATE_22050;
  54. break;
  55. case 16:
  56. dma.speed = AL_RATE_16000;
  57. break;
  58. case 11:
  59. dma.speed = AL_RATE_11025;
  60. break;
  61. case 8:
  62. dma.speed = AL_RATE_8000;
  63. break;
  64. default:
  65. dma.speed = AL_RATE_22050;
  66. Com_Printf("Don't currently support %i kHz sample rate. Using %i.\n",
  67. (int)s_khz->value, (int)(dma.speed/1000));
  68. }
  69. sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
  70. dma.channels = (int)sndchannels->value;
  71. if (dma.channels != 2)
  72. Com_Printf("Don't currently support %i sound channels. Try 2.\n",
  73. sndchannels);
  74. /***********************/
  75. ac = alNewConfig();
  76. alSetChannels( ac, AL_STEREO );
  77. alSetSampFmt( ac, AL_SAMPFMT_TWOSCOMP );
  78. alSetQueueSize( ac, QSND_BUFFER_FRAMES );
  79. if (dma.samplebits == 8)
  80. alSetWidth( ac, AL_SAMPLE_8 );
  81. else
  82. alSetWidth( ac, AL_SAMPLE_16 );
  83. sgisnd_aport = alOpenPort( "Quake", "w", ac );
  84. if (!sgisnd_aport)
  85. {
  86. printf( "failed to open audio port!\n" );
  87. }
  88. // set desired sample rate
  89. pvbuf[0].param = AL_MASTER_CLOCK;
  90. pvbuf[0].value.i = AL_CRYSTAL_MCLK_TYPE;
  91. pvbuf[1].param = AL_RATE;
  92. pvbuf[1].value.ll = alIntToFixed( dma.speed );
  93. alSetParams( alGetResource( sgisnd_aport ), pvbuf, 2 );
  94. if (pvbuf[1].sizeOut < 0)
  95. printf( "illegal sample rate %d\n", dma.speed );
  96. sgisnd_frames_per_ns = dma.speed * 1.0e-9;
  97. dma.samples = sizeof(dma_buffer)/(dma.samplebits/8);
  98. dma.submission_chunk = 1;
  99. dma.buffer = (unsigned char *)dma_buffer;
  100. dma.samplepos = 0;
  101. alFreeConfig( ac );
  102. return true;
  103. }
  104. /*
  105. ==============
  106. SNDDMA_GetDMAPos
  107. return the current sample position (in mono samples, not stereo)
  108. inside the recirculating dma buffer, so the mixing code will know
  109. how many sample are required to fill it up.
  110. ===============
  111. */
  112. int SNDDMA_GetDMAPos(void)
  113. {
  114. long long ustFuture, ustNow;
  115. if (!sgisnd_aport) return( 0 );
  116. alGetFrameTime( sgisnd_aport, &sgisnd_startframe, &ustFuture );
  117. dmGetUST( (unsigned long long *)&ustNow );
  118. sgisnd_startframe -= (long long)((ustFuture - ustNow) * sgisnd_frames_per_ns);
  119. sgisnd_startframe += 100;
  120. //printf( "frame %ld pos %d\n", frame, UST_TO_BUFFPOS( sgisnd_startframe ) );
  121. return( UST_TO_BUFFPOS( sgisnd_startframe ) );
  122. }
  123. /*
  124. ==============
  125. SNDDMA_Shutdown
  126. Reset the sound device for exiting
  127. ===============
  128. */
  129. void SNDDMA_Shutdown(void)
  130. {
  131. if (sgisnd_aport) alClosePort( sgisnd_aport ), sgisnd_aport = NULL;
  132. return;
  133. }
  134. /*
  135. ==============
  136. SNDDMA_Submit
  137. Send sound to device if buffer isn't really the dma buffer
  138. ===============
  139. */
  140. extern int soundtime;
  141. void SNDDMA_Submit(void)
  142. {
  143. int nFillable, nFilled, nPos;
  144. int nFrames, nFramesLeft;
  145. unsigned endtime;
  146. if (!sgisnd_aport) return;
  147. nFillable = alGetFillable( sgisnd_aport );
  148. nFilled = QSND_BUFFER_FRAMES - nFillable;
  149. nFrames = dma.samples >> (dma.channels - 1);
  150. if (paintedtime - soundtime < nFrames)
  151. nFrames = paintedtime - soundtime;
  152. if (nFrames <= QSND_SKID) return;
  153. nPos = UST_TO_BUFFPOS( sgisnd_startframe );
  154. // dump re-written contents of the buffer
  155. if (sgisnd_lastframewritten > sgisnd_startframe)
  156. {
  157. alDiscardFrames( sgisnd_aport, sgisnd_lastframewritten - sgisnd_startframe );
  158. }
  159. else if ((int)(sgisnd_startframe - sgisnd_lastframewritten) >= QSND_BUFFER_FRAMES)
  160. {
  161. // blow away everything if we've underflowed
  162. alDiscardFrames( sgisnd_aport, QSND_BUFFER_FRAMES );
  163. }
  164. // don't block
  165. if (nFrames > nFillable) nFrames = nFillable;
  166. // account for stereo
  167. nFramesLeft = nFrames;
  168. if (nPos + nFrames * dma.channels > QSND_BUFFER_SIZE)
  169. {
  170. int nFramesAtEnd = (QSND_BUFFER_SIZE - nPos) >> (dma.channels - 1);
  171. alWriteFrames( sgisnd_aport, &dma_buffer[nPos], nFramesAtEnd );
  172. nPos = 0;
  173. nFramesLeft -= nFramesAtEnd;
  174. }
  175. alWriteFrames( sgisnd_aport, &dma_buffer[nPos], nFramesLeft );
  176. sgisnd_lastframewritten = sgisnd_startframe + nFrames;
  177. }
  178. void SNDDMA_BeginPainting (void)
  179. {
  180. }