5 #include <math.h> // pow()
10 #include "audio_plugin.h"
13 #define SAMPLE_FORMAT FMT_S16_LE
15 #define SAMPLE_RATE 11025 // Hz
16 #define SAMPLE_CHANNELS 2
19 #define SAMPLE_TYPE char
21 #define SAMPLE_TYPE short
35 const char snd_prefixen[] = { 'P', 'P', 'A', 'S', 'S', 'S', 'M',
39 int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
40 int snd_MusicDevice, // current music card # (index to dmxCodes)
41 snd_SfxDevice, // current sfx card # (index to dmxCodes)
42 snd_MaxVolume, // maximum volume for sound
43 snd_MusicVolume; // maximum volume for music
44 int dmxCodes[NUM_SCARDS]; // the dmx code for a given card
46 int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables
47 int snd_Mport; // midi variables
49 extern boolean snd_MusicAvail, // whether music is available
50 snd_SfxAvail; // whether sfx are available
52 void I_PauseSong(int handle)
56 void I_ResumeSong(int handle)
60 void I_SetMusicVolume(int volume)
64 void I_SetSfxVolume(int volume)
74 int I_RegisterSong(void *data)
79 void I_UnRegisterSong(int handle)
83 int I_QrySongPlaying(int handle)
88 // Stops a song. MUST be called before I_UnregisterSong().
90 void I_StopSong(int handle)
94 void I_PlaySong(int handle, boolean looping)
107 unsigned char* begin; // pointers into Sample.firstSample
110 SAMPLE_TYPE* lvol_table; // point into vol_lookup
111 SAMPLE_TYPE* rvol_table;
113 unsigned int pitch_step;
114 unsigned int step_remainder; // 0.16 bit remainder of last step.
124 short freq; // always 11025
125 long length; // sample length
126 unsigned char firstSample;
130 extern OutputPlugin* get_oplugin_info();
131 static OutputPlugin* audioPI = 0;
132 static int audio_exit_thread = 1;
133 static pthread_t audio_thread;
137 Channel channel[ CHAN_COUNT ];
139 #define MAX_VOL 64 // 64 keeps our table down to 16Kb
140 SAMPLE_TYPE vol_lookup[ MAX_VOL * 256 ];
142 int steptable[ 256 ]; // Pitch to stepping lookup
145 #define BUF_LEN 256*2
148 void* audio_loop( void* arg )
160 end = (SAMPLE_TYPE*) (buf + BUF_LEN);
161 cend = channel + CHAN_COUNT;
163 while( ! audio_exit_thread )
165 begin = (SAMPLE_TYPE*) buf;
168 // Mix all the channels together.
174 for( ; chan < cend; chan++ )
176 // Check channel, if active.
179 // Get the sample from the channel.
180 sample = *chan->begin;
182 // Adjust volume accordingly.
183 dl += chan->lvol_table[ sample ];
184 dr += chan->rvol_table[ sample ];
186 // Increment sample pointer with pitch adjustment.
187 chan->step_remainder += chan->pitch_step;
188 chan->begin += chan->step_remainder >> 16;
189 chan->step_remainder &= 65535;
191 // Check whether we are done.
192 if( chan->begin >= chan->end )
195 //printf( " channel done %d\n", chan );
200 #if 0 //SAMPLE_FORMAT
201 if( dl > 127 ) dl = 127;
202 else if( dl < -128 ) dl = -128;
204 if( dr > 127 ) dr = 127;
205 else if( dr < -128 ) dr = -128;
207 if( dl > 0x7fff ) dl = 0x7fff;
208 else if( dl < -0x8000 ) dl = -0x8000;
210 if( dr > 0x7fff ) dr = 0x7fff;
211 else if( dr < -0x8000 ) dr = -0x8000;
218 // This write is expected to block.
219 audioPI->write_audio( buf, BUF_LEN );
226 // Gets lump nums of the named sound. Returns pointer which will be
227 // passed to I_StartSound() when you want to start an SFX. Must be
228 // sure to pass this to UngetSoundEffect() so that they can be
232 int I_GetSfxLumpNum(sfxinfo_t *sound)
234 return W_GetNumForName(sound->lumpname);
240 // Data is a pointer to a Sample structure.
241 // Volume ranges from 0 to 127.
242 // Separation (orientation/stereo) ranges from 0 to 255. 128 is balanced.
243 // Pitch ranges from 0 to 255. Normal is 128.
244 // Priority looks to be unused (always 0).
246 int I_StartSound( int id, void* data, int vol, int sep, int pitch, int priority)
248 // Relative time order to find oldest sound.
249 static unsigned int soundTime = 0;
257 // Find an empty channel, the oldest playing channel, or default to 0.
258 // Currently ignoring priority.
262 for( i = 0; i < CHAN_COUNT; i++ )
264 if( ! channel[ i ].begin )
269 if( channel[ i ].time < oldest )
272 oldest = channel[ i ].time;
276 sample = (Sample*) data;
277 chan = &channel[ chanId ];
279 I_UpdateSoundParams( chanId + 1, vol, sep, pitch );
281 // begin must be set last because the audio thread will access the channel
282 // once it is non-zero. Perhaps this should be protected by a mutex.
284 chan->pri = priority;
285 chan->time = soundTime;
286 chan->end = &sample->firstSample + sample->length;
287 chan->begin = &sample->firstSample;
292 printf( "I_StartSound %d: v:%d s:%d p:%d pri:%d | %d %d %d %d\n",
293 id, vol, sep, pitch, priority,
294 chanId, chan->pitch_step, sample->a, sample->freq );
300 void I_StopSound(int handle)
304 channel[ handle ].begin = 0;
307 int I_SoundIsPlaying(int handle)
311 return( channel[ handle ].begin != 0 );
314 void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
319 // Set left/right channel volume based on seperation.
321 sep += 1; // range 1 - 256
322 lvol = vol - ((vol * sep * sep) >> 16); // (256*256);
324 rvol = vol - ((vol * sep * sep) >> 16);
327 // Sanity check, clamp volume.
330 //printf( "rvol out of bounds %d, id %d\n", rvol, handle );
333 else if( rvol > 127 )
335 //printf( "rvol out of bounds %d, id %d\n", rvol, handle );
341 //printf( "lvol out of bounds %d, id %d\n", lvol, handle );
344 else if( lvol > 127 )
346 //printf( "lvol out of bounds %d, id %d\n", lvol, handle );
350 // Limit to MAX_VOL (64)
356 chan = &channel[ handle ];
357 chan->pitch_step = steptable[ pitch ];
358 chan->step_remainder = 0;
359 chan->lvol_table = &vol_lookup[ lvol * 256 ];
360 chan->rvol_table = &vol_lookup[ rvol * 256 ];
365 * SOUND STARTUP STUFF
370 // inits all sound stuff
372 void I_StartupSound (void)
376 snd_MusicDevice = snd_SfxDevice = 0;
378 if( M_CheckParm( "-nosound" ) )
380 ST_Message("I_StartupSound: Sound Disabled.\n");
385 ST_Message("I_StartupSound: Hope you hear a pop.\n");
387 /* Using get_oplugin_info() from oss.c. In the future this could
388 load from a real shared library plugin. */
389 audioPI = get_oplugin_info();
393 ok = audioPI->open_audio( SAMPLE_FORMAT, SAMPLE_RATE, SAMPLE_CHANNELS );
396 audio_exit_thread = 0;
397 pthread_create( &audio_thread, NULL, audio_loop, NULL);
401 fprintf( stderr, "I_StartupSound: failed\n" );
405 // shuts down all sound stuff
407 void I_ShutdownSound (void)
411 if( ! audio_exit_thread )
413 audio_exit_thread = 1;
414 pthread_join( audio_thread, NULL );
416 audioPI->close_audio();
420 void I_SetChannels(int channels)
425 // We always have CHAN_COUNT channels.
427 for( j = 0; j < CHAN_COUNT; j++ )
429 channel[ j ].begin = 0;
430 channel[ j ].end = 0;
431 channel[ j ].time = 0;
435 // This table provides step widths for pitch parameters.
436 steptablemid = steptable + 128;
437 for( j = -128; j < 128; j++ )
439 steptablemid[ j ] = (int) (pow( 2.0, (j/64.0) ) * 65536.0);
443 // Generate the volume lookup tables.
444 for( v = 0 ; v < MAX_VOL ; v++ )
446 for( j = 0; j < 256; j++ )
448 //vol_lookup[v*256+j] = 128 + ((v * (j-128)) / (MAX_VOL-1));
450 // Turn the unsigned samples into signed samples.
451 #if 0 // SAMPLE_FORMAT
452 vol_lookup[v*256+j] = (v * (j-128)) / (MAX_VOL-1);
454 vol_lookup[v*256+j] = (v * (j-128) * 256) / (MAX_VOL-1);
457 //printf("vol_lookup[%d*256+%d] = %d\n", v, j, vol_lookup[v*256+j]);