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