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) {
57 const char *str = alGetString(err);
59 nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s\n", location, err, (str) ? str : "??"));
61 nprintf(("OpenAL", "AL-ERROR => 0x%x: %s\n", err, alGetString(err)));
70 static void oal_init_channels()
72 const int MAX_SOURCES = 32;
74 Channels.reserve(MAX_SOURCES);
76 for (int n = 0; n < MAX_SOURCES; n++) {
77 sound_channel n_channel;
79 alGenSources(1, &n_channel.source_id);
81 if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) {
85 Channels.push_back(n_channel);
89 int oal_init(int use_eax)
91 ALint ver_major = 0, ver_minor = 0;
97 nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" ));
99 alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &ver_major);
100 alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &ver_minor);
102 if ( (ver_major < 1) || (ver_minor < 1) ) {
103 nprintf(("Sound", "SOUND ==> Minimum supported OpenAL version is 1.1\n"));
107 al_device = alcOpenDevice(NULL);
109 if (al_device == NULL) {
110 nprintf(("Sound", "SOUND ==> Unable to open device!\n"));
111 nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device))));
115 al_context = alcCreateContext(al_device, NULL);
117 if (al_context == NULL) {
118 nprintf(("Sound", "SOUND ==> Unable to create context!\n"));
119 nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device))));
121 alcCloseDevice(al_device);
127 alcMakeContextCurrent(al_context);
139 oal_check_for_errors("oal_init() end");
150 oal_check_for_errors("oal_close() begin");
152 while ( !Channels.empty() ) {
153 ALuint sid = Channels.back().source_id;
157 alSourcei(sid, AL_BUFFER, 0);
159 alDeleteSources(1, &sid);
164 while ( !Buffers.empty() ) {
165 ALuint bid = Buffers.back().buf_id;
167 if ( alIsBuffer(bid) ) {
168 alDeleteBuffers(1, &bid);
176 oal_check_for_errors("oal_close() end");
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);
258 alSourcei(source_id, AL_BUFFER, 0);
261 oal_check_for_errors("oal_stop_buffer() end");
264 void oal_stop_channel(int channel)
270 SDL_assert( channel >= 0 );
271 SDL_assert( channel < (int)Channels.size() );
273 if (Channels[channel].flags & SND_FLAG_EXT) {
277 oal_check_for_errors("oal_stop_channel() begin");
279 alSourceStop(Channels[channel].source_id);
281 alSourcei(Channels[channel].source_id, AL_BUFFER, 0);
282 Channels[channel].buf_idx = -1;
284 oal_check_for_errors("oal_stop_channel() end");
287 void oal_stop_channel_all()
293 int size = (int)Channels.size();
295 for (int i = 0; i < size; i++) {
296 if (Channels[i].flags & SND_FLAG_EXT) {
304 int oal_get_buffer_size(int sid, int *size)
310 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
314 *size = Buffers[sid].nbytes;
319 int oal_get_channel_size(int channel)
325 if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
329 if (Channels[channel].buf_idx >= 0) {
330 return Buffers[Channels[channel].buf_idx].nbytes;
336 // -----------------------------------------------------------------------------
337 // Source properties *set functions
338 // -----------------------------------------------------------------------------
340 void oal_set_volume(int channel, float volume)
346 SDL_assert( channel >= 0 );
347 SDL_assert( channel < (int)Channels.size() );
348 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
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() );
365 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
367 oal_check_for_errors("oal_set_pan() begin");
369 alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
371 oal_check_for_errors("oal_set_pan() end");
374 void oal_set_pitch(int channel, float pitch)
380 SDL_assert( channel >= 0 );
381 SDL_assert( channel < (int)Channels.size() );
382 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
384 oal_check_for_errors("oal_set_pitch() begin");
386 alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
388 oal_check_for_errors("oal_set_pitch() end");
391 void oal_set_play_position(int channel, int position)
397 SDL_assert( channel >= 0 );
398 SDL_assert( channel < (int)Channels.size() );
399 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
401 oal_check_for_errors("oal_set_play_position() begin");
403 alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
405 oal_check_for_errors("oal_set_play_position() end");
408 // -----------------------------------------------------------------------------
410 // -----------------------------------------------------------------------------
411 // Source properties *get functions
412 // -----------------------------------------------------------------------------
414 float oal_get_pitch(int channel)
422 SDL_assert( channel >= 0 );
423 SDL_assert( channel < (int)Channels.size() );
424 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
426 oal_check_for_errors("oal_get_pitch() begin");
428 alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
430 oal_check_for_errors("oal_get_pitch() end");
435 int oal_get_play_position(int channel)
447 //SDL_assert( channel >= 0 );
448 SDL_assert( channel < (int)Channels.size() );
450 oal_check_for_errors("oal_get_play_position() begin");
452 alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
454 if (alGetError() != AL_NO_ERROR) {
461 // -----------------------------------------------------------------------------
468 int oal_is_channel_playing(int channel)
476 SDL_assert( channel >= 0 );
477 SDL_assert( channel < (int)Channels.size() );
479 oal_check_for_errors("oal_is_channel_playing() begin");
481 alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
483 oal_check_for_errors("oal_is_channel_playing() end");
485 if (status == AL_PLAYING) {
492 void oal_chg_loop_status(int channel, int loop)
498 SDL_assert( channel >= 0 );
499 SDL_assert( channel < (int)Channels.size() );
500 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
502 oal_check_for_errors("oal_chg_loop_status() begin");
504 alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
507 Channels[channel].flags |= SND_FLAG_LOOPING;
509 Channels[channel].flags &= ~SND_FLAG_LOOPING;
512 oal_check_for_errors("oal_chg_loop_status() end");
515 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
518 float lowest_vol = 0.0f;
519 int lowest_vol_index = -1;
521 int instance_count = 0; // number of instances of sound already playing
522 float lowest_instance_vol = 1.0f;
523 int lowest_instance_vol_index = -1;
525 int first_free_channel = -1;
531 int size = (int)Channels.size();
533 oal_check_for_errors("oal_get_free_channel_idx() begin");
535 // Look for a channel to use to play this sample
536 for (i = 0; i < size; i++) {
537 sound_channel *chp = &Channels[i];
538 int looping = chp->flags & SND_FLAG_LOOPING;
540 if (chp->snd_id == 0) {
541 if (first_free_channel == -1) {
542 first_free_channel = i;
548 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
550 if ( (status != AL_PLAYING) && (status != AL_PAUSED) ) {
551 if (first_free_channel == -1) {
552 first_free_channel = i;
557 if (chp->snd_id == snd_id) {
560 if ( (chp->vol < lowest_instance_vol) && !looping ) {
561 lowest_instance_vol = chp->vol;
562 lowest_instance_vol_index = i;
566 if ( (chp->vol < lowest_vol) && !looping ) {
567 lowest_vol_index = i;
568 lowest_vol = chp->vol;
573 // determine the limit of concurrent instances of this sound
575 case SND_PRIORITY_MUST_PLAY:
579 case SND_PRIORITY_SINGLE_INSTANCE:
583 case SND_PRIORITY_DOUBLE_INSTANCE:
587 case SND_PRIORITY_TRIPLE_INSTANCE:
598 // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
599 if (instance_count >= limit) {
600 // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
601 if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) {
602 first_free_channel = lowest_instance_vol_index;
604 first_free_channel = -1;
607 // there is no limit barrier to play the sound, so see if we've ran out of channels
608 if (first_free_channel == -1) {
609 // stop the lowest volume instance to play our sound if priority demands it
610 if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) {
611 // Check if the lowest volume playing is less than the volume of the requested sound.
612 // If so, then we are going to trash the lowest volume sound.
613 if (Channels[lowest_vol_index].vol <= new_volume) {
614 first_free_channel = lowest_vol_index;
620 oal_check_for_errors("oal_get_free_channel_idx() end");
622 return first_free_channel;
625 // get a channel for use elsewhere (MVE playback, streaming audio, etc.)
626 sound_channel *oal_get_free_channel(float volume, int snd_id, int priority)
632 int chan = oal_get_free_channel_idx(volume, snd_id, priority);
638 SDL_assert( Channels[chan].source_id != 0 );
640 alSourceStop(Channels[chan].source_id);
641 alSourcei(Channels[chan].source_id, AL_BUFFER, 0);
643 if (Channels[chan].buf_idx >= 0) {
644 Buffers[Channels[chan].buf_idx].chan_idx = -1;
647 Channels[chan].vol = volume;
648 Channels[chan].priority = priority;
649 Channels[chan].last_position = 0;
650 Channels[chan].flags = SND_FLAG_EXT;
651 Channels[chan].buf_idx = -1;
652 Channels[chan].snd_id = snd_id;
653 Channels[chan].sig = channel_next_sig++;
655 if (channel_next_sig < 0) {
656 channel_next_sig = 1;
659 return &Channels[chan];
662 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
666 unsigned int tag = 0, size = 0, next_chunk;
673 cfp = cfopen(filename, "rb");
676 nprintf(("Error", "Couldn't open '%s'\n", filename ));
680 // check for valid file type
681 id = cfread_int(cfp);
684 if (id != 0x46464952) {
685 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
693 // check for valid RIFF type
694 id = cfread_int(cfp);
697 if (id != 0x45564157) {
698 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
704 while ( !cfeof(cfp) ) {
705 tag = cfread_uint(cfp);
706 size = cfread_uint(cfp);
708 next_chunk = cftell(cfp) + size;
713 hdr.code = cfread_short(cfp);
714 hdr.num_channels = cfread_ushort(cfp);
715 hdr.sample_rate = cfread_uint(cfp);
716 hdr.bytes_per_second = cfread_uint(cfp);
717 hdr.block_align = cfread_ushort(cfp);
718 hdr.bits_per_sample = cfread_ushort(cfp);
721 hdr.extra_size = cfread_ushort(cfp);
724 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
725 SDL_assert( (*header) != NULL );
727 memcpy((*header), &hdr, sizeof(WAVE_chunk));
729 if (hdr.extra_size) {
730 (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
731 SDL_assert( (*header)->extra_data != NULL );
733 cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
743 (*dest) = (ubyte*) malloc (size);
744 SDL_assert( (*dest) != NULL );
746 cfread((*dest), size, 1, cfp);
751 // drop everything else
756 cfseek(cfp, next_chunk, CF_SEEK_SET);
764 static int oal_get_free_buffer()
770 int size = (int)Buffers.size();
772 for (int i = 0; i < size; i++) {
773 if (Buffers[i].buf_id == 0) {
780 Buffers.push_back(nbuf);
782 return (int)(Buffers.size()-1);
785 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
787 SDL_assert( final_size != NULL );
788 SDL_assert( header != NULL );
789 SDL_assert( si != NULL );
795 int buf_idx = oal_get_free_buffer();
803 sound_buffer *buf = &Buffers[buf_idx];
805 oal_check_for_errors("oal_load_buffer() begin");
807 alGenBuffers(1, &buf->buf_id);
809 if ( !buf->buf_id ) {
813 ALenum format = AL_INVALID;
819 // the below conversion variables are only used when the wav format is not PCM.
820 ubyte *convert_buffer = NULL; // storage for converted wav file
821 int convert_len; // num bytes of converted wav file
822 uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size)
825 switch (si->format) {
826 case WAVE_FORMAT_PCM: {
827 SDL_assert( si->data != NULL );
830 bps = si->avg_bytes_per_sec;
833 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
834 // swap 16-bit sound data
838 for (uint i=0; i<size; i=i+2) {
839 swap_tmp = (ushort*)(si->data + i);
840 *swap_tmp = INTEL_SHORT(*swap_tmp);
850 case WAVE_FORMAT_ADPCM: {
851 SDL_assert( si->data != NULL );
853 // this ADPCM decoder decodes to 16-bit only so keep that in mind
854 nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" ));
856 int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16);
858 // ACM conversion failed?
859 if ( (rc == -1) || (src_bytes_used != si->size) ) {
860 alDeleteBuffers(1, &buf->buf_id);
863 if (convert_buffer != NULL) {
864 free(convert_buffer);
871 bps = (((si->n_channels * bits) / 8) * si->sample_rate);
873 data = convert_buffer;
875 nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
881 nprintf(( "Sound", "Unsupported sound encoding\n" ));
882 alDeleteBuffers(1, &buf->buf_id);
887 // format is now in pcm
888 frequency = si->sample_rate;
891 if (si->n_channels == 2) {
892 format = AL_FORMAT_STEREO16;
893 } else if (si->n_channels == 1) {
894 format = AL_FORMAT_MONO16;
896 } else if (bits == 8) {
897 if (si->n_channels == 2) {
898 format = AL_FORMAT_STEREO8;
899 } else if (si->n_channels == 1) {
900 format = AL_FORMAT_MONO8;
904 if (format == AL_INVALID) {
905 alDeleteBuffers(1, &buf->buf_id);
908 if (convert_buffer != NULL) {
909 free(convert_buffer);
918 alBufferData(buf->buf_id, format, data, size, frequency);
921 buf->frequency = frequency;
922 buf->bits_per_sample = bits;
923 buf->nchannels = si->n_channels;
924 buf->nseconds = size / bps;
927 if (convert_buffer != NULL) {
928 free(convert_buffer);
931 oal_check_for_errors("oal_load_buffer() end");
936 void oal_unload_buffer(int sid)
942 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
946 oal_check_for_errors("oal_unload_buffer() begin");
948 sound_buffer *buf = &Buffers[sid];
951 if (buf->chan_idx >= 0) {
952 alSourceStop(Channels[buf->chan_idx].source_id);
953 alSourcei(Channels[buf->chan_idx].source_id, AL_BUFFER, 0);
957 alDeleteBuffers(1, &buf->buf_id);
961 oal_check_for_errors("oal_unload_buffer() end");
964 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
970 int buf_idx = oal_get_free_buffer();
976 sound_buffer *buf = &Buffers[buf_idx];
978 oal_check_for_errors("oal_load_buffer() begin");
980 alGenBuffers(1, &buf->buf_id);
982 if ( !buf->buf_id ) {
987 buf->frequency = frequency;
988 buf->bits_per_sample = bits_per_sample;
989 buf->nchannels = nchannels;
990 buf->nseconds = nseconds;
991 buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
996 int oal_lock_data(int sid, ubyte *data, int size)
1002 oal_check_for_errors("oal_lock_data() begin");
1004 SDL_assert( sid >= 0 );
1005 SDL_assert( sid < (int)Buffers.size() );
1007 ALuint buf_id = Buffers[sid].buf_id;
1010 if (Buffers[sid].bits_per_sample == 16) {
1011 if (Buffers[sid].nchannels == 2) {
1012 format = AL_FORMAT_STEREO16;
1013 } else if (Buffers[sid].nchannels == 1) {
1014 format = AL_FORMAT_MONO16;
1018 } else if (Buffers[sid].bits_per_sample == 8) {
1019 if (Buffers[sid].nchannels == 2) {
1020 format = AL_FORMAT_STEREO8;
1021 } else if (Buffers[sid].nchannels == 1) {
1022 format = AL_FORMAT_MONO8;
1030 Buffers[sid].nbytes = size;
1032 alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1034 if ( oal_check_for_errors("oal_lock_data() end") ) {
1041 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1043 if ( !OAL_inited ) {
1047 SDL_assert( sid >= 0 );
1048 SDL_assert( sid < (int)Buffers.size() );
1050 oal_check_for_errors("oal_play() begin");
1052 int channel = oal_get_free_channel_idx(volume, snd_id, priority);
1058 sound_channel *chan = &Channels[channel];
1061 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1063 if (status == AL_PLAYING) {
1064 oal_stop_channel(channel);
1067 // set all the things
1069 chan->flags = flags;
1070 chan->priority = priority;
1071 chan->last_position = 0;
1072 chan->buf_idx = sid;
1073 chan->snd_id = snd_id;
1074 chan->sig = channel_next_sig++;
1076 Buffers[sid].chan_idx = channel;
1078 alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f);
1079 alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1080 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1081 alSourcef(chan->source_id, AL_GAIN, volume);
1082 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1083 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1084 alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE);
1086 // maybe attach source to reverb effect
1087 oal_efx_attach(chan->source_id);
1090 alSourcePlay(chan->source_id);
1092 if (channel_next_sig < 0) {
1093 channel_next_sig = 1;
1096 oal_check_for_errors("oal_play() end");
1101 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)
1103 if ( !OAL_inited ) {
1107 SDL_assert( sid >= 0 );
1108 SDL_assert( sid < (int)Buffers.size() );
1110 oal_check_for_errors("oal_play_3d() begin");
1112 int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1118 sound_channel *chan = &Channels[channel];
1121 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1123 if (status == AL_PLAYING) {
1124 oal_stop_channel(channel);
1127 int flags = SND_FLAG_3D;
1130 flags |= SND_FLAG_LOOPING;
1133 // set all the things
1134 chan->vol = max_volume;
1135 chan->flags = flags;
1136 chan->priority = priority;
1137 chan->last_position = 0;
1138 chan->buf_idx = sid;
1139 chan->snd_id = snd_id;
1140 chan->sig = channel_next_sig++;
1142 Buffers[sid].chan_idx = channel;
1144 oal_update_source(channel, min, max, pos, vel);
1146 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1147 alSourcef(chan->source_id, AL_GAIN, max_volume);
1148 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1149 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE);
1150 alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE);
1152 // maybe attach source to reverb effect
1153 oal_efx_attach(chan->source_id);
1156 alSourcePlay(chan->source_id);
1158 if (channel_next_sig < 0) {
1159 channel_next_sig = 1;
1162 oal_check_for_errors("oal_play_3d() end");
1169 ALint state, current_position;
1171 if ( !OAL_inited ) {
1175 oal_check_for_errors("oal_do_frame() begin");
1177 int size = (int)Channels.size();
1179 // make sure there aren't any looping voice messages
1180 for (int i = 0; i < size; i++) {
1181 if (Channels[i].flags & SND_FLAG_EXT) {
1182 // streaming sources should be managed elsewhere
1186 if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) {
1187 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state);
1189 if (state != AL_PLAYING) {
1193 alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, ¤t_position);
1195 if (current_position != 0) {
1196 if (current_position < Channels[i].last_position) {
1197 alSourceStop(Channels[i].source_id);
1199 Channels[i].last_position = current_position;
1205 oal_check_for_errors("oal_do_frame() end");
1208 int oal_update_source(int channel, int min, int max, vector *pos, vector *vel)
1210 if ( !OAL_inited ) {
1218 if ( !(Channels[channel].flags & SND_FLAG_3D) ) {
1222 ALuint source_id = Channels[channel].source_id;
1223 ALfloat rolloff = 1.0f;
1225 oal_check_for_errors("oal_update_source() begin");
1228 alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1232 alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1234 alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1241 const float MIN_GAIN = 0.05f;
1242 float minf = i2fl(min);
1243 float maxf = i2fl(max);
1245 // yep, just making this shit up
1246 rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN;
1248 if (rolloff < 0.0f) {
1253 alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff);
1255 alSourcei(source_id, AL_REFERENCE_DISTANCE, min);
1256 alSourcei(source_id, AL_MAX_DISTANCE, max);
1259 oal_check_for_errors("oal_update_source() end");
1264 int oal_update_listener(vector *pos, vector *vel, matrix *orient)
1266 if ( !OAL_inited ) {
1270 oal_check_for_errors("oal_update_listener() begin");
1273 alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1277 alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1281 ALfloat alOrient[6];
1283 alOrient[0] = orient->v.fvec.xyz.x;
1284 alOrient[1] = orient->v.fvec.xyz.y;
1285 alOrient[2] = -orient->v.fvec.xyz.z;
1287 alOrient[3] = orient->v.uvec.xyz.x;
1288 alOrient[4] = orient->v.uvec.xyz.y;
1289 alOrient[5] = -orient->v.uvec.xyz.z;
1291 alListenerfv(AL_ORIENTATION, alOrient);
1294 oal_check_for_errors("oal_update_listener() end");