|
|
1.1.1.2 ! root 1: /* ! 2: Copyright (C) 1997-2001 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ 1.1 root 20: #include <dmedia/dmedia.h> 21: #include <dmedia/audio.h> 22: 23: #include "../client/client.h" 24: #include "../client/snd_loc.h" 25: 26: /* 27: ================== 28: SNDDM_Init 29: 30: Try to find a sound device to mix for. 31: Returns false if nothing is found. 32: Returns true and fills in the "dma" structure with information for the mixer. 33: ================== 34: */ 35: 36: // must be power of two! 37: #define QSND_SKID 2 38: #define QSND_BUFFER_FRAMES 8192 39: #define QSND_BUFFER_SIZE (QSND_BUFFER_FRAMES*2) 40: 41: #define UST_TO_BUFFPOS(ust) ((int)((ust) & (QSND_BUFFER_FRAMES - 1)) << 1) 42: 43: cvar_t *s_loadas8bit; 44: cvar_t *s_khz; 45: cvar_t *sndchannels; 46: 47: short int dma_buffer[QSND_BUFFER_SIZE]; 48: ALport sgisnd_aport = NULL; 49: long long sgisnd_startframe; 50: double sgisnd_frames_per_ns; 51: long long sgisnd_lastframewritten = 0; 52: 53: qboolean SNDDMA_Init(void) 54: { 55: ALconfig ac = NULL; 56: ALpv pvbuf[2]; 57: 58: s_loadas8bit = Cvar_Get("s_loadas8bit", "16", CVAR_ARCHIVE); 59: if ((int)s_loadas8bit->value) 60: dma.samplebits = 8; 61: else 62: dma.samplebits = 16; 63: 64: if (dma.samplebits != 16) { 65: Com_Printf("Don't currently support %i-bit data. Forcing 16-bit.\n", 66: dma.samplebits); 67: dma.samplebits = 16; 68: Cvar_SetValue( "s_loadas8bit", false ); 69: } 70: 71: s_khz = Cvar_Get("s_khz", "0", CVAR_ARCHIVE); 72: switch ((int)s_khz->value) { 73: case 48: 74: dma.speed = AL_RATE_48000; 75: break; 76: case 44: 77: dma.speed = AL_RATE_44100; 78: break; 79: case 32: 80: dma.speed = AL_RATE_32000; 81: break; 82: case 22: 83: dma.speed = AL_RATE_22050; 84: break; 85: case 16: 86: dma.speed = AL_RATE_16000; 87: break; 88: case 11: 89: dma.speed = AL_RATE_11025; 90: break; 91: case 8: 92: dma.speed = AL_RATE_8000; 93: break; 94: default: 95: dma.speed = AL_RATE_22050; 96: Com_Printf("Don't currently support %i kHz sample rate. Using %i.\n", 97: (int)s_khz->value, (int)(dma.speed/1000)); 98: } 99: 100: sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE); 101: dma.channels = (int)sndchannels->value; 102: if (dma.channels != 2) 103: Com_Printf("Don't currently support %i sound channels. Try 2.\n", 104: sndchannels); 105: 106: /***********************/ 107: 108: ac = alNewConfig(); 109: alSetChannels( ac, AL_STEREO ); 110: alSetSampFmt( ac, AL_SAMPFMT_TWOSCOMP ); 111: alSetQueueSize( ac, QSND_BUFFER_FRAMES ); 112: if (dma.samplebits == 8) 113: alSetWidth( ac, AL_SAMPLE_8 ); 114: else 115: alSetWidth( ac, AL_SAMPLE_16 ); 116: 117: sgisnd_aport = alOpenPort( "Quake", "w", ac ); 118: if (!sgisnd_aport) 119: { 120: printf( "failed to open audio port!\n" ); 121: } 122: 123: // set desired sample rate 124: pvbuf[0].param = AL_MASTER_CLOCK; 125: pvbuf[0].value.i = AL_CRYSTAL_MCLK_TYPE; 126: pvbuf[1].param = AL_RATE; 127: pvbuf[1].value.ll = alIntToFixed( dma.speed ); 128: alSetParams( alGetResource( sgisnd_aport ), pvbuf, 2 ); 129: if (pvbuf[1].sizeOut < 0) 130: printf( "illegal sample rate %d\n", dma.speed ); 131: 132: sgisnd_frames_per_ns = dma.speed * 1.0e-9; 133: 134: dma.samples = sizeof(dma_buffer)/(dma.samplebits/8); 135: dma.submission_chunk = 1; 136: 137: dma.buffer = (unsigned char *)dma_buffer; 138: 139: dma.samplepos = 0; 140: 141: alFreeConfig( ac ); 142: return true; 143: } 144: 145: 146: /* 147: ============== 148: SNDDMA_GetDMAPos 149: 150: return the current sample position (in mono samples, not stereo) 151: inside the recirculating dma buffer, so the mixing code will know 152: how many sample are required to fill it up. 153: =============== 154: */ 155: int SNDDMA_GetDMAPos(void) 156: { 157: long long ustFuture, ustNow; 158: if (!sgisnd_aport) return( 0 ); 159: alGetFrameTime( sgisnd_aport, &sgisnd_startframe, &ustFuture ); 160: dmGetUST( (unsigned long long *)&ustNow ); 161: sgisnd_startframe -= (long long)((ustFuture - ustNow) * sgisnd_frames_per_ns); 162: sgisnd_startframe += 100; 163: //printf( "frame %ld pos %d\n", frame, UST_TO_BUFFPOS( sgisnd_startframe ) ); 164: return( UST_TO_BUFFPOS( sgisnd_startframe ) ); 165: } 166: 167: /* 168: ============== 169: SNDDMA_Shutdown 170: 171: Reset the sound device for exiting 172: =============== 173: */ 174: void SNDDMA_Shutdown(void) 175: { 176: if (sgisnd_aport) alClosePort( sgisnd_aport ), sgisnd_aport = NULL; 177: return; 178: } 179: 180: /* 181: ============== 182: SNDDMA_Submit 183: 184: Send sound to device if buffer isn't really the dma buffer 185: =============== 186: */ 187: 188: extern int soundtime; 189: 190: void SNDDMA_Submit(void) 191: { 192: int nFillable, nFilled, nPos; 193: int nFrames, nFramesLeft; 194: unsigned endtime; 195: 196: if (!sgisnd_aport) return; 197: 198: nFillable = alGetFillable( sgisnd_aport ); 199: nFilled = QSND_BUFFER_FRAMES - nFillable; 200: 201: nFrames = dma.samples >> (dma.channels - 1); 202: 203: if (paintedtime - soundtime < nFrames) 204: nFrames = paintedtime - soundtime; 205: 206: if (nFrames <= QSND_SKID) return; 207: 208: nPos = UST_TO_BUFFPOS( sgisnd_startframe ); 209: 210: // dump re-written contents of the buffer 211: if (sgisnd_lastframewritten > sgisnd_startframe) 212: { 213: alDiscardFrames( sgisnd_aport, sgisnd_lastframewritten - sgisnd_startframe ); 214: } 215: else if ((int)(sgisnd_startframe - sgisnd_lastframewritten) >= QSND_BUFFER_FRAMES) 216: { 217: // blow away everything if we've underflowed 218: alDiscardFrames( sgisnd_aport, QSND_BUFFER_FRAMES ); 219: } 220: 221: // don't block 222: if (nFrames > nFillable) nFrames = nFillable; 223: 224: // account for stereo 225: nFramesLeft = nFrames; 226: if (nPos + nFrames * dma.channels > QSND_BUFFER_SIZE) 227: { 228: int nFramesAtEnd = (QSND_BUFFER_SIZE - nPos) >> (dma.channels - 1); 229: 230: alWriteFrames( sgisnd_aport, &dma_buffer[nPos], nFramesAtEnd ); 231: nPos = 0; 232: nFramesLeft -= nFramesAtEnd; 233: } 234: alWriteFrames( sgisnd_aport, &dma_buffer[nPos], nFramesLeft ); 235: 236: sgisnd_lastframewritten = sgisnd_startframe + nFrames; 237: } 238: 239: void SNDDMA_BeginPainting (void) 240: { 241: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.