macosx_snddma.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // mac_snddma.c
  19. // all other sound mixing is portable
  20. #include "../client/snd_local.h"
  21. #include <Carbon/Carbon.h>
  22. // For 'ri'
  23. #include "../renderer/tr_local.h"
  24. #import <Foundation/NSZone.h>
  25. // TJW - Different versions of SoundManager have different DMA buffer sizes. On MacOS X DP2,
  26. // the buffer size is 8K. On MacOS 9 it is much smaller. The SoundManager guy at Apple says
  27. // that the size of the buffer will be decreasing for final release to help get rid of latency.
  28. //#define MAX_MIXED_SAMPLES (0x8000 * 64)
  29. //#define SUBMISSION_CHUNK (0x100 * 64)
  30. // Original MacOS 9 sizes
  31. //#define MAX_MIXED_SAMPLES 0x8000
  32. //#define SUBMISSION_CHUNK 0x100
  33. static unsigned int submissionChunk;
  34. static unsigned int maxMixedSamples;
  35. static short *s_mixedSamples;
  36. static int s_chunkCount; // number of chunks submitted
  37. static SndChannel *s_sndChan;
  38. static ExtSoundHeader s_sndHeader;
  39. /*
  40. ===============
  41. S_Callback
  42. ===============
  43. */
  44. void S_Callback( SndChannel *sc, SndCommand *cmd )
  45. {
  46. SndCommand mySndCmd;
  47. SndCommand mySndCmd2;
  48. int offset;
  49. offset = ( s_chunkCount * submissionChunk ) & (maxMixedSamples-1);
  50. // queue up another sound buffer
  51. memset( &s_sndHeader, 0, sizeof( s_sndHeader ) );
  52. s_sndHeader.samplePtr = (void *)(s_mixedSamples + offset);
  53. s_sndHeader.numChannels = 2;
  54. s_sndHeader.sampleRate = rate22khz;
  55. s_sndHeader.loopStart = 0;
  56. s_sndHeader.loopEnd = 0;
  57. s_sndHeader.encode = extSH;
  58. s_sndHeader.baseFrequency = 1;
  59. s_sndHeader.numFrames = submissionChunk / 2;
  60. s_sndHeader.markerChunk = NULL;
  61. s_sndHeader.instrumentChunks = NULL;
  62. s_sndHeader.AESRecording = NULL;
  63. s_sndHeader.sampleSize = 16;
  64. mySndCmd.cmd = bufferCmd;
  65. mySndCmd.param1 = 0;
  66. mySndCmd.param2 = (int)&s_sndHeader;
  67. SndDoCommand( sc, &mySndCmd, true );
  68. // and another callback
  69. mySndCmd2.cmd = callBackCmd;
  70. mySndCmd2.param1 = 0;
  71. mySndCmd2.param2 = 0;
  72. SndDoCommand( sc, &mySndCmd2, true );
  73. s_chunkCount++; // this is the next buffer we will submit
  74. }
  75. /*
  76. ===============
  77. S_MakeTestPattern
  78. ===============
  79. */
  80. void S_MakeTestPattern( void ) {
  81. int i;
  82. float v;
  83. int sample;
  84. for ( i = 0 ; i < dma.samples / 2 ; i ++ ) {
  85. v = sin( M_PI * 2 * i / 64 );
  86. sample = v * 0x4000;
  87. ((short *)dma.buffer)[i*2] = sample;
  88. ((short *)dma.buffer)[i*2+1] = sample;
  89. }
  90. }
  91. /*
  92. ===============
  93. SNDDMA_Init
  94. ===============
  95. */
  96. qboolean SNDDMA_Init(void)
  97. {
  98. int err;
  99. cvar_t *bufferSize;
  100. cvar_t *chunkSize;
  101. chunkSize = ri.Cvar_Get( "s_chunksize", "8192", CVAR_ARCHIVE );
  102. bufferSize = ri.Cvar_Get( "s_buffersize", "65536", CVAR_ARCHIVE );
  103. if (!chunkSize->integer) {
  104. ri.Error(ERR_FATAL, "snd_chunkSize must be non-zero\n");
  105. }
  106. if (!bufferSize->integer) {
  107. ri.Error(ERR_FATAL, "snd_bufferSize must be non-zero\n");
  108. }
  109. if (chunkSize->integer >= bufferSize->integer) {
  110. ri.Error(ERR_FATAL, "snd_chunkSize must be less than snd_bufferSize\n");
  111. }
  112. if (bufferSize->integer % chunkSize->integer) {
  113. ri.Error(ERR_FATAL, "snd_bufferSize must be an even multiple of snd_chunkSize\n");
  114. }
  115. // create a sound channel
  116. s_sndChan = NULL;
  117. err = SndNewChannel( &s_sndChan, sampledSynth, initStereo, NewSndCallBackProc(S_Callback) );
  118. if ( err ) {
  119. return false;
  120. }
  121. submissionChunk = chunkSize->integer;
  122. maxMixedSamples = bufferSize->integer;
  123. s_mixedSamples = NSZoneMalloc(NULL, sizeof(*s_mixedSamples) * maxMixedSamples);
  124. dma.channels = 2;
  125. dma.samples = maxMixedSamples;
  126. dma.submission_chunk = submissionChunk;
  127. dma.samplebits = 16;
  128. dma.speed = 22050;
  129. dma.buffer = (byte *)s_mixedSamples;
  130. // que up the first submission-chunk sized buffer
  131. s_chunkCount = 0;
  132. S_Callback( s_sndChan, NULL );
  133. return qtrue;
  134. }
  135. /*
  136. ===============
  137. SNDDMA_GetDMAPos
  138. ===============
  139. */
  140. int SNDDMA_GetDMAPos(void) {
  141. return s_chunkCount * submissionChunk;
  142. }
  143. /*
  144. ===============
  145. SNDDMA_Shutdown
  146. ===============
  147. */
  148. void SNDDMA_Shutdown(void) {
  149. if ( s_sndChan ) {
  150. SndDisposeChannel( s_sndChan, true );
  151. s_sndChan = NULL;
  152. }
  153. }
  154. /*
  155. ===============
  156. SNDDMA_BeginPainting
  157. ===============
  158. */
  159. void SNDDMA_BeginPainting(void) {
  160. }
  161. /*
  162. ===============
  163. SNDDMA_Submit
  164. ===============
  165. */
  166. void SNDDMA_Submit(void) {
  167. }