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
16 #include "oal_capture.h"
20 #include "osregistry.h"
23 static int OAL_inited = 0;
25 static ALCdevice *al_device = NULL;
26 static ALCcontext *al_context = NULL;
30 ALuint buf_id; // OpenAL buffer id
31 int chan_idx; // channel index this buffer is currently bound to
39 sound_buffer() : buf_id(0), chan_idx(-1), frequency(0), bits_per_sample(0),
40 nchannels(0), nseconds(0), nbytes(0)
45 static std::vector<sound_buffer> Buffers;
47 static std::vector<sound_channel> Channels;
48 static int channel_next_sig = 1;
50 extern void oal_efx_attach(ALuint source_id);
53 bool oal_check_for_errors(const char *location)
55 ALenum err = alGetError();
57 if (err != AL_NO_ERROR) {
60 const char *str = alGetString(err);
62 nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s\n", location, err, (str) ? str : "??"));
64 nprintf(("OpenAL", "AL-ERROR => 0x%x: %s\n", err, alGetString(err)));
73 static void oal_init_channels()
75 const int MAX_SOURCES = 32;
77 Channels.reserve(MAX_SOURCES);
79 for (int n = 0; n < MAX_SOURCES; n++) {
80 sound_channel n_channel;
82 alGenSources(1, &n_channel.source_id);
84 if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) {
88 Channels.push_back(n_channel);
94 ALint ver_major = 0, ver_minor = 0;
95 std::string PlaybackDevice;
96 const char *ptr = NULL;
102 mprintf(("Initializing OpenAL audio device...\n"));
104 alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &ver_major);
105 alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &ver_minor);
107 if ( (ver_major < 1) || (ver_minor < 1) ) {
108 Warning(LOCATION, "Minimum supported OpenAL version is 1.1!");
112 ptr = os_config_read_string("Audio", "PlaybackDevice", "default");
114 if ( ptr && !SDL_strcasecmp(ptr, "default") ) {
118 al_device = alcOpenDevice(ptr);
120 if (al_device == NULL) {
121 al_device = alcOpenDevice(NULL);
123 if (al_device == NULL) {
124 nprintf(("Sound", "SOUND ==> Unable to open device!\n"));
125 nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device))));
130 if ( alcIsExtensionPresent(al_device, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE ) {
131 ptr = alcGetString(al_device, ALC_ALL_DEVICES_SPECIFIER);
133 ptr = alcGetString(al_device, ALC_DEVICE_SPECIFIER);
138 PlaybackDevice = ptr;
140 al_context = alcCreateContext(al_device, NULL);
142 if (al_context == NULL) {
143 nprintf(("Sound", "SOUND ==> Unable to create context!\n"));
144 nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device))));
146 alcCloseDevice(al_device);
152 alcMakeContextCurrent(al_context);
160 mprintf((" Vendor : %s\n", alGetString(AL_VENDOR)));
161 mprintf((" Renderer : %s\n", alGetString(AL_RENDERER)));
162 mprintf((" Version : %s\n", alGetString(AL_VERSION)));
164 if ( os_config_read_uint("Audio", "EFX", 0) ) {
165 if (oal_efx_init() < 0) {
166 mprintf((" EFX : Not Supported\n"));
168 mprintf((" EFX : Enabled\n"));
171 mprintf((" EFX : Disabled\n"));
174 mprintf((" Channels : %d\n", Channels.size()));
175 mprintf((" Playback device : %s\n", PlaybackDevice.c_str()));
182 oal_check_for_errors("oal_init() end");
193 oal_check_for_errors("oal_close() begin");
195 while ( !Channels.empty() ) {
196 ALuint sid = Channels.back().source_id;
200 alSourcei(sid, AL_BUFFER, 0);
202 alDeleteSources(1, &sid);
207 while ( !Buffers.empty() ) {
208 ALuint bid = Buffers.back().buf_id;
210 if ( alIsBuffer(bid) ) {
211 alDeleteBuffers(1, &bid);
219 oal_check_for_errors("oal_close() end");
224 alcMakeContextCurrent(NULL);
225 alcDestroyContext(al_context);
226 alcCloseDevice(al_device);
234 int oal_get_channel(int sig)
242 int size = (int)Channels.size();
244 for (i = 0; i < size; i++) {
245 if (Channels[i].sig == sig) {
248 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
250 if (status == AL_PLAYING) {
261 int oal_get_number_channels()
271 int size = (int)Channels.size();
273 for (i = 0; i < size; i++) {
274 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
276 if (status == AL_PLAYING) {
284 void oal_stop_buffer(int sid)
290 oal_check_for_errors("oal_stop_buffer() begin");
292 SDL_assert( sid >= 0 );
293 SDL_assert( sid < (int)Buffers.size() );
295 int cid = Buffers[sid].chan_idx;
298 ALuint source_id = Channels[cid].source_id;
300 alSourceStop(source_id);
301 alSourcei(source_id, AL_BUFFER, 0);
304 oal_check_for_errors("oal_stop_buffer() end");
307 void oal_stop_channel(int channel)
313 SDL_assert( channel >= 0 );
314 SDL_assert( channel < (int)Channels.size() );
316 if (Channels[channel].flags & SND_FLAG_EXT) {
320 oal_check_for_errors("oal_stop_channel() begin");
322 alSourceStop(Channels[channel].source_id);
324 alSourcei(Channels[channel].source_id, AL_BUFFER, 0);
325 Channels[channel].buf_idx = -1;
327 oal_check_for_errors("oal_stop_channel() end");
330 void oal_stop_channel_all()
336 int size = (int)Channels.size();
338 for (int i = 0; i < size; i++) {
339 if (Channels[i].flags & SND_FLAG_EXT) {
347 int oal_get_buffer_size(int sid, int *size)
353 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
357 *size = Buffers[sid].nbytes;
362 int oal_get_channel_size(int channel)
368 if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
372 if (Channels[channel].buf_idx >= 0) {
373 return Buffers[Channels[channel].buf_idx].nbytes;
379 // -----------------------------------------------------------------------------
380 // Source properties *set functions
381 // -----------------------------------------------------------------------------
383 void oal_set_volume(int channel, float volume)
389 SDL_assert( channel >= 0 );
390 SDL_assert( channel < (int)Channels.size() );
391 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
393 oal_check_for_errors("oal_set_volume() begin");
395 alSourcef(Channels[channel].source_id, AL_GAIN, volume);
397 oal_check_for_errors("oal_set_volume() end");
400 void oal_set_pan(int channel, float pan)
406 SDL_assert( channel >= 0 );
407 SDL_assert( channel < (int)Channels.size() );
408 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
410 oal_check_for_errors("oal_set_pan() begin");
412 alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
414 oal_check_for_errors("oal_set_pan() end");
417 void oal_set_pitch(int channel, float pitch)
423 SDL_assert( channel >= 0 );
424 SDL_assert( channel < (int)Channels.size() );
425 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
427 oal_check_for_errors("oal_set_pitch() begin");
429 alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
431 oal_check_for_errors("oal_set_pitch() end");
434 void oal_set_play_position(int channel, int position)
440 SDL_assert( channel >= 0 );
441 SDL_assert( channel < (int)Channels.size() );
442 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
444 oal_check_for_errors("oal_set_play_position() begin");
446 alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
448 oal_check_for_errors("oal_set_play_position() end");
451 // -----------------------------------------------------------------------------
453 // -----------------------------------------------------------------------------
454 // Source properties *get functions
455 // -----------------------------------------------------------------------------
457 float oal_get_pitch(int channel)
465 SDL_assert( channel >= 0 );
466 SDL_assert( channel < (int)Channels.size() );
467 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
469 oal_check_for_errors("oal_get_pitch() begin");
471 alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
473 oal_check_for_errors("oal_get_pitch() end");
478 int oal_get_play_position(int channel)
490 //SDL_assert( channel >= 0 );
491 SDL_assert( channel < (int)Channels.size() );
493 oal_check_for_errors("oal_get_play_position() begin");
495 alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
497 if (alGetError() != AL_NO_ERROR) {
504 // -----------------------------------------------------------------------------
511 int oal_is_channel_playing(int channel)
519 SDL_assert( channel >= 0 );
520 SDL_assert( channel < (int)Channels.size() );
522 oal_check_for_errors("oal_is_channel_playing() begin");
524 alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
526 oal_check_for_errors("oal_is_channel_playing() end");
528 if (status == AL_PLAYING) {
535 void oal_chg_loop_status(int channel, int loop)
541 SDL_assert( channel >= 0 );
542 SDL_assert( channel < (int)Channels.size() );
543 SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
545 oal_check_for_errors("oal_chg_loop_status() begin");
547 alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
550 Channels[channel].flags |= SND_FLAG_LOOPING;
552 Channels[channel].flags &= ~SND_FLAG_LOOPING;
555 oal_check_for_errors("oal_chg_loop_status() end");
558 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
561 float lowest_vol = 0.0f;
562 int lowest_vol_index = -1;
564 int instance_count = 0; // number of instances of sound already playing
565 float lowest_instance_vol = 1.0f;
566 int lowest_instance_vol_index = -1;
568 int first_free_channel = -1;
574 int size = (int)Channels.size();
576 oal_check_for_errors("oal_get_free_channel_idx() begin");
578 // Look for a channel to use to play this sample
579 for (i = 0; i < size; i++) {
580 sound_channel *chp = &Channels[i];
581 int looping = chp->flags & SND_FLAG_LOOPING;
583 if (chp->snd_id == 0) {
584 if (first_free_channel == -1) {
585 first_free_channel = i;
591 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
593 if ( (status != AL_PLAYING) && (status != AL_PAUSED) ) {
594 if (first_free_channel == -1) {
595 first_free_channel = i;
600 if (chp->snd_id == snd_id) {
603 if ( (chp->vol < lowest_instance_vol) && !looping ) {
604 lowest_instance_vol = chp->vol;
605 lowest_instance_vol_index = i;
609 if ( (chp->vol < lowest_vol) && !looping ) {
610 lowest_vol_index = i;
611 lowest_vol = chp->vol;
616 // determine the limit of concurrent instances of this sound
618 case SND_PRIORITY_MUST_PLAY:
622 case SND_PRIORITY_SINGLE_INSTANCE:
626 case SND_PRIORITY_DOUBLE_INSTANCE:
630 case SND_PRIORITY_TRIPLE_INSTANCE:
641 // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
642 if (instance_count >= limit) {
643 // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
644 if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) {
645 first_free_channel = lowest_instance_vol_index;
647 first_free_channel = -1;
650 // there is no limit barrier to play the sound, so see if we've ran out of channels
651 if (first_free_channel == -1) {
652 // stop the lowest volume instance to play our sound if priority demands it
653 if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) {
654 // Check if the lowest volume playing is less than the volume of the requested sound.
655 // If so, then we are going to trash the lowest volume sound.
656 if (Channels[lowest_vol_index].vol <= new_volume) {
657 first_free_channel = lowest_vol_index;
663 oal_check_for_errors("oal_get_free_channel_idx() end");
665 return first_free_channel;
668 // get a channel for use elsewhere (MVE playback, streaming audio, etc.)
669 sound_channel *oal_get_free_channel(float volume, int snd_id, int priority)
675 int chan = oal_get_free_channel_idx(volume, snd_id, priority);
681 SDL_assert( Channels[chan].source_id != 0 );
683 alSourceStop(Channels[chan].source_id);
684 alSourcei(Channels[chan].source_id, AL_BUFFER, 0);
686 if (Channels[chan].buf_idx >= 0) {
687 Buffers[Channels[chan].buf_idx].chan_idx = -1;
690 Channels[chan].vol = volume;
691 Channels[chan].priority = priority;
692 Channels[chan].last_position = 0;
693 Channels[chan].flags = SND_FLAG_EXT;
694 Channels[chan].buf_idx = -1;
695 Channels[chan].snd_id = snd_id;
696 Channels[chan].sig = channel_next_sig++;
698 if (channel_next_sig < 0) {
699 channel_next_sig = 1;
702 return &Channels[chan];
705 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
709 unsigned int tag = 0, size = 0, next_chunk;
716 cfp = cfopen(filename, "rb");
719 nprintf(("Error", "Couldn't open '%s'\n", filename ));
723 // check for valid file type
724 id = cfread_int(cfp);
727 if (id != 0x46464952) {
728 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
736 // check for valid RIFF type
737 id = cfread_int(cfp);
740 if (id != 0x45564157) {
741 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
747 while ( !cfeof(cfp) ) {
748 tag = cfread_uint(cfp);
749 size = cfread_uint(cfp);
751 next_chunk = cftell(cfp) + size;
756 hdr.code = cfread_short(cfp);
757 hdr.num_channels = cfread_ushort(cfp);
758 hdr.sample_rate = cfread_uint(cfp);
759 hdr.bytes_per_second = cfread_uint(cfp);
760 hdr.block_align = cfread_ushort(cfp);
761 hdr.bits_per_sample = cfread_ushort(cfp);
764 hdr.extra_size = cfread_ushort(cfp);
767 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
768 SDL_assert( (*header) != NULL );
770 memcpy((*header), &hdr, sizeof(WAVE_chunk));
772 if (hdr.extra_size) {
773 (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
774 SDL_assert( (*header)->extra_data != NULL );
776 cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
786 (*dest) = (ubyte*) malloc (size);
787 SDL_assert( (*dest) != NULL );
789 cfread((*dest), size, 1, cfp);
794 // drop everything else
799 cfseek(cfp, next_chunk, CF_SEEK_SET);
807 static int oal_get_free_buffer()
813 int size = (int)Buffers.size();
815 for (int i = 0; i < size; i++) {
816 if (Buffers[i].buf_id == 0) {
823 Buffers.push_back(nbuf);
825 return (int)(Buffers.size()-1);
828 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
830 SDL_assert( final_size != NULL );
831 SDL_assert( header != NULL );
832 SDL_assert( si != NULL );
838 int buf_idx = oal_get_free_buffer();
846 sound_buffer *buf = &Buffers[buf_idx];
848 oal_check_for_errors("oal_load_buffer() begin");
850 alGenBuffers(1, &buf->buf_id);
852 if ( !buf->buf_id ) {
856 ALenum format = AL_INVALID;
862 // the below conversion variables are only used when the wav format is not PCM.
863 ubyte *convert_buffer = NULL; // storage for converted wav file
864 int convert_len; // num bytes of converted wav file
865 uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size)
868 switch (si->format) {
869 case WAVE_FORMAT_PCM: {
870 SDL_assert( si->data != NULL );
873 bps = si->avg_bytes_per_sec;
876 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
877 // swap 16-bit sound data
881 for (uint i=0; i<size; i=i+2) {
882 swap_tmp = (ushort*)(si->data + i);
883 *swap_tmp = INTEL_SHORT(*swap_tmp);
893 case WAVE_FORMAT_ADPCM: {
894 SDL_assert( si->data != NULL );
896 // this ADPCM decoder decodes to 16-bit only so keep that in mind
897 nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" ));
899 int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, &convert_len, &src_bytes_used, 16);
901 // ACM conversion failed?
902 if ( (rc == -1) || (src_bytes_used != si->size) ) {
903 alDeleteBuffers(1, &buf->buf_id);
906 if (convert_buffer != NULL) {
907 free(convert_buffer);
914 bps = (((si->n_channels * bits) / 8) * si->sample_rate);
916 data = convert_buffer;
918 nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
924 nprintf(( "Sound", "Unsupported sound encoding\n" ));
925 alDeleteBuffers(1, &buf->buf_id);
930 // format is now in pcm
931 frequency = si->sample_rate;
934 if (si->n_channels == 2) {
935 format = AL_FORMAT_STEREO16;
936 } else if (si->n_channels == 1) {
937 format = AL_FORMAT_MONO16;
939 } else if (bits == 8) {
940 if (si->n_channels == 2) {
941 format = AL_FORMAT_STEREO8;
942 } else if (si->n_channels == 1) {
943 format = AL_FORMAT_MONO8;
947 if (format == AL_INVALID) {
948 alDeleteBuffers(1, &buf->buf_id);
951 if (convert_buffer != NULL) {
952 free(convert_buffer);
961 alBufferData(buf->buf_id, format, data, size, frequency);
964 buf->frequency = frequency;
965 buf->bits_per_sample = bits;
966 buf->nchannels = si->n_channels;
967 buf->nseconds = size / bps;
970 if (convert_buffer != NULL) {
971 free(convert_buffer);
974 oal_check_for_errors("oal_load_buffer() end");
979 void oal_unload_buffer(int sid)
985 if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
989 oal_check_for_errors("oal_unload_buffer() begin");
991 sound_buffer *buf = &Buffers[sid];
994 if (buf->chan_idx >= 0) {
995 alSourceStop(Channels[buf->chan_idx].source_id);
996 alSourcei(Channels[buf->chan_idx].source_id, AL_BUFFER, 0);
1000 alDeleteBuffers(1, &buf->buf_id);
1004 oal_check_for_errors("oal_unload_buffer() end");
1007 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
1009 if ( !OAL_inited ) {
1013 int buf_idx = oal_get_free_buffer();
1019 sound_buffer *buf = &Buffers[buf_idx];
1021 oal_check_for_errors("oal_load_buffer() begin");
1023 alGenBuffers(1, &buf->buf_id);
1025 if ( !buf->buf_id ) {
1030 buf->frequency = frequency;
1031 buf->bits_per_sample = bits_per_sample;
1032 buf->nchannels = nchannels;
1033 buf->nseconds = nseconds;
1034 buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
1039 int oal_lock_data(int sid, ubyte *data, int size)
1041 if ( !OAL_inited ) {
1045 oal_check_for_errors("oal_lock_data() begin");
1047 SDL_assert( sid >= 0 );
1048 SDL_assert( sid < (int)Buffers.size() );
1050 ALuint buf_id = Buffers[sid].buf_id;
1053 if (Buffers[sid].bits_per_sample == 16) {
1054 if (Buffers[sid].nchannels == 2) {
1055 format = AL_FORMAT_STEREO16;
1056 } else if (Buffers[sid].nchannels == 1) {
1057 format = AL_FORMAT_MONO16;
1061 } else if (Buffers[sid].bits_per_sample == 8) {
1062 if (Buffers[sid].nchannels == 2) {
1063 format = AL_FORMAT_STEREO8;
1064 } else if (Buffers[sid].nchannels == 1) {
1065 format = AL_FORMAT_MONO8;
1073 Buffers[sid].nbytes = size;
1075 alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1077 if ( oal_check_for_errors("oal_lock_data() end") ) {
1084 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1086 if ( !OAL_inited ) {
1090 SDL_assert( sid >= 0 );
1091 SDL_assert( sid < (int)Buffers.size() );
1093 oal_check_for_errors("oal_play() begin");
1095 int channel = oal_get_free_channel_idx(volume, 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 // set all the things
1112 chan->flags = flags;
1113 chan->priority = priority;
1114 chan->last_position = 0;
1115 chan->buf_idx = sid;
1116 chan->snd_id = snd_id;
1117 chan->sig = channel_next_sig++;
1119 Buffers[sid].chan_idx = channel;
1121 alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f);
1122 alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1123 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1124 alSourcef(chan->source_id, AL_GAIN, volume);
1125 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1126 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1127 alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE);
1129 // maybe attach source to reverb effect
1130 oal_efx_attach(chan->source_id);
1133 alSourcePlay(chan->source_id);
1135 if (channel_next_sig < 0) {
1136 channel_next_sig = 1;
1139 oal_check_for_errors("oal_play() end");
1144 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)
1146 if ( !OAL_inited ) {
1150 SDL_assert( sid >= 0 );
1151 SDL_assert( sid < (int)Buffers.size() );
1153 oal_check_for_errors("oal_play_3d() begin");
1155 int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1161 sound_channel *chan = &Channels[channel];
1164 alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1166 if (status == AL_PLAYING) {
1167 oal_stop_channel(channel);
1170 int flags = SND_FLAG_3D;
1173 flags |= SND_FLAG_LOOPING;
1176 // set all the things
1177 chan->vol = max_volume;
1178 chan->flags = flags;
1179 chan->priority = priority;
1180 chan->last_position = 0;
1181 chan->buf_idx = sid;
1182 chan->snd_id = snd_id;
1183 chan->sig = channel_next_sig++;
1185 Buffers[sid].chan_idx = channel;
1187 oal_update_source(channel, min, max, pos, vel);
1189 alSourcef(chan->source_id, AL_PITCH, 1.0f);
1190 alSourcef(chan->source_id, AL_GAIN, max_volume);
1191 alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1192 alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE);
1193 alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE);
1195 // maybe attach source to reverb effect
1196 oal_efx_attach(chan->source_id);
1199 alSourcePlay(chan->source_id);
1201 if (channel_next_sig < 0) {
1202 channel_next_sig = 1;
1205 oal_check_for_errors("oal_play_3d() end");
1212 ALint state, current_position;
1214 if ( !OAL_inited ) {
1218 oal_check_for_errors("oal_do_frame() begin");
1220 int size = (int)Channels.size();
1222 // make sure there aren't any looping voice messages
1223 for (int i = 0; i < size; i++) {
1224 if (Channels[i].flags & SND_FLAG_EXT) {
1225 // streaming sources should be managed elsewhere
1229 if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) {
1230 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state);
1232 if (state != AL_PLAYING) {
1236 alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, ¤t_position);
1238 if (current_position != 0) {
1239 if (current_position < Channels[i].last_position) {
1240 alSourceStop(Channels[i].source_id);
1242 Channels[i].last_position = current_position;
1248 oal_check_for_errors("oal_do_frame() end");
1251 int oal_update_source(int channel, int min, int max, vector *pos, vector *vel)
1253 if ( !OAL_inited ) {
1261 if ( !(Channels[channel].flags & SND_FLAG_3D) ) {
1265 ALuint source_id = Channels[channel].source_id;
1266 ALfloat rolloff = 1.0f;
1268 oal_check_for_errors("oal_update_source() begin");
1271 alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1275 alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1277 alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1284 const float MIN_GAIN = 0.05f;
1285 float minf = i2fl(min);
1286 float maxf = i2fl(max);
1288 // yep, just making this shit up
1289 rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN;
1291 if (rolloff < 0.0f) {
1296 alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff);
1298 alSourcei(source_id, AL_REFERENCE_DISTANCE, min);
1299 alSourcei(source_id, AL_MAX_DISTANCE, max);
1302 oal_check_for_errors("oal_update_source() end");
1307 int oal_update_listener(vector *pos, vector *vel, matrix *orient)
1309 if ( !OAL_inited ) {
1313 oal_check_for_errors("oal_update_listener() begin");
1316 alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1320 alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1324 ALfloat alOrient[6];
1326 alOrient[0] = orient->v.fvec.xyz.x;
1327 alOrient[1] = orient->v.fvec.xyz.y;
1328 alOrient[2] = -orient->v.fvec.xyz.z;
1330 alOrient[3] = orient->v.uvec.xyz.x;
1331 alOrient[4] = orient->v.uvec.xyz.y;
1332 alOrient[5] = -orient->v.uvec.xyz.z;
1334 alListenerfv(AL_ORIENTATION, alOrient);
1337 oal_check_for_errors("oal_update_listener() end");