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;
48 bool oal_check_for_errors(const char *location)
50 ALenum err = alGetError();
52 if (err != AL_NO_ERROR) {
54 const char *str = alGetString(err);
56 nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s", location, err, (str) ? str : "??"));
58 nprintf(("OpenAL", "AL-ERROR => 0x%x: %s", err, alGetString(err)));
67 static void oal_init_channels()
69 const int MAX_SOURCES = 32;
71 Channels.reserve(MAX_SOURCES);
73 for (int n = 0; n < MAX_SOURCES; n++) {
74 sound_channel n_channel;
76 alGenSources(1, &n_channel.source_id);
78 if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) {
82 Channels.push_back(n_channel);
86 int oal_init(int use_eax)
88 ALint ver_major = 0, ver_minor = 0;
94 nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" ));
96 oal_check_for_errors("oal_init() begin");
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 while ( !Channels.empty() ) {
152 ALuint sid = Channels.back().source_id;
156 alGetSourcei(sid, AL_BUFFERS_PROCESSED, &processed);
158 while (processed > 0) {
159 alSourceUnqueueBuffers(sid, 1, &bid);
163 alSourcei(sid, AL_BUFFER, 0);
165 alDeleteSources(1, &sid);
170 while ( !Buffers.empty() ) {
171 ALuint bid = Buffers.back().buf_id;
173 alDeleteBuffers(1, &bid);
181 alcMakeContextCurrent(NULL);
182 alcDestroyContext(al_context);
183 alcCloseDevice(al_device);
191 int oal_get_channel(int sig)
199 int size = (int)Channels.size();
201 for (i = 0; i < size; i++) {
202 if (Channels[i].sig == sig) {
205 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
207 if (status == AL_PLAYING) {
218 int oal_get_number_channels()
228 int size = (int)Channels.size();
230 for (i = 0; i < size; i++) {
231 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
233 if (status == AL_PLAYING) {
241 void oal_stop_buffer(int sid)
247 oal_check_for_errors("oal_stop_buffer() begin");
249 SDL_assert( sid >= 0 );
250 SDL_assert( sid < (int)Buffers.size() );
252 int cid = Buffers[sid].chan_idx;
255 ALuint source_id = Channels[cid].source_id;
257 alSourceStop(source_id);
260 oal_check_for_errors("oal_stop_buffer() end");
263 void oal_stop_channel(int channel)
272 SDL_assert( channel >= 0 );
273 SDL_assert( channel < (int)Channels.size() );
275 oal_check_for_errors("oal_stop_channel() begin");
277 alSourceStop(Channels[channel].source_id);
279 // if this channel was used for streaming, make sure to unqueue any buffers
280 if (Channels[channel].snd_id < 0) {
281 alGetSourcei(Channels[channel].source_id, AL_BUFFERS_PROCESSED, &processed);
283 while (processed > 0) {
284 alSourceUnqueueBuffers(Channels[channel].source_id, 1, &bid);
289 oal_check_for_errors("oal_stop_channel() end");
292 void oal_stop_channel_all()
298 int size = (int)Channels.size();
300 for (int i = 0; i < size; i++) {
305 int oal_get_buffer_size(int sid, int *size)
311 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
315 *size = Buffers[sid].nbytes;
320 int oal_get_channel_size(int channel)
326 if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
330 if (Channels[channel].buf_idx >= 0) {
331 return Buffers[Channels[channel].buf_idx].nbytes;
337 // -----------------------------------------------------------------------------
338 // Source properties *set functions
339 // -----------------------------------------------------------------------------
341 void oal_set_volume(int channel, float volume)
347 SDL_assert( channel >= 0 );
348 SDL_assert( channel < (int)Channels.size() );
350 oal_check_for_errors("oal_set_volume() begin");
352 alSourcef(Channels[channel].source_id, AL_GAIN, volume);
354 oal_check_for_errors("oal_set_volume() end");
357 void oal_set_pan(int channel, float pan)
363 SDL_assert( channel >= 0 );
364 SDL_assert( channel < (int)Channels.size() );
366 oal_check_for_errors("oal_set_pan() begin");
368 alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
370 oal_check_for_errors("oal_set_pan() end");
373 void oal_set_pitch(int channel, float pitch)
379 SDL_assert( channel >= 0 );
380 SDL_assert( channel < (int)Channels.size() );
382 oal_check_for_errors("oal_set_pitch() begin");
384 alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
386 oal_check_for_errors("oal_set_pitch() end");
389 void oal_set_play_position(int channel, int position)
395 SDL_assert( channel >= 0 );
396 SDL_assert( channel < (int)Channels.size() );
398 oal_check_for_errors("oal_set_play_position() begin");
400 alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
402 oal_check_for_errors("oal_set_play_position() end");
405 void oal_set_source_properties_all(ALenum param, ALint *props)
411 oal_check_for_errors("oal_set_source_properties_all() begin");
413 int size = (int)Channels.size();
415 // make sure there aren't any looping voice messages
416 for (int i = 0; i < size; i++) {
417 alSourceiv(Channels[i].source_id, param, props);
420 oal_check_for_errors("oal_set_source_properties_all() end");
423 // -----------------------------------------------------------------------------
425 // -----------------------------------------------------------------------------
426 // Source properties *get functions
427 // -----------------------------------------------------------------------------
429 float oal_get_pitch(int channel)
437 SDL_assert( channel >= 0 );
438 SDL_assert( channel < (int)Channels.size() );
440 oal_check_for_errors("oal_get_pitch() begin");
442 alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
444 oal_check_for_errors("oal_get_pitch() end");
449 int oal_get_play_position(int channel)
461 //SDL_assert( channel >= 0 );
462 SDL_assert( channel < (int)Channels.size() );
464 oal_check_for_errors("oal_get_play_position() begin");
466 alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
468 if (alGetError() != AL_NO_ERROR) {
475 // -----------------------------------------------------------------------------
482 int oal_is_channel_playing(int channel)
490 SDL_assert( channel >= 0 );
491 SDL_assert( channel < (int)Channels.size() );
493 oal_check_for_errors("oal_is_channel_playing() begin");
495 alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
497 oal_check_for_errors("oal_is_channel_playing() end");
499 if (status == AL_PLAYING) {
506 void oal_chg_loop_status(int channel, int loop)
512 SDL_assert( channel >= 0 );
513 SDL_assert( channel < (int)Channels.size() );
515 oal_check_for_errors("oal_chg_loop_status() begin");
517 alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
520 Channels[channel].flags |= SND_FLAG_LOOPING;
522 Channels[channel].flags &= ~SND_FLAG_LOOPING;
525 oal_check_for_errors("oal_chg_loop_status() end");
528 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
531 float lowest_vol = 0.0f;
532 int lowest_vol_index = -1;
534 int instance_count = 0; // number of instances of sound already playing
535 float lowest_instance_vol = 1.0f;
536 int lowest_instance_vol_index = -1;
538 int first_free_channel = -1;
540 int size = (int)Channels.size();
542 oal_check_for_errors("oal_get_free_channel_idx() begin");
544 // Look for a channel to use to play this sample
545 for (i = 0; i < size; i++) {
546 sound_channel *chp = &Channels[i];
547 int looping = chp->flags & SND_FLAG_LOOPING;
549 if (chp->snd_id == 0) {
550 if (first_free_channel == -1) {
551 first_free_channel = i;
557 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
559 if (status != AL_PLAYING) {
560 if (first_free_channel == -1) {
561 first_free_channel = i;
566 if (chp->snd_id == snd_id) {
569 if ( (chp->vol < lowest_instance_vol) && !looping ) {
570 lowest_instance_vol = chp->vol;
571 lowest_instance_vol_index = i;
575 if ( (chp->vol < lowest_vol) && !looping ) {
576 lowest_vol_index = i;
577 lowest_vol = chp->vol;
582 // determine the limit of concurrent instances of this sound
584 case SND_PRIORITY_MUST_PLAY:
588 case SND_PRIORITY_SINGLE_INSTANCE:
592 case SND_PRIORITY_DOUBLE_INSTANCE:
596 case SND_PRIORITY_TRIPLE_INSTANCE:
607 // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
608 if (instance_count >= limit) {
609 // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
610 if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) {
611 first_free_channel = lowest_instance_vol_index;
613 first_free_channel = -1;
616 // there is no limit barrier to play the sound, so see if we've ran out of channels
617 if (first_free_channel == -1) {
618 // stop the lowest volume instance to play our sound if priority demands it
619 if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) {
620 // Check if the lowest volume playing is less than the volume of the requested sound.
621 // If so, then we are going to trash the lowest volume sound.
622 if (Channels[lowest_vol_index].vol <= new_volume) {
623 first_free_channel = lowest_vol_index;
629 oal_check_for_errors("oal_get_free_channel_idx() end");
631 return first_free_channel;
634 // get a channel for use elsewhere (MVE playback, streaming audio, etc.)
635 sound_channel *oal_get_free_channel(float volume, int snd_id, int priority)
641 int chan = oal_get_free_channel_idx(volume, snd_id, priority);
647 SDL_assert( Channels[chan].source_id != 0 );
649 Channels[chan].buf_idx = -1;
650 Channels[chan].snd_id = -1;
651 Channels[chan].sig = channel_next_sig++;
653 if (channel_next_sig < 0) {
654 channel_next_sig = 1;
657 return &Channels[chan];
660 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
664 unsigned int tag = 0, size = 0, next_chunk;
671 cfp = cfopen(filename, "rb");
674 nprintf(("Error", "Couldn't open '%s'\n", filename ));
678 // check for valid file type
679 id = cfread_int(cfp);
682 if (id != 0x46464952) {
683 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
691 // check for valid RIFF type
692 id = cfread_int(cfp);
695 if (id != 0x45564157) {
696 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
702 while ( !cfeof(cfp) ) {
703 tag = cfread_uint(cfp);
704 size = cfread_uint(cfp);
706 next_chunk = cftell(cfp) + size;
711 hdr.code = cfread_short(cfp);
712 hdr.num_channels = cfread_ushort(cfp);
713 hdr.sample_rate = cfread_uint(cfp);
714 hdr.bytes_per_second = cfread_uint(cfp);
715 hdr.block_align = cfread_ushort(cfp);
716 hdr.bits_per_sample = cfread_ushort(cfp);
719 hdr.extra_size = cfread_ushort(cfp);
722 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
723 SDL_assert( (*header) != NULL );
725 memcpy((*header), &hdr, sizeof(WAVE_chunk));
727 if (hdr.extra_size) {
728 (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
729 SDL_assert( (*header)->extra_data != NULL );
731 cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
741 (*dest) = (ubyte*) malloc (size);
742 SDL_assert( (*dest) != NULL );
744 cfread((*dest), size, 1, cfp);
749 // drop everything else
754 cfseek(cfp, next_chunk, CF_SEEK_SET);
762 static int oal_get_free_buffer()
768 int size = (int)Buffers.size();
770 for (int i = 0; i < size; i++) {
771 if (Buffers[i].buf_id == 0) {
778 Buffers.push_back(nbuf);
780 return (int)(Buffers.size()-1);
783 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
785 SDL_assert( final_size != NULL );
786 SDL_assert( header != NULL );
787 SDL_assert( si != NULL );
793 int buf_idx = oal_get_free_buffer();
801 sound_buffer *buf = &Buffers[buf_idx];
803 oal_check_for_errors("oal_load_buffer() begin");
805 alGenBuffers(1, &buf->buf_id);
807 if ( !buf->buf_id ) {
811 ALenum format = AL_INVALID;
817 // the below conversion variables are only used when the wav format is not PCM.
818 ubyte *convert_buffer = NULL; // storage for converted wav file
819 int convert_len; // num bytes of converted wav file
820 uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size)
823 switch (si->format) {
824 case WAVE_FORMAT_PCM: {
825 SDL_assert( si->data != NULL );
828 bps = si->avg_bytes_per_sec;
831 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
832 // swap 16-bit sound data
836 for (uint i=0; i<size; i=i+2) {
837 swap_tmp = (ushort*)(si->data + i);
838 *swap_tmp = INTEL_SHORT(*swap_tmp);
848 case WAVE_FORMAT_ADPCM: {
849 SDL_assert( si->data != NULL );
851 // this ADPCM decoder decodes to 16-bit only so keep that in mind
852 nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" ));
854 int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16);
856 // ACM conversion failed?
857 if ( (rc == -1) || (src_bytes_used != si->size) ) {
858 alDeleteBuffers(1, &buf->buf_id);
861 if (convert_buffer != NULL) {
862 free(convert_buffer);
869 bps = (((si->n_channels * bits) / 8) * si->sample_rate);
871 data = convert_buffer;
873 nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
879 nprintf(( "Sound", "Unsupported sound encoding\n" ));
880 alDeleteBuffers(1, &buf->buf_id);
885 // format is now in pcm
886 frequency = si->sample_rate;
889 if (si->n_channels == 2) {
890 format = AL_FORMAT_STEREO16;
891 } else if (si->n_channels == 1) {
892 format = AL_FORMAT_MONO16;
894 } else if (bits == 8) {
895 if (si->n_channels == 2) {
896 format = AL_FORMAT_STEREO8;
897 } else if (si->n_channels == 1) {
898 format = AL_FORMAT_MONO8;
902 if (format == AL_INVALID) {
903 alDeleteBuffers(1, &buf->buf_id);
906 if (convert_buffer != NULL) {
907 free(convert_buffer);
916 alBufferData(buf->buf_id, format, data, size, frequency);
919 buf->frequency = frequency;
920 buf->bits_per_sample = bits;
921 buf->nchannels = si->n_channels;
922 buf->nseconds = size / bps;
925 if (convert_buffer != NULL) {
926 free(convert_buffer);
929 oal_check_for_errors("oal_load_buffer() end");
934 void oal_unload_buffer(int sid)
940 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
944 oal_check_for_errors("oal_unload_buffer() begin");
946 sound_buffer *buf = &Buffers[sid];
949 alDeleteBuffers(1, &buf->buf_id);
953 oal_check_for_errors("oal_unload_buffer() end");
956 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
962 int buf_idx = oal_get_free_buffer();
968 sound_buffer *buf = &Buffers[buf_idx];
970 oal_check_for_errors("oal_load_buffer() begin");
972 alGenBuffers(1, &buf->buf_id);
974 if ( !buf->buf_id ) {
979 buf->frequency = frequency;
980 buf->bits_per_sample = bits_per_sample;
981 buf->nchannels = nchannels;
982 buf->nseconds = nseconds;
983 buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
988 int oal_lock_data(int sid, ubyte *data, int size)
994 oal_check_for_errors("oal_lock_data() begin");
996 SDL_assert( sid >= 0 );
997 SDL_assert( sid < (int)Buffers.size() );
999 ALuint buf_id = Buffers[sid].buf_id;
1002 if (Buffers[sid].bits_per_sample == 16) {
1003 if (Buffers[sid].nchannels == 2) {
1004 format = AL_FORMAT_STEREO16;
1005 } else if (Buffers[sid].nchannels == 1) {
1006 format = AL_FORMAT_MONO16;
1010 } else if (Buffers[sid].bits_per_sample == 8) {
1011 if (Buffers[sid].nchannels == 2) {
1012 format = AL_FORMAT_STEREO8;
1013 } else if (Buffers[sid].nchannels == 1) {
1014 format = AL_FORMAT_MONO8;
1022 Buffers[sid].nbytes = size;
1024 alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1026 if ( oal_check_for_errors("oal_lock_data() end") ) {
1033 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1035 if ( !OAL_inited ) {
1039 SDL_assert( sid >= 0 );
1040 SDL_assert( sid < (int)Buffers.size() );
1042 oal_check_for_errors("oal_play() begin");
1044 int channel = oal_get_free_channel_idx(volume, snd_id, priority);
1050 sound_channel *chan = &Channels[channel];
1053 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1055 if (status == AL_PLAYING) {
1056 oal_stop_channel(channel);
1059 // set all the things
1061 chan->flags = flags;
1062 chan->priority = priority;
1063 chan->last_position = 0;
1064 chan->buf_idx = sid;
1065 chan->snd_id = snd_id;
1066 chan->sig = channel_next_sig++;
1068 Buffers[sid].chan_idx = channel;
1070 alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f);
1071 alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1072 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1073 alSourcef(chan->source_id, AL_GAIN, volume);
1074 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1075 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1076 alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE);
1079 alSourcePlay(chan->source_id);
1081 if (channel_next_sig < 0) {
1082 channel_next_sig = 1;
1085 oal_check_for_errors("oal_play() end");
1090 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)
1092 if ( !OAL_inited ) {
1096 SDL_assert( sid >= 0 );
1097 SDL_assert( sid < (int)Buffers.size() );
1099 oal_check_for_errors("oal_play_3d() begin");
1101 int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1107 sound_channel *chan = &Channels[channel];
1110 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1112 if (status == AL_PLAYING) {
1113 oal_stop_channel(channel);
1116 int flags = SND_FLAG_3D;
1119 flags |= SND_FLAG_LOOPING;
1122 // set all the things
1123 chan->vol = max_volume;
1124 chan->flags = flags;
1125 chan->priority = priority;
1126 chan->last_position = 0;
1127 chan->buf_idx = sid;
1128 chan->snd_id = snd_id;
1129 chan->sig = channel_next_sig++;
1131 Buffers[sid].chan_idx = channel;
1133 oal_update_source(channel, min, max, pos, vel);
1135 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1136 alSourcef(chan->source_id, AL_GAIN, max_volume);
1137 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1138 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE);
1139 alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE);
1142 alSourcePlay(chan->source_id);
1144 if (channel_next_sig < 0) {
1145 channel_next_sig = 1;
1148 oal_check_for_errors("oal_play_3d() end");
1155 ALint state, current_position;
1157 oal_check_for_errors("oal_do_frame() begin");
1159 int size = (int)Channels.size();
1161 // make sure there aren't any looping voice messages
1162 for (int i = 0; i < size; i++) {
1164 if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) {
1165 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state);
1167 if (state != AL_PLAYING) {
1171 alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, ¤t_position);
1173 if (current_position != 0) {
1174 if (current_position < Channels[i].last_position) {
1175 alSourceStop(Channels[i].source_id);
1177 Channels[i].last_position = current_position;
1183 oal_check_for_errors("oal_do_frame() end");
1186 int oal_update_source(int channel, int min, int max, vector *pos, vector *vel)
1188 if ( !OAL_inited ) {
1196 if ( !Channels[channel].flags & SND_FLAG_3D ) {
1200 ALuint source_id = Channels[channel].source_id;
1201 ALfloat rolloff = 1.0f;
1203 oal_check_for_errors("oal_update_source() begin");
1206 alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1210 alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1212 alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1219 const float MIN_GAIN = 0.05f;
1220 float minf = i2fl(min);
1221 float maxf = i2fl(max);
1223 // yep, just making this shit up
1224 rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN;
1226 if (rolloff < 0.0f) {
1231 alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff);
1233 alSourcei(source_id, AL_REFERENCE_DISTANCE, min);
1234 alSourcei(source_id, AL_MAX_DISTANCE, max);
1237 oal_check_for_errors("oal_update_source() end");
1242 int oal_update_listener(vector *pos, vector *vel, matrix *orient)
1244 if ( !OAL_inited ) {
1248 oal_check_for_errors("oal_update_listener() begin");
1251 alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1255 alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1259 ALfloat alOrient[6];
1261 alOrient[0] = orient->v.fvec.xyz.x;
1262 alOrient[1] = orient->v.fvec.xyz.y;
1263 alOrient[2] = -orient->v.fvec.xyz.z;
1265 alOrient[3] = orient->v.uvec.xyz.x;
1266 alOrient[4] = orient->v.uvec.xyz.y;
1267 alOrient[5] = -orient->v.uvec.xyz.z;
1269 alListenerfv(AL_ORIENTATION, alOrient);
1272 oal_check_for_errors("oal_update_listener() end");