2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
20 static int OAL_inited = 0;
22 static ALCdevice *al_device = NULL;
23 static ALCcontext *al_context = NULL;
27 ALuint buf_id; // OpenAL buffer id
28 int chan_idx; // channel index this buffer is currently bound to
36 sound_buffer() : buf_id(0), chan_idx(-1), frequency(0), bits_per_sample(0),
37 nchannels(0), nseconds(0), nbytes(0)
42 static std::vector<sound_buffer> Buffers;
44 static std::vector<sound_channel> Channels;
45 static int channel_next_sig = 1;
47 extern void oal_efx_attach(ALuint source_id);
50 bool oal_check_for_errors(const char *location)
52 ALenum err = alGetError();
54 if (err != AL_NO_ERROR) {
56 const char *str = alGetString(err);
58 nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s\n", location, err, (str) ? str : "??"));
60 nprintf(("OpenAL", "AL-ERROR => 0x%x: %s\n", err, alGetString(err)));
69 static void oal_init_channels()
71 const int MAX_SOURCES = 32;
73 Channels.reserve(MAX_SOURCES);
75 for (int n = 0; n < MAX_SOURCES; n++) {
76 sound_channel n_channel;
78 alGenSources(1, &n_channel.source_id);
80 if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) {
84 Channels.push_back(n_channel);
88 int oal_init(int use_eax)
90 ALint ver_major = 0, ver_minor = 0;
96 nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" ));
98 alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &ver_major);
99 alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &ver_minor);
101 if ( (ver_major < 1) || (ver_minor < 1) ) {
102 nprintf(("Sound", "SOUND ==> Minimum supported OpenAL version is 1.1\n"));
106 al_device = alcOpenDevice(NULL);
108 if (al_device == NULL) {
109 nprintf(("Sound", "SOUND ==> Unable to open device!\n"));
110 nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device))));
114 al_context = alcCreateContext(al_device, NULL);
116 if (al_context == NULL) {
117 nprintf(("Sound", "SOUND ==> Unable to create context!\n"));
118 nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device))));
120 alcCloseDevice(al_device);
126 alcMakeContextCurrent(al_context);
138 oal_check_for_errors("oal_init() end");
149 oal_check_for_errors("oal_close() begin");
151 while ( !Channels.empty() ) {
152 ALuint sid = Channels.back().source_id;
156 alSourcei(sid, AL_BUFFER, 0);
158 alDeleteSources(1, &sid);
163 while ( !Buffers.empty() ) {
164 ALuint bid = Buffers.back().buf_id;
166 if ( alIsBuffer(bid) ) {
167 alDeleteBuffers(1, &bid);
175 oal_check_for_errors("oal_close() end");
180 alcMakeContextCurrent(NULL);
181 alcDestroyContext(al_context);
182 alcCloseDevice(al_device);
190 int oal_get_channel(int sig)
198 int size = (int)Channels.size();
200 for (i = 0; i < size; i++) {
201 if (Channels[i].sig == sig) {
204 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
206 if (status == AL_PLAYING) {
217 int oal_get_number_channels()
227 int size = (int)Channels.size();
229 for (i = 0; i < size; i++) {
230 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
232 if (status == AL_PLAYING) {
240 void oal_stop_buffer(int sid)
246 oal_check_for_errors("oal_stop_buffer() begin");
248 SDL_assert( sid >= 0 );
249 SDL_assert( sid < (int)Buffers.size() );
251 int cid = Buffers[sid].chan_idx;
254 ALuint source_id = Channels[cid].source_id;
256 alSourceStop(source_id);
257 alSourcei(source_id, AL_BUFFER, 0);
260 oal_check_for_errors("oal_stop_buffer() end");
263 void oal_stop_channel(int channel)
269 SDL_assert( channel >= 0 );
270 SDL_assert( channel < (int)Channels.size() );
272 oal_check_for_errors("oal_stop_channel() begin");
274 alSourceStop(Channels[channel].source_id);
276 alSourcei(Channels[channel].source_id, AL_BUFFER, 0);
277 Channels[channel].buf_idx = -1;
279 oal_check_for_errors("oal_stop_channel() end");
282 void oal_stop_channel_all()
288 int size = (int)Channels.size();
290 for (int i = 0; i < size; i++) {
295 int oal_get_buffer_size(int sid, int *size)
301 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
305 *size = Buffers[sid].nbytes;
310 int oal_get_channel_size(int channel)
316 if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
320 if (Channels[channel].buf_idx >= 0) {
321 return Buffers[Channels[channel].buf_idx].nbytes;
327 // -----------------------------------------------------------------------------
328 // Source properties *set functions
329 // -----------------------------------------------------------------------------
331 void oal_set_volume(int channel, float volume)
337 SDL_assert( channel >= 0 );
338 SDL_assert( channel < (int)Channels.size() );
340 oal_check_for_errors("oal_set_volume() begin");
342 alSourcef(Channels[channel].source_id, AL_GAIN, volume);
344 oal_check_for_errors("oal_set_volume() end");
347 void oal_set_pan(int channel, float pan)
353 SDL_assert( channel >= 0 );
354 SDL_assert( channel < (int)Channels.size() );
356 oal_check_for_errors("oal_set_pan() begin");
358 alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
360 oal_check_for_errors("oal_set_pan() end");
363 void oal_set_pitch(int channel, float pitch)
369 SDL_assert( channel >= 0 );
370 SDL_assert( channel < (int)Channels.size() );
372 oal_check_for_errors("oal_set_pitch() begin");
374 alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
376 oal_check_for_errors("oal_set_pitch() end");
379 void oal_set_play_position(int channel, int position)
385 SDL_assert( channel >= 0 );
386 SDL_assert( channel < (int)Channels.size() );
388 oal_check_for_errors("oal_set_play_position() begin");
390 alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
392 oal_check_for_errors("oal_set_play_position() end");
395 // -----------------------------------------------------------------------------
397 // -----------------------------------------------------------------------------
398 // Source properties *get functions
399 // -----------------------------------------------------------------------------
401 float oal_get_pitch(int channel)
409 SDL_assert( channel >= 0 );
410 SDL_assert( channel < (int)Channels.size() );
412 oal_check_for_errors("oal_get_pitch() begin");
414 alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
416 oal_check_for_errors("oal_get_pitch() end");
421 int oal_get_play_position(int channel)
433 //SDL_assert( channel >= 0 );
434 SDL_assert( channel < (int)Channels.size() );
436 oal_check_for_errors("oal_get_play_position() begin");
438 alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
440 if (alGetError() != AL_NO_ERROR) {
447 // -----------------------------------------------------------------------------
454 int oal_is_channel_playing(int channel)
462 SDL_assert( channel >= 0 );
463 SDL_assert( channel < (int)Channels.size() );
465 oal_check_for_errors("oal_is_channel_playing() begin");
467 alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
469 oal_check_for_errors("oal_is_channel_playing() end");
471 if (status == AL_PLAYING) {
478 void oal_chg_loop_status(int channel, int loop)
484 SDL_assert( channel >= 0 );
485 SDL_assert( channel < (int)Channels.size() );
487 oal_check_for_errors("oal_chg_loop_status() begin");
489 alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
492 Channels[channel].flags |= SND_FLAG_LOOPING;
494 Channels[channel].flags &= ~SND_FLAG_LOOPING;
497 oal_check_for_errors("oal_chg_loop_status() end");
500 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
503 float lowest_vol = 0.0f;
504 int lowest_vol_index = -1;
506 int instance_count = 0; // number of instances of sound already playing
507 float lowest_instance_vol = 1.0f;
508 int lowest_instance_vol_index = -1;
510 int first_free_channel = -1;
516 int size = (int)Channels.size();
518 oal_check_for_errors("oal_get_free_channel_idx() begin");
520 // Look for a channel to use to play this sample
521 for (i = 0; i < size; i++) {
522 sound_channel *chp = &Channels[i];
523 int looping = chp->flags & SND_FLAG_LOOPING;
525 if (chp->snd_id == 0) {
526 if (first_free_channel == -1) {
527 first_free_channel = i;
533 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
535 if ( (status != AL_PLAYING) && (status != AL_PAUSED) ) {
536 if (first_free_channel == -1) {
537 first_free_channel = i;
542 if (chp->snd_id == snd_id) {
545 if ( (chp->vol < lowest_instance_vol) && !looping ) {
546 lowest_instance_vol = chp->vol;
547 lowest_instance_vol_index = i;
551 if ( (chp->vol < lowest_vol) && !looping ) {
552 lowest_vol_index = i;
553 lowest_vol = chp->vol;
558 // determine the limit of concurrent instances of this sound
560 case SND_PRIORITY_MUST_PLAY:
564 case SND_PRIORITY_SINGLE_INSTANCE:
568 case SND_PRIORITY_DOUBLE_INSTANCE:
572 case SND_PRIORITY_TRIPLE_INSTANCE:
583 // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
584 if (instance_count >= limit) {
585 // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
586 if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) {
587 first_free_channel = lowest_instance_vol_index;
589 first_free_channel = -1;
592 // there is no limit barrier to play the sound, so see if we've ran out of channels
593 if (first_free_channel == -1) {
594 // stop the lowest volume instance to play our sound if priority demands it
595 if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) {
596 // Check if the lowest volume playing is less than the volume of the requested sound.
597 // If so, then we are going to trash the lowest volume sound.
598 if (Channels[lowest_vol_index].vol <= new_volume) {
599 first_free_channel = lowest_vol_index;
605 oal_check_for_errors("oal_get_free_channel_idx() end");
607 return first_free_channel;
610 // get a channel for use elsewhere (MVE playback, streaming audio, etc.)
611 sound_channel *oal_get_free_channel(float volume, int snd_id, int priority)
617 int chan = oal_get_free_channel_idx(volume, snd_id, priority);
623 SDL_assert( Channels[chan].source_id != 0 );
625 alSourceStop(Channels[chan].source_id);
626 alSourcei(Channels[chan].source_id, AL_BUFFER, 0);
628 if (Channels[chan].buf_idx >= 0) {
629 Buffers[Channels[chan].buf_idx].chan_idx = -1;
632 Channels[chan].vol = volume;
633 Channels[chan].priority = priority;
634 Channels[chan].last_position = 0;
635 Channels[chan].flags = 0;
636 Channels[chan].buf_idx = -1;
637 Channels[chan].snd_id = snd_id;
638 Channels[chan].sig = channel_next_sig++;
640 if (channel_next_sig < 0) {
641 channel_next_sig = 1;
644 return &Channels[chan];
647 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
651 unsigned int tag = 0, size = 0, next_chunk;
658 cfp = cfopen(filename, "rb");
661 nprintf(("Error", "Couldn't open '%s'\n", filename ));
665 // check for valid file type
666 id = cfread_int(cfp);
669 if (id != 0x46464952) {
670 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
678 // check for valid RIFF type
679 id = cfread_int(cfp);
682 if (id != 0x45564157) {
683 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
689 while ( !cfeof(cfp) ) {
690 tag = cfread_uint(cfp);
691 size = cfread_uint(cfp);
693 next_chunk = cftell(cfp) + size;
698 hdr.code = cfread_short(cfp);
699 hdr.num_channels = cfread_ushort(cfp);
700 hdr.sample_rate = cfread_uint(cfp);
701 hdr.bytes_per_second = cfread_uint(cfp);
702 hdr.block_align = cfread_ushort(cfp);
703 hdr.bits_per_sample = cfread_ushort(cfp);
706 hdr.extra_size = cfread_ushort(cfp);
709 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
710 SDL_assert( (*header) != NULL );
712 memcpy((*header), &hdr, sizeof(WAVE_chunk));
714 if (hdr.extra_size) {
715 (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
716 SDL_assert( (*header)->extra_data != NULL );
718 cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
728 (*dest) = (ubyte*) malloc (size);
729 SDL_assert( (*dest) != NULL );
731 cfread((*dest), size, 1, cfp);
736 // drop everything else
741 cfseek(cfp, next_chunk, CF_SEEK_SET);
749 static int oal_get_free_buffer()
755 int size = (int)Buffers.size();
757 for (int i = 0; i < size; i++) {
758 if (Buffers[i].buf_id == 0) {
765 Buffers.push_back(nbuf);
767 return (int)(Buffers.size()-1);
770 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
772 SDL_assert( final_size != NULL );
773 SDL_assert( header != NULL );
774 SDL_assert( si != NULL );
780 int buf_idx = oal_get_free_buffer();
788 sound_buffer *buf = &Buffers[buf_idx];
790 oal_check_for_errors("oal_load_buffer() begin");
792 alGenBuffers(1, &buf->buf_id);
794 if ( !buf->buf_id ) {
798 ALenum format = AL_INVALID;
804 // the below conversion variables are only used when the wav format is not PCM.
805 ubyte *convert_buffer = NULL; // storage for converted wav file
806 int convert_len; // num bytes of converted wav file
807 uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size)
810 switch (si->format) {
811 case WAVE_FORMAT_PCM: {
812 SDL_assert( si->data != NULL );
815 bps = si->avg_bytes_per_sec;
818 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
819 // swap 16-bit sound data
823 for (uint i=0; i<size; i=i+2) {
824 swap_tmp = (ushort*)(si->data + i);
825 *swap_tmp = INTEL_SHORT(*swap_tmp);
835 case WAVE_FORMAT_ADPCM: {
836 SDL_assert( si->data != NULL );
838 // this ADPCM decoder decodes to 16-bit only so keep that in mind
839 nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" ));
841 int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16);
843 // ACM conversion failed?
844 if ( (rc == -1) || (src_bytes_used != si->size) ) {
845 alDeleteBuffers(1, &buf->buf_id);
848 if (convert_buffer != NULL) {
849 free(convert_buffer);
856 bps = (((si->n_channels * bits) / 8) * si->sample_rate);
858 data = convert_buffer;
860 nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
866 nprintf(( "Sound", "Unsupported sound encoding\n" ));
867 alDeleteBuffers(1, &buf->buf_id);
872 // format is now in pcm
873 frequency = si->sample_rate;
876 if (si->n_channels == 2) {
877 format = AL_FORMAT_STEREO16;
878 } else if (si->n_channels == 1) {
879 format = AL_FORMAT_MONO16;
881 } else if (bits == 8) {
882 if (si->n_channels == 2) {
883 format = AL_FORMAT_STEREO8;
884 } else if (si->n_channels == 1) {
885 format = AL_FORMAT_MONO8;
889 if (format == AL_INVALID) {
890 alDeleteBuffers(1, &buf->buf_id);
893 if (convert_buffer != NULL) {
894 free(convert_buffer);
903 alBufferData(buf->buf_id, format, data, size, frequency);
906 buf->frequency = frequency;
907 buf->bits_per_sample = bits;
908 buf->nchannels = si->n_channels;
909 buf->nseconds = size / bps;
912 if (convert_buffer != NULL) {
913 free(convert_buffer);
916 oal_check_for_errors("oal_load_buffer() end");
921 void oal_unload_buffer(int sid)
927 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
931 oal_check_for_errors("oal_unload_buffer() begin");
933 sound_buffer *buf = &Buffers[sid];
936 if (buf->chan_idx >= 0) {
937 alSourceStop(Channels[buf->chan_idx].source_id);
938 alSourcei(Channels[buf->chan_idx].source_id, AL_BUFFER, 0);
942 alDeleteBuffers(1, &buf->buf_id);
946 oal_check_for_errors("oal_unload_buffer() end");
949 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
955 int buf_idx = oal_get_free_buffer();
961 sound_buffer *buf = &Buffers[buf_idx];
963 oal_check_for_errors("oal_load_buffer() begin");
965 alGenBuffers(1, &buf->buf_id);
967 if ( !buf->buf_id ) {
972 buf->frequency = frequency;
973 buf->bits_per_sample = bits_per_sample;
974 buf->nchannels = nchannels;
975 buf->nseconds = nseconds;
976 buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
981 int oal_lock_data(int sid, ubyte *data, int size)
987 oal_check_for_errors("oal_lock_data() begin");
989 SDL_assert( sid >= 0 );
990 SDL_assert( sid < (int)Buffers.size() );
992 ALuint buf_id = Buffers[sid].buf_id;
995 if (Buffers[sid].bits_per_sample == 16) {
996 if (Buffers[sid].nchannels == 2) {
997 format = AL_FORMAT_STEREO16;
998 } else if (Buffers[sid].nchannels == 1) {
999 format = AL_FORMAT_MONO16;
1003 } else if (Buffers[sid].bits_per_sample == 8) {
1004 if (Buffers[sid].nchannels == 2) {
1005 format = AL_FORMAT_STEREO8;
1006 } else if (Buffers[sid].nchannels == 1) {
1007 format = AL_FORMAT_MONO8;
1015 Buffers[sid].nbytes = size;
1017 alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1019 if ( oal_check_for_errors("oal_lock_data() end") ) {
1026 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1028 if ( !OAL_inited ) {
1032 SDL_assert( sid >= 0 );
1033 SDL_assert( sid < (int)Buffers.size() );
1035 oal_check_for_errors("oal_play() begin");
1037 int channel = oal_get_free_channel_idx(volume, snd_id, priority);
1043 sound_channel *chan = &Channels[channel];
1046 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1048 if (status == AL_PLAYING) {
1049 oal_stop_channel(channel);
1052 // set all the things
1054 chan->flags = flags;
1055 chan->priority = priority;
1056 chan->last_position = 0;
1057 chan->buf_idx = sid;
1058 chan->snd_id = snd_id;
1059 chan->sig = channel_next_sig++;
1061 Buffers[sid].chan_idx = channel;
1063 alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f);
1064 alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1065 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1066 alSourcef(chan->source_id, AL_GAIN, volume);
1067 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1068 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1069 alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE);
1071 // maybe attach source to reverb effect
1072 oal_efx_attach(chan->source_id);
1075 alSourcePlay(chan->source_id);
1077 if (channel_next_sig < 0) {
1078 channel_next_sig = 1;
1081 oal_check_for_errors("oal_play() end");
1086 int oal_play_3d( int sid, int snd_id, vector *pos, vector *vel, int min, int max, int looping, float max_volume, float estimated_vol, int priority)
1088 if ( !OAL_inited ) {
1092 SDL_assert( sid >= 0 );
1093 SDL_assert( sid < (int)Buffers.size() );
1095 oal_check_for_errors("oal_play_3d() begin");
1097 int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1103 sound_channel *chan = &Channels[channel];
1106 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1108 if (status == AL_PLAYING) {
1109 oal_stop_channel(channel);
1112 int flags = SND_FLAG_3D;
1115 flags |= SND_FLAG_LOOPING;
1118 // set all the things
1119 chan->vol = max_volume;
1120 chan->flags = flags;
1121 chan->priority = priority;
1122 chan->last_position = 0;
1123 chan->buf_idx = sid;
1124 chan->snd_id = snd_id;
1125 chan->sig = channel_next_sig++;
1127 Buffers[sid].chan_idx = channel;
1129 oal_update_source(channel, min, max, pos, vel);
1131 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1132 alSourcef(chan->source_id, AL_GAIN, max_volume);
1133 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1134 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE);
1135 alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE);
1137 // maybe attach source to reverb effect
1138 oal_efx_attach(chan->source_id);
1141 alSourcePlay(chan->source_id);
1143 if (channel_next_sig < 0) {
1144 channel_next_sig = 1;
1147 oal_check_for_errors("oal_play_3d() end");
1154 ALint state, current_position;
1156 if ( !OAL_inited ) {
1160 oal_check_for_errors("oal_do_frame() begin");
1162 int size = (int)Channels.size();
1164 // make sure there aren't any looping voice messages
1165 for (int i = 0; i < size; i++) {
1166 if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) {
1167 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state);
1169 if (state != AL_PLAYING) {
1173 alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, ¤t_position);
1175 if (current_position != 0) {
1176 if (current_position < Channels[i].last_position) {
1177 alSourceStop(Channels[i].source_id);
1179 Channels[i].last_position = current_position;
1185 oal_check_for_errors("oal_do_frame() end");
1188 int oal_update_source(int channel, int min, int max, vector *pos, vector *vel)
1190 if ( !OAL_inited ) {
1198 if ( !Channels[channel].flags & SND_FLAG_3D ) {
1202 ALuint source_id = Channels[channel].source_id;
1203 ALfloat rolloff = 1.0f;
1205 oal_check_for_errors("oal_update_source() begin");
1208 alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1212 alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1214 alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1221 const float MIN_GAIN = 0.05f;
1222 float minf = i2fl(min);
1223 float maxf = i2fl(max);
1225 // yep, just making this shit up
1226 rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN;
1228 if (rolloff < 0.0f) {
1233 alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff);
1235 alSourcei(source_id, AL_REFERENCE_DISTANCE, min);
1236 alSourcei(source_id, AL_MAX_DISTANCE, max);
1239 oal_check_for_errors("oal_update_source() end");
1244 int oal_update_listener(vector *pos, vector *vel, matrix *orient)
1246 if ( !OAL_inited ) {
1250 oal_check_for_errors("oal_update_listener() begin");
1253 alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1257 alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1261 ALfloat alOrient[6];
1263 alOrient[0] = orient->v.fvec.xyz.x;
1264 alOrient[1] = orient->v.fvec.xyz.y;
1265 alOrient[2] = -orient->v.fvec.xyz.z;
1267 alOrient[3] = orient->v.uvec.xyz.x;
1268 alOrient[4] = orient->v.uvec.xyz.y;
1269 alOrient[5] = -orient->v.uvec.xyz.z;
1271 alListenerfv(AL_ORIENTATION, alOrient);
1274 oal_check_for_errors("oal_update_listener() end");