|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.