Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

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 }