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 alDeleteBuffers(1, &bid);
173 oal_check_for_errors("oal_close() end");
178 alcMakeContextCurrent(NULL);
179 alcDestroyContext(al_context);
180 alcCloseDevice(al_device);
188 int oal_get_channel(int sig)
196 int size = (int)Channels.size();
198 for (i = 0; i < size; i++) {
199 if (Channels[i].sig == sig) {
202 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
204 if (status == AL_PLAYING) {
215 int oal_get_number_channels()
225 int size = (int)Channels.size();
227 for (i = 0; i < size; i++) {
228 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
230 if (status == AL_PLAYING) {
238 void oal_stop_buffer(int sid)
244 oal_check_for_errors("oal_stop_buffer() begin");
246 SDL_assert( sid >= 0 );
247 SDL_assert( sid < (int)Buffers.size() );
249 int cid = Buffers[sid].chan_idx;
252 ALuint source_id = Channels[cid].source_id;
254 alSourceStop(source_id);
257 oal_check_for_errors("oal_stop_buffer() end");
260 void oal_stop_channel(int channel)
266 SDL_assert( channel >= 0 );
267 SDL_assert( channel < (int)Channels.size() );
269 oal_check_for_errors("oal_stop_channel() begin");
271 alSourceStop(Channels[channel].source_id);
273 alSourcei(Channels[channel].source_id, AL_BUFFER, 0);
274 Channels[channel].buf_idx = -1;
276 oal_check_for_errors("oal_stop_channel() end");
279 void oal_stop_channel_all()
285 int size = (int)Channels.size();
287 for (int i = 0; i < size; i++) {
292 int oal_get_buffer_size(int sid, int *size)
298 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
302 *size = Buffers[sid].nbytes;
307 int oal_get_channel_size(int channel)
313 if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
317 if (Channels[channel].buf_idx >= 0) {
318 return Buffers[Channels[channel].buf_idx].nbytes;
324 // -----------------------------------------------------------------------------
325 // Source properties *set functions
326 // -----------------------------------------------------------------------------
328 void oal_set_volume(int channel, float volume)
334 SDL_assert( channel >= 0 );
335 SDL_assert( channel < (int)Channels.size() );
337 oal_check_for_errors("oal_set_volume() begin");
339 alSourcef(Channels[channel].source_id, AL_GAIN, volume);
341 oal_check_for_errors("oal_set_volume() end");
344 void oal_set_pan(int channel, float pan)
350 SDL_assert( channel >= 0 );
351 SDL_assert( channel < (int)Channels.size() );
353 oal_check_for_errors("oal_set_pan() begin");
355 alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
357 oal_check_for_errors("oal_set_pan() end");
360 void oal_set_pitch(int channel, float pitch)
366 SDL_assert( channel >= 0 );
367 SDL_assert( channel < (int)Channels.size() );
369 oal_check_for_errors("oal_set_pitch() begin");
371 alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
373 oal_check_for_errors("oal_set_pitch() end");
376 void oal_set_play_position(int channel, int position)
382 SDL_assert( channel >= 0 );
383 SDL_assert( channel < (int)Channels.size() );
385 oal_check_for_errors("oal_set_play_position() begin");
387 alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
389 oal_check_for_errors("oal_set_play_position() end");
392 // -----------------------------------------------------------------------------
394 // -----------------------------------------------------------------------------
395 // Source properties *get functions
396 // -----------------------------------------------------------------------------
398 float oal_get_pitch(int channel)
406 SDL_assert( channel >= 0 );
407 SDL_assert( channel < (int)Channels.size() );
409 oal_check_for_errors("oal_get_pitch() begin");
411 alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
413 oal_check_for_errors("oal_get_pitch() end");
418 int oal_get_play_position(int channel)
430 //SDL_assert( channel >= 0 );
431 SDL_assert( channel < (int)Channels.size() );
433 oal_check_for_errors("oal_get_play_position() begin");
435 alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
437 if (alGetError() != AL_NO_ERROR) {
444 // -----------------------------------------------------------------------------
451 int oal_is_channel_playing(int channel)
459 SDL_assert( channel >= 0 );
460 SDL_assert( channel < (int)Channels.size() );
462 oal_check_for_errors("oal_is_channel_playing() begin");
464 alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
466 oal_check_for_errors("oal_is_channel_playing() end");
468 if (status == AL_PLAYING) {
475 void oal_chg_loop_status(int channel, int loop)
481 SDL_assert( channel >= 0 );
482 SDL_assert( channel < (int)Channels.size() );
484 oal_check_for_errors("oal_chg_loop_status() begin");
486 alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
489 Channels[channel].flags |= SND_FLAG_LOOPING;
491 Channels[channel].flags &= ~SND_FLAG_LOOPING;
494 oal_check_for_errors("oal_chg_loop_status() end");
497 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
500 float lowest_vol = 0.0f;
501 int lowest_vol_index = -1;
503 int instance_count = 0; // number of instances of sound already playing
504 float lowest_instance_vol = 1.0f;
505 int lowest_instance_vol_index = -1;
507 int first_free_channel = -1;
513 int size = (int)Channels.size();
515 oal_check_for_errors("oal_get_free_channel_idx() begin");
517 // Look for a channel to use to play this sample
518 for (i = 0; i < size; i++) {
519 sound_channel *chp = &Channels[i];
520 int looping = chp->flags & SND_FLAG_LOOPING;
522 if (chp->snd_id == 0) {
523 if (first_free_channel == -1) {
524 first_free_channel = i;
530 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
532 if (status != AL_PLAYING) {
533 if (first_free_channel == -1) {
534 first_free_channel = i;
539 if (chp->snd_id == snd_id) {
542 if ( (chp->vol < lowest_instance_vol) && !looping ) {
543 lowest_instance_vol = chp->vol;
544 lowest_instance_vol_index = i;
548 if ( (chp->vol < lowest_vol) && !looping ) {
549 lowest_vol_index = i;
550 lowest_vol = chp->vol;
555 // determine the limit of concurrent instances of this sound
557 case SND_PRIORITY_MUST_PLAY:
561 case SND_PRIORITY_SINGLE_INSTANCE:
565 case SND_PRIORITY_DOUBLE_INSTANCE:
569 case SND_PRIORITY_TRIPLE_INSTANCE:
580 // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
581 if (instance_count >= limit) {
582 // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
583 if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) {
584 first_free_channel = lowest_instance_vol_index;
586 first_free_channel = -1;
589 // there is no limit barrier to play the sound, so see if we've ran out of channels
590 if (first_free_channel == -1) {
591 // stop the lowest volume instance to play our sound if priority demands it
592 if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) {
593 // Check if the lowest volume playing is less than the volume of the requested sound.
594 // If so, then we are going to trash the lowest volume sound.
595 if (Channels[lowest_vol_index].vol <= new_volume) {
596 first_free_channel = lowest_vol_index;
602 oal_check_for_errors("oal_get_free_channel_idx() end");
604 return first_free_channel;
607 // get a channel for use elsewhere (MVE playback, streaming audio, etc.)
608 sound_channel *oal_get_free_channel(float volume, int snd_id, int priority)
614 int chan = oal_get_free_channel_idx(volume, snd_id, priority);
620 SDL_assert( Channels[chan].source_id != 0 );
622 // should be stopped already, but just in case
623 alSourceStop(Channels[chan].source_id);
625 alSourcei(Channels[chan].source_id, AL_BUFFER, 0);
627 if (Channels[chan].buf_idx >= 0) {
628 Buffers[Channels[chan].buf_idx].chan_idx = -1;
631 Channels[chan].vol = volume;
632 Channels[chan].priority = priority;
633 Channels[chan].last_position = 0;
634 Channels[chan].buf_idx = -1;
635 Channels[chan].snd_id = snd_id;
636 Channels[chan].sig = channel_next_sig++;
638 if (channel_next_sig < 0) {
639 channel_next_sig = 1;
642 return &Channels[chan];
645 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
649 unsigned int tag = 0, size = 0, next_chunk;
656 cfp = cfopen(filename, "rb");
659 nprintf(("Error", "Couldn't open '%s'\n", filename ));
663 // check for valid file type
664 id = cfread_int(cfp);
667 if (id != 0x46464952) {
668 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
676 // check for valid RIFF type
677 id = cfread_int(cfp);
680 if (id != 0x45564157) {
681 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
687 while ( !cfeof(cfp) ) {
688 tag = cfread_uint(cfp);
689 size = cfread_uint(cfp);
691 next_chunk = cftell(cfp) + size;
696 hdr.code = cfread_short(cfp);
697 hdr.num_channels = cfread_ushort(cfp);
698 hdr.sample_rate = cfread_uint(cfp);
699 hdr.bytes_per_second = cfread_uint(cfp);
700 hdr.block_align = cfread_ushort(cfp);
701 hdr.bits_per_sample = cfread_ushort(cfp);
704 hdr.extra_size = cfread_ushort(cfp);
707 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
708 SDL_assert( (*header) != NULL );
710 memcpy((*header), &hdr, sizeof(WAVE_chunk));
712 if (hdr.extra_size) {
713 (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
714 SDL_assert( (*header)->extra_data != NULL );
716 cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
726 (*dest) = (ubyte*) malloc (size);
727 SDL_assert( (*dest) != NULL );
729 cfread((*dest), size, 1, cfp);
734 // drop everything else
739 cfseek(cfp, next_chunk, CF_SEEK_SET);
747 static int oal_get_free_buffer()
753 int size = (int)Buffers.size();
755 for (int i = 0; i < size; i++) {
756 if (Buffers[i].buf_id == 0) {
763 Buffers.push_back(nbuf);
765 return (int)(Buffers.size()-1);
768 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
770 SDL_assert( final_size != NULL );
771 SDL_assert( header != NULL );
772 SDL_assert( si != NULL );
778 int buf_idx = oal_get_free_buffer();
786 sound_buffer *buf = &Buffers[buf_idx];
788 oal_check_for_errors("oal_load_buffer() begin");
790 alGenBuffers(1, &buf->buf_id);
792 if ( !buf->buf_id ) {
796 ALenum format = AL_INVALID;
802 // the below conversion variables are only used when the wav format is not PCM.
803 ubyte *convert_buffer = NULL; // storage for converted wav file
804 int convert_len; // num bytes of converted wav file
805 uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size)
808 switch (si->format) {
809 case WAVE_FORMAT_PCM: {
810 SDL_assert( si->data != NULL );
813 bps = si->avg_bytes_per_sec;
816 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
817 // swap 16-bit sound data
821 for (uint i=0; i<size; i=i+2) {
822 swap_tmp = (ushort*)(si->data + i);
823 *swap_tmp = INTEL_SHORT(*swap_tmp);
833 case WAVE_FORMAT_ADPCM: {
834 SDL_assert( si->data != NULL );
836 // this ADPCM decoder decodes to 16-bit only so keep that in mind
837 nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" ));
839 int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16);
841 // ACM conversion failed?
842 if ( (rc == -1) || (src_bytes_used != si->size) ) {
843 alDeleteBuffers(1, &buf->buf_id);
846 if (convert_buffer != NULL) {
847 free(convert_buffer);
854 bps = (((si->n_channels * bits) / 8) * si->sample_rate);
856 data = convert_buffer;
858 nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
864 nprintf(( "Sound", "Unsupported sound encoding\n" ));
865 alDeleteBuffers(1, &buf->buf_id);
870 // format is now in pcm
871 frequency = si->sample_rate;
874 if (si->n_channels == 2) {
875 format = AL_FORMAT_STEREO16;
876 } else if (si->n_channels == 1) {
877 format = AL_FORMAT_MONO16;
879 } else if (bits == 8) {
880 if (si->n_channels == 2) {
881 format = AL_FORMAT_STEREO8;
882 } else if (si->n_channels == 1) {
883 format = AL_FORMAT_MONO8;
887 if (format == AL_INVALID) {
888 alDeleteBuffers(1, &buf->buf_id);
891 if (convert_buffer != NULL) {
892 free(convert_buffer);
901 alBufferData(buf->buf_id, format, data, size, frequency);
904 buf->frequency = frequency;
905 buf->bits_per_sample = bits;
906 buf->nchannels = si->n_channels;
907 buf->nseconds = size / bps;
910 if (convert_buffer != NULL) {
911 free(convert_buffer);
914 oal_check_for_errors("oal_load_buffer() end");
919 void oal_unload_buffer(int sid)
925 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
929 oal_check_for_errors("oal_unload_buffer() begin");
931 sound_buffer *buf = &Buffers[sid];
934 if (buf->chan_idx >= 0) {
935 alSourceStop(Channels[buf->chan_idx].source_id);
936 alSourcei(Channels[buf->chan_idx].source_id, AL_BUFFER, 0);
940 alDeleteBuffers(1, &buf->buf_id);
944 oal_check_for_errors("oal_unload_buffer() end");
947 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
953 int buf_idx = oal_get_free_buffer();
959 sound_buffer *buf = &Buffers[buf_idx];
961 oal_check_for_errors("oal_load_buffer() begin");
963 alGenBuffers(1, &buf->buf_id);
965 if ( !buf->buf_id ) {
970 buf->frequency = frequency;
971 buf->bits_per_sample = bits_per_sample;
972 buf->nchannels = nchannels;
973 buf->nseconds = nseconds;
974 buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
979 int oal_lock_data(int sid, ubyte *data, int size)
985 oal_check_for_errors("oal_lock_data() begin");
987 SDL_assert( sid >= 0 );
988 SDL_assert( sid < (int)Buffers.size() );
990 ALuint buf_id = Buffers[sid].buf_id;
993 if (Buffers[sid].bits_per_sample == 16) {
994 if (Buffers[sid].nchannels == 2) {
995 format = AL_FORMAT_STEREO16;
996 } else if (Buffers[sid].nchannels == 1) {
997 format = AL_FORMAT_MONO16;
1001 } else if (Buffers[sid].bits_per_sample == 8) {
1002 if (Buffers[sid].nchannels == 2) {
1003 format = AL_FORMAT_STEREO8;
1004 } else if (Buffers[sid].nchannels == 1) {
1005 format = AL_FORMAT_MONO8;
1013 Buffers[sid].nbytes = size;
1015 alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1017 if ( oal_check_for_errors("oal_lock_data() end") ) {
1024 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1026 if ( !OAL_inited ) {
1030 SDL_assert( sid >= 0 );
1031 SDL_assert( sid < (int)Buffers.size() );
1033 oal_check_for_errors("oal_play() begin");
1035 int channel = oal_get_free_channel_idx(volume, snd_id, priority);
1041 sound_channel *chan = &Channels[channel];
1044 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1046 if (status == AL_PLAYING) {
1047 oal_stop_channel(channel);
1050 // set all the things
1052 chan->flags = flags;
1053 chan->priority = priority;
1054 chan->last_position = 0;
1055 chan->buf_idx = sid;
1056 chan->snd_id = snd_id;
1057 chan->sig = channel_next_sig++;
1059 Buffers[sid].chan_idx = channel;
1061 alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f);
1062 alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1063 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1064 alSourcef(chan->source_id, AL_GAIN, volume);
1065 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1066 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1067 alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE);
1069 // maybe attach source to reverb effect
1070 oal_efx_attach(chan->source_id);
1073 alSourcePlay(chan->source_id);
1075 if (channel_next_sig < 0) {
1076 channel_next_sig = 1;
1079 oal_check_for_errors("oal_play() end");
1084 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)
1086 if ( !OAL_inited ) {
1090 SDL_assert( sid >= 0 );
1091 SDL_assert( sid < (int)Buffers.size() );
1093 oal_check_for_errors("oal_play_3d() begin");
1095 int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1101 sound_channel *chan = &Channels[channel];
1104 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1106 if (status == AL_PLAYING) {
1107 oal_stop_channel(channel);
1110 int flags = SND_FLAG_3D;
1113 flags |= SND_FLAG_LOOPING;
1116 // set all the things
1117 chan->vol = max_volume;
1118 chan->flags = flags;
1119 chan->priority = priority;
1120 chan->last_position = 0;
1121 chan->buf_idx = sid;
1122 chan->snd_id = snd_id;
1123 chan->sig = channel_next_sig++;
1125 Buffers[sid].chan_idx = channel;
1127 oal_update_source(channel, min, max, pos, vel);
1129 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1130 alSourcef(chan->source_id, AL_GAIN, max_volume);
1131 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1132 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE);
1133 alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE);
1135 // maybe attach source to reverb effect
1136 oal_efx_attach(chan->source_id);
1139 alSourcePlay(chan->source_id);
1141 if (channel_next_sig < 0) {
1142 channel_next_sig = 1;
1145 oal_check_for_errors("oal_play_3d() end");
1152 ALint state, current_position;
1154 if ( !OAL_inited ) {
1158 oal_check_for_errors("oal_do_frame() begin");
1160 int size = (int)Channels.size();
1162 // make sure there aren't any looping voice messages
1163 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");