]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/oal.cpp
fix faulty flag check
[taylor/freespace2.git] / src / sound / oal.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 #include <vector>
10 #include <list>
11
12 #include "pstypes.h"
13 #include "oal.h"
14 #include "oal_efx.h"
15 #include "cfile.h"
16 #include "sound.h"
17 #include "acm.h"
18
19
20 static int OAL_inited = 0;
21
22 static ALCdevice *al_device = NULL;
23 static ALCcontext *al_context = NULL;
24
25
26 struct sound_buffer {
27         ALuint buf_id;          // OpenAL buffer id
28         int chan_idx;           // channel index this buffer is currently bound to
29
30         int frequency;
31         int bits_per_sample;
32         int nchannels;
33         int nseconds;
34         int nbytes;
35
36         sound_buffer() : buf_id(0), chan_idx(-1), frequency(0), bits_per_sample(0),
37                         nchannels(0), nseconds(0), nbytes(0)
38         {
39         }
40 };
41
42 static std::vector<sound_buffer> Buffers;
43
44 static std::vector<sound_channel> Channels;
45 static int channel_next_sig = 1;
46
47 extern void oal_efx_attach(ALuint source_id);
48
49
50 bool oal_check_for_errors(const char *location)
51 {
52         ALenum err = alGetError();
53
54         if (err != AL_NO_ERROR) {
55 #ifndef NDEBUG
56                 if (location) {
57                         const char *str = alGetString(err);
58
59                         nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s\n", location, err, (str) ? str : "??"));
60                 } else {
61                         nprintf(("OpenAL", "AL-ERROR => 0x%x: %s\n", err, alGetString(err)));
62                 }
63 #endif
64                 return true;
65         }
66
67         return false;
68 }
69
70 static void oal_init_channels()
71 {
72         const int MAX_SOURCES = 32;
73
74         Channels.reserve(MAX_SOURCES);
75
76         for (int n = 0; n < MAX_SOURCES; n++) {
77                 sound_channel n_channel;
78
79                 alGenSources(1, &n_channel.source_id);
80
81                 if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) {
82                         break;
83                 }
84
85                 Channels.push_back(n_channel);
86         }
87 }
88
89 int oal_init(int use_eax)
90 {
91         ALint ver_major = 0, ver_minor = 0;
92
93         if (OAL_inited) {
94                 return 0;
95         }
96
97         nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" ));
98
99         alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &ver_major);
100         alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &ver_minor);
101
102         if ( (ver_major < 1) || (ver_minor < 1) ) {
103                 nprintf(("Sound", "SOUND ==> Minimum supported OpenAL version is 1.1\n"));
104                 return -1;
105         }
106
107         al_device = alcOpenDevice(NULL);
108
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))));
112                 return -1;
113         }
114
115         al_context = alcCreateContext(al_device, NULL);
116
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))));
120
121                 alcCloseDevice(al_device);
122                 al_device = NULL;
123
124                 return -1;
125         }
126
127         alcMakeContextCurrent(al_context);
128
129         OAL_inited = 1;
130
131         oal_init_channels();
132
133         Buffers.reserve(64);
134
135         if (use_eax) {
136                 oal_efx_init();
137         }
138
139         oal_check_for_errors("oal_init() end");
140
141         return 0;
142 }
143
144 void oal_close()
145 {
146         if ( !OAL_inited ) {
147                 return;
148         }
149
150         oal_check_for_errors("oal_close() begin");
151
152         while ( !Channels.empty() ) {
153                 ALuint sid = Channels.back().source_id;
154
155                 alSourceStop(sid);
156
157                 alSourcei(sid, AL_BUFFER, 0);
158
159                 alDeleteSources(1, &sid);
160
161                 Channels.pop_back();
162         }
163
164         while ( !Buffers.empty() ) {
165                 ALuint bid = Buffers.back().buf_id;
166
167                 if ( alIsBuffer(bid) ) {
168                         alDeleteBuffers(1, &bid);
169                 }
170
171                 Buffers.pop_back();
172         }
173
174         oal_efx_close();
175
176         oal_check_for_errors("oal_close() end");
177
178         Channels.clear();
179         Buffers.clear();
180
181         alcMakeContextCurrent(NULL);
182         alcDestroyContext(al_context);
183         alcCloseDevice(al_device);
184
185         al_context = NULL;
186         al_device = NULL;
187
188         OAL_inited = 0;
189 }
190
191 int oal_get_channel(int sig)
192 {
193         int i;
194
195         if ( !OAL_inited ) {
196                 return -1;
197         }
198
199         int size = (int)Channels.size();
200
201         for (i = 0; i < size; i++) {
202                 if (Channels[i].sig == sig) {
203                         ALint status;
204
205                         alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
206
207                         if (status == AL_PLAYING) {
208                                 return i;
209                         } else {
210                                 return -1;
211                         }
212                 }
213         }
214
215         return -1;
216 }
217
218 int oal_get_number_channels()
219 {
220         int i;
221         ALint status;
222         int count = 0;
223
224         if ( !OAL_inited ) {
225                 return -1;
226         }
227
228         int size = (int)Channels.size();
229
230         for (i = 0; i < size; i++) {
231                 alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status);
232
233                 if (status == AL_PLAYING) {
234                         count++;
235                 }
236         }
237
238         return count;
239 }
240
241 void oal_stop_buffer(int sid)
242 {
243         if ( !OAL_inited ) {
244                 return;
245         }
246
247         oal_check_for_errors("oal_stop_buffer() begin");
248
249         SDL_assert( sid >= 0 );
250         SDL_assert( sid < (int)Buffers.size() );
251
252         int cid = Buffers[sid].chan_idx;
253
254         if (cid != -1) {
255                 ALuint source_id = Channels[cid].source_id;
256
257                 alSourceStop(source_id);
258                 alSourcei(source_id, AL_BUFFER, 0);
259         }
260
261         oal_check_for_errors("oal_stop_buffer() end");
262 }
263
264 void oal_stop_channel(int channel)
265 {
266         if ( !OAL_inited ) {
267                 return;
268         }
269
270         SDL_assert( channel >= 0 );
271         SDL_assert( channel < (int)Channels.size() );
272
273         if (Channels[channel].flags & SND_FLAG_EXT) {
274                 return;
275         }
276
277         oal_check_for_errors("oal_stop_channel() begin");
278
279         alSourceStop(Channels[channel].source_id);
280
281         alSourcei(Channels[channel].source_id, AL_BUFFER, 0);
282         Channels[channel].buf_idx = -1;
283
284         oal_check_for_errors("oal_stop_channel() end");
285 }
286
287 void oal_stop_channel_all()
288 {
289         if ( !OAL_inited ) {
290                 return;
291         }
292
293         int size = (int)Channels.size();
294
295         for (int i = 0; i < size; i++) {
296                 if (Channels[i].flags & SND_FLAG_EXT) {
297                         continue;
298                 }
299
300                 oal_stop_channel(i);
301         }
302 }
303
304 int oal_get_buffer_size(int sid, int *size)
305 {
306         if ( !OAL_inited ) {
307                 return -1;
308         }
309
310         if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
311                 return -1;
312         }
313
314         *size = Buffers[sid].nbytes;
315
316         return 0;
317 }
318
319 int oal_get_channel_size(int channel)
320 {
321         if ( !OAL_inited ) {
322                 return -1;
323         }
324
325         if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
326                 return -1;
327         }
328
329         if (Channels[channel].buf_idx >= 0) {
330                 return Buffers[Channels[channel].buf_idx].nbytes;
331         }
332
333         return 0;
334 }
335
336 // -----------------------------------------------------------------------------
337 // Source properties *set functions
338 // -----------------------------------------------------------------------------
339
340 void oal_set_volume(int channel, float volume)
341 {
342         if ( !OAL_inited ) {
343                 return;
344         }
345
346         SDL_assert( channel >= 0 );
347         SDL_assert( channel < (int)Channels.size() );
348         SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
349
350         oal_check_for_errors("oal_set_volume() begin");
351
352         alSourcef(Channels[channel].source_id, AL_GAIN, volume);
353
354         oal_check_for_errors("oal_set_volume() end");
355 }
356
357 void oal_set_pan(int channel, float pan)
358 {
359         if ( !OAL_inited ) {
360                 return;
361         }
362
363         SDL_assert( channel >= 0 );
364         SDL_assert( channel < (int)Channels.size() );
365         SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
366
367         oal_check_for_errors("oal_set_pan() begin");
368
369         alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
370
371         oal_check_for_errors("oal_set_pan() end");
372 }
373
374 void oal_set_pitch(int channel, float pitch)
375 {
376         if ( !OAL_inited ) {
377                 return;
378         }
379
380         SDL_assert( channel >= 0 );
381         SDL_assert( channel < (int)Channels.size() );
382         SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
383
384         oal_check_for_errors("oal_set_pitch() begin");
385
386         alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
387
388         oal_check_for_errors("oal_set_pitch() end");
389 }
390
391 void oal_set_play_position(int channel, int position)
392 {
393         if ( !OAL_inited ) {
394                 return;
395         }
396
397         SDL_assert( channel >= 0 );
398         SDL_assert( channel < (int)Channels.size() );
399         SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
400
401         oal_check_for_errors("oal_set_play_position() begin");
402
403         alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
404
405         oal_check_for_errors("oal_set_play_position() end");
406 }
407
408 // -----------------------------------------------------------------------------
409
410 // -----------------------------------------------------------------------------
411 // Source properties *get functions
412 // -----------------------------------------------------------------------------
413
414 float oal_get_pitch(int channel)
415 {
416         float pitch = 1.0f;
417
418         if ( !OAL_inited ) {
419                 return 1.0f;
420         }
421
422         SDL_assert( channel >= 0 );
423         SDL_assert( channel < (int)Channels.size() );
424         SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
425
426         oal_check_for_errors("oal_get_pitch() begin");
427
428         alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
429
430         oal_check_for_errors("oal_get_pitch() end");
431
432         return pitch;
433 }
434
435 int oal_get_play_position(int channel)
436 {
437         ALint offset = 0;
438
439         if ( !OAL_inited ) {
440                 return 0;
441         }
442
443         if (channel < 0) {
444                 return 0;
445         }
446
447         //SDL_assert( channel >= 0 );
448         SDL_assert( channel < (int)Channels.size() );
449
450         oal_check_for_errors("oal_get_play_position() begin");
451
452         alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
453
454         if (alGetError() != AL_NO_ERROR) {
455                 return offset;
456         }
457
458         return 0;
459 }
460
461 // -----------------------------------------------------------------------------
462
463 int oal_is_initted()
464 {
465         return OAL_inited;
466 }
467
468 int oal_is_channel_playing(int channel)
469 {
470         ALint status;
471
472         if ( !OAL_inited ) {
473                 return 0;
474         }
475
476         SDL_assert( channel >= 0 );
477         SDL_assert( channel < (int)Channels.size() );
478
479         oal_check_for_errors("oal_is_channel_playing() begin");
480
481         alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
482
483         oal_check_for_errors("oal_is_channel_playing() end");
484
485         if (status == AL_PLAYING) {
486                 return 1;
487         }
488
489         return 0;
490 }
491
492 void oal_chg_loop_status(int channel, int loop)
493 {
494         if ( !OAL_inited ) {
495                 return;
496         }
497
498         SDL_assert( channel >= 0 );
499         SDL_assert( channel < (int)Channels.size() );
500         SDL_assert( !(Channels[channel].flags & SND_FLAG_EXT) );
501
502         oal_check_for_errors("oal_chg_loop_status() begin");
503
504         alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
505
506         if (loop) {
507                 Channels[channel].flags |= SND_FLAG_LOOPING;
508         } else {
509                 Channels[channel].flags &= ~SND_FLAG_LOOPING;
510         }
511
512         oal_check_for_errors("oal_chg_loop_status() end");
513 }
514
515 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
516 {
517         int     i, limit;
518         float lowest_vol = 0.0f;
519         int lowest_vol_index = -1;
520         int status;
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;
524
525         int first_free_channel = -1;
526
527         if ( !OAL_inited ) {
528                 return -1;
529         }
530
531         int size = (int)Channels.size();
532
533         oal_check_for_errors("oal_get_free_channel_idx() begin");
534
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;
539
540                 if (chp->snd_id == 0) {
541                         if (first_free_channel == -1) {
542                                 first_free_channel = i;
543                         }
544
545                         continue;
546                 }
547
548                 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
549
550                 if ( (status != AL_PLAYING) && (status != AL_PAUSED) ) {
551                         if (first_free_channel == -1) {
552                                 first_free_channel = i;
553                         }
554
555                         continue;
556                 } else {
557                         if (chp->snd_id == snd_id) {
558                                 instance_count++;
559
560                                 if ( (chp->vol < lowest_instance_vol) && !looping ) {
561                                         lowest_instance_vol = chp->vol;
562                                         lowest_instance_vol_index = i;
563                                 }
564                         }
565
566                         if ( (chp->vol < lowest_vol) && !looping ) {
567                                 lowest_vol_index = i;
568                                 lowest_vol = chp->vol;
569                         }
570                 }
571         }
572
573         // determine the limit of concurrent instances of this sound
574         switch (priority) {
575                 case SND_PRIORITY_MUST_PLAY:
576                         limit = 100;
577                         break;
578
579                 case SND_PRIORITY_SINGLE_INSTANCE:
580                         limit = 1;
581                         break;
582
583                 case SND_PRIORITY_DOUBLE_INSTANCE:
584                         limit = 2;
585                         break;
586
587                 case SND_PRIORITY_TRIPLE_INSTANCE:
588                         limit = 3;
589                         break;
590
591                 default:
592                         Int3();                 // get Alan
593                         limit = 100;
594                         break;
595         }
596
597
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;
603                 } else {
604                         first_free_channel = -1;
605                 }
606         } else {
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;
615                                 }
616                         }
617                 }
618         }
619
620         oal_check_for_errors("oal_get_free_channel_idx() end");
621
622         return first_free_channel;
623 }
624
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)
627 {
628         if ( !OAL_inited ) {
629                 return NULL;
630         }
631
632         int chan = oal_get_free_channel_idx(volume, snd_id, priority);
633
634         if (chan < 0) {
635                 return NULL;
636         }
637
638         SDL_assert( Channels[chan].source_id != 0 );
639
640         alSourceStop(Channels[chan].source_id);
641         alSourcei(Channels[chan].source_id, AL_BUFFER, 0);
642
643         if (Channels[chan].buf_idx >= 0) {
644                 Buffers[Channels[chan].buf_idx].chan_idx = -1;
645         }
646
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++;
654
655         if (channel_next_sig < 0) {
656                 channel_next_sig = 1;
657         }
658
659         return &Channels[chan];
660 }
661
662 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
663 {
664         CFILE *cfp = NULL;
665         int id = 0;
666         unsigned int tag = 0, size = 0, next_chunk;
667         WAVE_chunk hdr;
668
669         if ( !OAL_inited ) {
670                 return 0;
671         }
672
673         cfp = cfopen(filename, "rb");
674
675         if (cfp == NULL) {
676                 nprintf(("Error", "Couldn't open '%s'\n", filename ));
677                 return -1;
678         }
679
680         // check for valid file type
681         id = cfread_int(cfp);
682
683         // 'RIFF'
684         if (id != 0x46464952) {
685                 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
686                 cfclose(cfp);
687                 return -1;
688         }
689
690         // skip RIFF size
691         cfread_int(cfp);
692
693         // check for valid RIFF type
694         id = cfread_int(cfp);
695
696         // 'WAVE'
697         if (id != 0x45564157) {
698                 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
699                 cfclose(cfp);
700                 return -1;
701         }
702
703         // parse WAVE tags
704         while ( !cfeof(cfp) ) {
705                 tag = cfread_uint(cfp);
706                 size = cfread_uint(cfp);
707
708                 next_chunk = cftell(cfp) + size;
709
710                 switch (tag) {
711                         // 'fmt '
712                         case 0x20746d66: {
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);
719
720                                 if (hdr.code != 1) {
721                                         hdr.extra_size = cfread_ushort(cfp);
722                                 }
723
724                                 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
725                                 SDL_assert( (*header) != NULL );
726
727                                 memcpy((*header), &hdr, sizeof(WAVE_chunk));
728
729                                 if (hdr.extra_size) {
730                                         (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
731                                         SDL_assert( (*header)->extra_data != NULL );
732
733                                         cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
734                                 }
735
736                                 break;
737                         }
738
739                         // 'data'
740                         case 0x61746164: {
741                                 *dest_size = size;
742
743                                 (*dest) = (ubyte*) malloc (size);
744                                 SDL_assert( (*dest) != NULL );
745
746                                 cfread((*dest), size, 1, cfp);
747
748                                 break;
749                         }
750
751                         // drop everything else
752                         default:
753                                 break;
754                 }
755
756                 cfseek(cfp, next_chunk, CF_SEEK_SET);
757         }
758
759         cfclose(cfp);
760
761         return 0;
762 }
763
764 static int oal_get_free_buffer()
765 {
766         if ( !OAL_inited ) {
767                 return -1;
768         }
769
770         int size = (int)Buffers.size();
771
772         for (int i = 0; i < size; i++) {
773                 if (Buffers[i].buf_id == 0) {
774                         return i;
775                 }
776         }
777
778         sound_buffer nbuf;
779
780         Buffers.push_back(nbuf);
781
782         return (int)(Buffers.size()-1);
783 }
784
785 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
786 {
787         SDL_assert( final_size != NULL );
788         SDL_assert( header != NULL );
789         SDL_assert( si != NULL );
790
791         if ( !OAL_inited ) {
792                 return 0;
793         }
794
795         int buf_idx = oal_get_free_buffer();
796
797         if (buf_idx < 0) {
798                 return -1;
799         }
800
801         *sid = buf_idx;
802
803         sound_buffer *buf = &Buffers[buf_idx];
804
805         oal_check_for_errors("oal_load_buffer() begin");
806
807         alGenBuffers(1, &buf->buf_id);
808
809         if ( !buf->buf_id ) {
810                 return -1;
811         }
812
813         ALenum format = AL_INVALID;
814         ALsizei size;
815         ALint bits, bps;
816         ALuint frequency;
817         ALvoid *data = NULL;
818
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)
823
824
825         switch (si->format) {
826                 case WAVE_FORMAT_PCM: {
827                         SDL_assert( si->data != NULL );
828
829                         bits = si->bits;
830                         bps  = si->avg_bytes_per_sec;
831                         size = si->size;
832
833 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
834                         // swap 16-bit sound data
835                         if (bits == 16) {
836                                 ushort *swap_tmp;
837
838                                 for (uint i=0; i<size; i=i+2) {
839                                         swap_tmp = (ushort*)(si->data + i);
840                                         *swap_tmp = INTEL_SHORT(*swap_tmp);
841                                 }
842                         }
843 #endif
844
845                         data = si->data;
846
847                         break;
848                 }
849
850                 case WAVE_FORMAT_ADPCM: {
851                         SDL_assert( si->data != NULL );
852
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" ));
855
856                         int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16);
857
858                         // ACM conversion failed?
859                         if ( (rc == -1) || (src_bytes_used != si->size) ) {
860                                 alDeleteBuffers(1, &buf->buf_id);
861                                 buf->buf_id = 0;
862
863                                 if (convert_buffer != NULL) {
864                                         free(convert_buffer);
865                                 }
866
867                                 return -1;
868                         }
869
870                         bits = 16;
871                         bps  = (((si->n_channels * bits) / 8) * si->sample_rate);
872                         size = convert_len;
873                         data = convert_buffer;
874
875                         nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
876
877                         break;
878                 }
879
880                 default:
881                         nprintf(( "Sound", "Unsupported sound encoding\n" ));
882                         alDeleteBuffers(1, &buf->buf_id);
883                         buf->buf_id = 0;
884                         return -1;
885         }
886
887         // format is now in pcm
888         frequency = si->sample_rate;
889
890         if (bits == 16) {
891                 if (si->n_channels == 2) {
892                         format = AL_FORMAT_STEREO16;
893                 } else if (si->n_channels == 1) {
894                         format = AL_FORMAT_MONO16;
895                 }
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;
901                 }
902         }
903
904         if (format == AL_INVALID) {
905                 alDeleteBuffers(1, &buf->buf_id);
906                 buf->buf_id = 0;
907
908                 if (convert_buffer != NULL) {
909                         free(convert_buffer);
910                 }
911
912                 return -1;
913         }
914
915         Snd_sram += size;
916         *final_size = size;
917
918         alBufferData(buf->buf_id, format, data, size, frequency);
919
920         buf->chan_idx = -1;
921         buf->frequency = frequency;
922         buf->bits_per_sample = bits;
923         buf->nchannels = si->n_channels;
924         buf->nseconds = size / bps;
925         buf->nbytes = size;
926
927         if (convert_buffer != NULL) {
928                 free(convert_buffer);
929         }
930
931         oal_check_for_errors("oal_load_buffer() end");
932
933         return 0;
934 }
935
936 void oal_unload_buffer(int sid)
937 {
938         if ( !OAL_inited ) {
939                 return;
940         }
941
942         if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
943                 return;
944         }
945
946         oal_check_for_errors("oal_unload_buffer() begin");
947
948         sound_buffer *buf = &Buffers[sid];
949
950         if (buf->buf_id) {
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);
954                         buf->chan_idx = -1;
955                 }
956
957                 alDeleteBuffers(1, &buf->buf_id);
958                 buf->buf_id = 0;
959         }
960
961         oal_check_for_errors("oal_unload_buffer() end");
962 }
963
964 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
965 {
966         if ( !OAL_inited ) {
967                 return -1;
968         }
969
970         int buf_idx = oal_get_free_buffer();
971
972         if (buf_idx < 0) {
973                 return -1;
974         }
975
976         sound_buffer *buf = &Buffers[buf_idx];
977
978         oal_check_for_errors("oal_load_buffer() begin");
979
980         alGenBuffers(1, &buf->buf_id);
981
982         if ( !buf->buf_id ) {
983                 return -1;
984         }
985
986         buf->chan_idx = -1;
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;
992
993         return buf_idx;
994 }
995
996 int oal_lock_data(int sid, ubyte *data, int size)
997 {
998         if ( !OAL_inited ) {
999                 return -1;
1000         }
1001
1002         oal_check_for_errors("oal_lock_data() begin");
1003
1004         SDL_assert( sid >= 0 );
1005         SDL_assert( sid < (int)Buffers.size() );
1006
1007         ALuint buf_id = Buffers[sid].buf_id;
1008         ALenum format;
1009
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;
1015                 } else {
1016                         return -1;
1017                 }
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;
1023                 } else {
1024                         return -1;
1025                 }
1026         } else {
1027                 return -1;
1028         }
1029
1030         Buffers[sid].nbytes = size;
1031
1032         alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1033
1034         if ( oal_check_for_errors("oal_lock_data() end") ) {
1035                 return -1;
1036         }
1037
1038         return 0;
1039 }
1040
1041 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1042 {
1043         if ( !OAL_inited ) {
1044                 return -1;
1045         }
1046
1047         SDL_assert( sid >= 0 );
1048         SDL_assert( sid < (int)Buffers.size() );
1049
1050         oal_check_for_errors("oal_play() begin");
1051
1052         int channel = oal_get_free_channel_idx(volume, snd_id, priority);
1053
1054         if (channel < 0) {
1055                 return -1;
1056         }
1057
1058         sound_channel *chan = &Channels[channel];
1059
1060         ALint status;
1061         alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1062
1063         if (status == AL_PLAYING) {
1064                 oal_stop_channel(channel);
1065         }
1066
1067         // set all the things
1068         chan->vol = volume;
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++;
1075
1076         Buffers[sid].chan_idx = channel;
1077
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);
1085
1086         // maybe attach source to reverb effect
1087         oal_efx_attach(chan->source_id);
1088
1089         // Actually play it
1090         alSourcePlay(chan->source_id);
1091
1092         if (channel_next_sig < 0) {
1093                 channel_next_sig = 1;
1094         }
1095
1096         oal_check_for_errors("oal_play() end");
1097
1098         return chan->sig;
1099 }
1100
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)
1102 {
1103         if ( !OAL_inited ) {
1104                 return -1;
1105         }
1106
1107         SDL_assert( sid >= 0 );
1108         SDL_assert( sid < (int)Buffers.size() );
1109
1110         oal_check_for_errors("oal_play_3d() begin");
1111
1112         int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1113
1114         if (channel < 0) {
1115                 return -1;
1116         }
1117
1118         sound_channel *chan = &Channels[channel];
1119
1120         ALint status;
1121         alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1122
1123         if (status == AL_PLAYING) {
1124                 oal_stop_channel(channel);
1125         }
1126
1127         int flags = SND_FLAG_3D;
1128
1129         if (looping) {
1130                 flags |= SND_FLAG_LOOPING;
1131         }
1132
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++;
1141
1142         Buffers[sid].chan_idx = channel;
1143
1144         oal_update_source(channel, min, max, pos, vel);
1145
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);
1151
1152         // maybe attach source to reverb effect
1153         oal_efx_attach(chan->source_id);
1154
1155         // Actually play it
1156         alSourcePlay(chan->source_id);
1157
1158         if (channel_next_sig < 0) {
1159                 channel_next_sig = 1;
1160         }
1161
1162         oal_check_for_errors("oal_play_3d() end");
1163
1164         return chan->sig;
1165 }
1166
1167 void oal_do_frame()
1168 {
1169         ALint state, current_position;
1170
1171         if ( !OAL_inited ) {
1172                 return;
1173         }
1174
1175         oal_check_for_errors("oal_do_frame() begin");
1176
1177         int size = (int)Channels.size();
1178
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
1183                         continue;
1184                 }
1185
1186                 if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) {
1187                         alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state);
1188
1189                         if (state != AL_PLAYING) {
1190                                 continue;
1191                         }
1192
1193                         alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, &current_position);
1194
1195                         if (current_position != 0) {
1196                                 if (current_position < Channels[i].last_position) {
1197                                         alSourceStop(Channels[i].source_id);
1198                                 } else {
1199                                         Channels[i].last_position = current_position;
1200                                 }
1201                         }
1202                 }
1203         }
1204
1205         oal_check_for_errors("oal_do_frame() end");
1206 }
1207
1208 int oal_update_source(int channel, int min, int max, vector *pos, vector *vel)
1209 {
1210         if ( !OAL_inited ) {
1211                 return 0;
1212         }
1213
1214         if (channel < 0) {
1215                 return 0;
1216         }
1217
1218         if ( !(Channels[channel].flags & SND_FLAG_3D) ) {
1219                 return 1;
1220         }
1221
1222         ALuint source_id = Channels[channel].source_id;
1223         ALfloat rolloff = 1.0f;
1224
1225         oal_check_for_errors("oal_update_source() begin");
1226
1227         if (pos) {
1228                 alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1229         }
1230
1231         if (vel) {
1232                 alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1233         } else {
1234                 alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1235         }
1236
1237         if (min >= 0) {
1238                 if (max <= min) {
1239                         rolloff = 0.0f;
1240                 } else {
1241                         const float MIN_GAIN = 0.05f;
1242                         float minf = i2fl(min);
1243                         float maxf = i2fl(max);
1244
1245                         // yep, just making this shit up
1246                         rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN;
1247
1248                         if (rolloff < 0.0f) {
1249                                 rolloff = 0.0f;
1250                         }
1251                 }
1252
1253                 alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff);
1254
1255                 alSourcei(source_id, AL_REFERENCE_DISTANCE, min);
1256                 alSourcei(source_id, AL_MAX_DISTANCE, max);
1257         }
1258
1259         oal_check_for_errors("oal_update_source() end");
1260
1261         return 0;
1262 }
1263
1264 int oal_update_listener(vector *pos, vector *vel, matrix *orient)
1265 {
1266         if ( !OAL_inited ) {
1267                 return 0;
1268         }
1269
1270         oal_check_for_errors("oal_update_listener() begin");
1271
1272         if (pos) {
1273                 alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1274         }
1275
1276         if (vel) {
1277                 alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1278         }
1279
1280         if (orient) {
1281                 ALfloat alOrient[6];
1282
1283                 alOrient[0] =  orient->v.fvec.xyz.x;
1284                 alOrient[1] =  orient->v.fvec.xyz.y;
1285                 alOrient[2] = -orient->v.fvec.xyz.z;
1286
1287                 alOrient[3] =  orient->v.uvec.xyz.x;
1288                 alOrient[4] =  orient->v.uvec.xyz.y;
1289                 alOrient[5] = -orient->v.uvec.xyz.z;
1290
1291                 alListenerfv(AL_ORIENTATION, alOrient);
1292         }
1293
1294         oal_check_for_errors("oal_update_listener() end");
1295
1296         return 0;
1297 }