]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/oal.cpp
first pass at updated sound code
[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
48 bool oal_check_for_errors(const char *location)
49 {
50         ALenum err = alGetError();
51
52         if (err != AL_NO_ERROR) {
53                 if (location) {
54                         const char *str = alGetString(err);
55
56                         nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s", location, err, (str) ? str : "??"));
57                 } else {
58                         nprintf(("OpenAL", "AL-ERROR => 0x%x: %s", err, alGetString(err)));
59                 }
60
61                 return true;
62         }
63
64         return false;
65 }
66
67 static void oal_init_channels()
68 {
69         const int MAX_SOURCES = 32;
70
71         Channels.reserve(MAX_SOURCES);
72
73         for (int n = 0; n < MAX_SOURCES; n++) {
74                 sound_channel n_channel;
75
76                 alGenSources(1, &n_channel.source_id);
77
78                 if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) {
79                         break;
80                 }
81
82                 Channels.push_back(n_channel);
83         }
84 }
85
86 int oal_init(int use_eax)
87 {
88         ALint ver_major = 0, ver_minor = 0;
89
90         if (OAL_inited) {
91                 return 0;
92         }
93
94         nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" ));
95
96         oal_check_for_errors("oal_init() begin");
97
98         alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &ver_major);
99         alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &ver_minor);
100
101         if ( (ver_major < 1) || (ver_minor < 1) ) {
102                 nprintf(("Sound", "SOUND ==> Minimum supported OpenAL version is 1.1\n"));
103                 return -1;
104         }
105
106         al_device = alcOpenDevice(NULL);
107
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))));
111                 return -1;
112         }
113
114         al_context = alcCreateContext(al_device, NULL);
115
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))));
119
120                 alcCloseDevice(al_device);
121                 al_device = NULL;
122
123                 return -1;
124         }
125
126         alcMakeContextCurrent(al_context);
127
128         oal_init_channels();
129
130         Buffers.reserve(64);
131
132         if (use_eax) {
133                 oal_efx_init();
134         }
135
136         OAL_inited = 1;
137
138         oal_check_for_errors("oal_init() end");
139
140         return 0;
141 }
142
143 void oal_close()
144 {
145         if ( !OAL_inited ) {
146                 return;
147         }
148
149         while ( !Channels.empty() ) {
150                 ALint processed = 0;
151                 ALuint bid;
152                 ALuint sid = Channels.back().source_id;
153
154                 alSourceStop(sid);
155
156                 alGetSourcei(sid, AL_BUFFERS_PROCESSED, &processed);
157
158                 while (processed > 0) {
159                         alSourceUnqueueBuffers(sid, 1, &bid);
160                         --processed;
161                 }
162
163                 alSourcei(sid, AL_BUFFER, 0);
164
165                 alDeleteSources(1, &sid);
166
167                 Channels.pop_back();
168         }
169
170         while ( !Buffers.empty() ) {
171                 ALuint bid = Buffers.back().buf_id;
172
173                 alDeleteBuffers(1, &bid);
174
175                 Buffers.pop_back();
176         }
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         }
259
260         oal_check_for_errors("oal_stop_buffer() end");
261 }
262
263 void oal_stop_channel(int channel)
264 {
265         ALint processed = 0;
266         ALuint bid;
267
268         if ( !OAL_inited ) {
269                 return;
270         }
271
272         SDL_assert( channel >= 0 );
273         SDL_assert( channel < (int)Channels.size() );
274
275         oal_check_for_errors("oal_stop_channel() begin");
276
277         alSourceStop(Channels[channel].source_id);
278
279         // if this channel was used for streaming, make sure to unqueue any buffers
280         if (Channels[channel].snd_id < 0) {
281                 alGetSourcei(Channels[channel].source_id, AL_BUFFERS_PROCESSED, &processed);
282
283                 while (processed > 0) {
284                         alSourceUnqueueBuffers(Channels[channel].source_id, 1, &bid);
285                         --processed;
286                 }
287         }
288
289         oal_check_for_errors("oal_stop_channel() end");
290 }
291
292 void oal_stop_channel_all()
293 {
294         if ( !OAL_inited ) {
295                 return;
296         }
297
298         int size = (int)Channels.size();
299
300         for (int i = 0; i < size; i++) {
301                 oal_stop_channel(i);
302         }
303 }
304
305 int oal_get_buffer_size(int sid, int *size)
306 {
307         if ( !OAL_inited ) {
308                 return -1;
309         }
310
311         if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
312                 return -1;
313         }
314
315         *size = Buffers[sid].nbytes;
316
317         return 0;
318 }
319
320 int oal_get_channel_size(int channel)
321 {
322         if ( !OAL_inited ) {
323                 return -1;
324         }
325
326         if ( (channel < 0) || (channel >= (int)Channels.size()) ) {
327                 return -1;
328         }
329
330         if (Channels[channel].buf_idx >= 0) {
331                 return Buffers[Channels[channel].buf_idx].nbytes;
332         }
333
334         return 0;
335 }
336
337 // -----------------------------------------------------------------------------
338 // Source properties *set functions
339 // -----------------------------------------------------------------------------
340
341 void oal_set_volume(int channel, float volume)
342 {
343         if ( !OAL_inited ) {
344                 return;
345         }
346
347         SDL_assert( channel >= 0 );
348         SDL_assert( channel < (int)Channels.size() );
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
366         oal_check_for_errors("oal_set_pan() begin");
367
368         alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f);
369
370         oal_check_for_errors("oal_set_pan() end");
371 }
372
373 void oal_set_pitch(int channel, float pitch)
374 {
375         if ( !OAL_inited ) {
376                 return;
377         }
378
379         SDL_assert( channel >= 0 );
380         SDL_assert( channel < (int)Channels.size() );
381
382         oal_check_for_errors("oal_set_pitch() begin");
383
384         alSourcef(Channels[channel].source_id, AL_PITCH, pitch);
385
386         oal_check_for_errors("oal_set_pitch() end");
387 }
388
389 void oal_set_play_position(int channel, int position)
390 {
391         if ( !OAL_inited ) {
392                 return;
393         }
394
395         SDL_assert( channel >= 0 );
396         SDL_assert( channel < (int)Channels.size() );
397
398         oal_check_for_errors("oal_set_play_position() begin");
399
400         alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position);
401
402         oal_check_for_errors("oal_set_play_position() end");
403 }
404
405 void oal_set_source_properties_all(ALenum param, ALint *props)
406 {
407         if (props == NULL) {
408                 return;
409         }
410
411         oal_check_for_errors("oal_set_source_properties_all() begin");
412
413         int size = (int)Channels.size();
414
415         // make sure there aren't any looping voice messages
416         for (int i = 0; i < size; i++) {
417                 alSourceiv(Channels[i].source_id, param, props);
418         }
419
420         oal_check_for_errors("oal_set_source_properties_all() end");
421 }
422
423 // -----------------------------------------------------------------------------
424
425 // -----------------------------------------------------------------------------
426 // Source properties *get functions
427 // -----------------------------------------------------------------------------
428
429 float oal_get_pitch(int channel)
430 {
431         float pitch = 1.0f;
432
433         if ( !OAL_inited ) {
434                 return 1.0f;
435         }
436
437         SDL_assert( channel >= 0 );
438         SDL_assert( channel < (int)Channels.size() );
439
440         oal_check_for_errors("oal_get_pitch() begin");
441
442         alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch);
443
444         oal_check_for_errors("oal_get_pitch() end");
445
446         return pitch;
447 }
448
449 int oal_get_play_position(int channel)
450 {
451         ALint offset = 0;
452
453         if ( !OAL_inited ) {
454                 return 0;
455         }
456
457         if (channel < 0) {
458                 return 0;
459         }
460
461         //SDL_assert( channel >= 0 );
462         SDL_assert( channel < (int)Channels.size() );
463
464         oal_check_for_errors("oal_get_play_position() begin");
465
466         alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset);
467
468         if (alGetError() != AL_NO_ERROR) {
469                 return offset;
470         }
471
472         return 0;
473 }
474
475 // -----------------------------------------------------------------------------
476
477 int oal_is_initted()
478 {
479         return OAL_inited;
480 }
481
482 int oal_is_channel_playing(int channel)
483 {
484         ALint status;
485
486         if ( !OAL_inited ) {
487                 return 0;
488         }
489
490         SDL_assert( channel >= 0 );
491         SDL_assert( channel < (int)Channels.size() );
492
493         oal_check_for_errors("oal_is_channel_playing() begin");
494
495         alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status);
496
497         oal_check_for_errors("oal_is_channel_playing() end");
498
499         if (status == AL_PLAYING) {
500                 return 1;
501         }
502
503         return 0;
504 }
505
506 void oal_chg_loop_status(int channel, int loop)
507 {
508         if ( !OAL_inited ) {
509                 return;
510         }
511
512         SDL_assert( channel >= 0 );
513         SDL_assert( channel < (int)Channels.size() );
514
515         oal_check_for_errors("oal_chg_loop_status() begin");
516
517         alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE);
518
519         if (loop) {
520                 Channels[channel].flags |= SND_FLAG_LOOPING;
521         } else {
522                 Channels[channel].flags &= ~SND_FLAG_LOOPING;
523         }
524
525         oal_check_for_errors("oal_chg_loop_status() end");
526 }
527
528 static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority)
529 {
530         int     i, limit;
531         float lowest_vol = 0.0f;
532         int lowest_vol_index = -1;
533         int status;
534         int instance_count = 0; // number of instances of sound already playing
535         float lowest_instance_vol = 1.0f;
536         int lowest_instance_vol_index = -1;
537
538         int first_free_channel = -1;
539
540         int size = (int)Channels.size();
541
542         oal_check_for_errors("oal_get_free_channel_idx() begin");
543
544         // Look for a channel to use to play this sample
545         for (i = 0; i < size; i++) {
546                 sound_channel *chp = &Channels[i];
547                 int looping = chp->flags & SND_FLAG_LOOPING;
548
549                 if (chp->snd_id == 0) {
550                         if (first_free_channel == -1) {
551                                 first_free_channel = i;
552                         }
553
554                         continue;
555                 }
556
557                 alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status);
558
559                 if (status != AL_PLAYING) {
560                         if (first_free_channel == -1) {
561                                 first_free_channel = i;
562                         }
563
564                         continue;
565                 } else {
566                         if (chp->snd_id == snd_id) {
567                                 instance_count++;
568
569                                 if ( (chp->vol < lowest_instance_vol) && !looping ) {
570                                         lowest_instance_vol = chp->vol;
571                                         lowest_instance_vol_index = i;
572                                 }
573                         }
574
575                         if ( (chp->vol < lowest_vol) && !looping ) {
576                                 lowest_vol_index = i;
577                                 lowest_vol = chp->vol;
578                         }
579                 }
580         }
581
582         // determine the limit of concurrent instances of this sound
583         switch (priority) {
584                 case SND_PRIORITY_MUST_PLAY:
585                         limit = 100;
586                         break;
587
588                 case SND_PRIORITY_SINGLE_INSTANCE:
589                         limit = 1;
590                         break;
591
592                 case SND_PRIORITY_DOUBLE_INSTANCE:
593                         limit = 2;
594                         break;
595
596                 case SND_PRIORITY_TRIPLE_INSTANCE:
597                         limit = 3;
598                         break;
599
600                 default:
601                         Int3();                 // get Alan
602                         limit = 100;
603                         break;
604         }
605
606
607         // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
608         if (instance_count >= limit) {
609                 // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
610                 if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) {
611                         first_free_channel = lowest_instance_vol_index;
612                 } else {
613                         first_free_channel = -1;
614                 }
615         } else {
616                 // there is no limit barrier to play the sound, so see if we've ran out of channels
617                 if (first_free_channel == -1) {
618                         // stop the lowest volume instance to play our sound if priority demands it
619                         if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) {
620                                 // Check if the lowest volume playing is less than the volume of the requested sound.
621                                 // If so, then we are going to trash the lowest volume sound.
622                                 if (Channels[lowest_vol_index].vol <= new_volume) {
623                                         first_free_channel = lowest_vol_index;
624                                 }
625                         }
626                 }
627         }
628
629         oal_check_for_errors("oal_get_free_channel_idx() end");
630
631         return first_free_channel;
632 }
633
634 // get a channel for use elsewhere (MVE playback, streaming audio, etc.)
635 sound_channel *oal_get_free_channel(float volume, int snd_id, int priority)
636 {
637         if ( !OAL_inited ) {
638                 return NULL;
639         }
640
641         int chan = oal_get_free_channel_idx(volume, snd_id, priority);
642
643         if (chan < 0) {
644                 return NULL;
645         }
646
647         SDL_assert( Channels[chan].source_id != 0 );
648
649         Channels[chan].buf_idx = -1;
650         Channels[chan].snd_id = -1;
651         Channels[chan].sig = channel_next_sig++;
652
653         if (channel_next_sig < 0) {
654                 channel_next_sig = 1;
655         }
656
657         return &Channels[chan];
658 }
659
660 int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header)
661 {
662         CFILE *cfp = NULL;
663         int id = 0;
664         unsigned int tag = 0, size = 0, next_chunk;
665         WAVE_chunk hdr;
666
667         if ( !OAL_inited ) {
668                 return 0;
669         }
670
671         cfp = cfopen(filename, "rb");
672
673         if (cfp == NULL) {
674                 nprintf(("Error", "Couldn't open '%s'\n", filename ));
675                 return -1;
676         }
677
678         // check for valid file type
679         id = cfread_int(cfp);
680
681         // 'RIFF'
682         if (id != 0x46464952) {
683                 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
684                 cfclose(cfp);
685                 return -1;
686         }
687
688         // skip RIFF size
689         cfread_int(cfp);
690
691         // check for valid RIFF type
692         id = cfread_int(cfp);
693
694         // 'WAVE'
695         if (id != 0x45564157) {
696                 nprintf(("Error", "Not a WAVE file '%s'\n", filename));
697                 cfclose(cfp);
698                 return -1;
699         }
700
701         // parse WAVE tags
702         while ( !cfeof(cfp) ) {
703                 tag = cfread_uint(cfp);
704                 size = cfread_uint(cfp);
705
706                 next_chunk = cftell(cfp) + size;
707
708                 switch (tag) {
709                         // 'fmt '
710                         case 0x20746d66: {
711                                 hdr.code = cfread_short(cfp);
712                                 hdr.num_channels = cfread_ushort(cfp);
713                                 hdr.sample_rate = cfread_uint(cfp);
714                                 hdr.bytes_per_second = cfread_uint(cfp);
715                                 hdr.block_align = cfread_ushort(cfp);
716                                 hdr.bits_per_sample = cfread_ushort(cfp);
717
718                                 if (hdr.code != 1) {
719                                         hdr.extra_size = cfread_ushort(cfp);
720                                 }
721
722                                 (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
723                                 SDL_assert( (*header) != NULL );
724
725                                 memcpy((*header), &hdr, sizeof(WAVE_chunk));
726
727                                 if (hdr.extra_size) {
728                                         (*header)->extra_data = (ubyte*) malloc (hdr.extra_size);
729                                         SDL_assert( (*header)->extra_data != NULL );
730
731                                         cfread((*header)->extra_data, hdr.extra_size, 1, cfp);
732                                 }
733
734                                 break;
735                         }
736
737                         // 'data'
738                         case 0x61746164: {
739                                 *dest_size = size;
740
741                                 (*dest) = (ubyte*) malloc (size);
742                                 SDL_assert( (*dest) != NULL );
743
744                                 cfread((*dest), size, 1, cfp);
745
746                                 break;
747                         }
748
749                         // drop everything else
750                         default:
751                                 break;
752                 }
753
754                 cfseek(cfp, next_chunk, CF_SEEK_SET);
755         }
756
757         cfclose(cfp);
758
759         return 0;
760 }
761
762 static int oal_get_free_buffer()
763 {
764         if ( !OAL_inited ) {
765                 return -1;
766         }
767
768         int size = (int)Buffers.size();
769
770         for (int i = 0; i < size; i++) {
771                 if (Buffers[i].buf_id == 0) {
772                         return i;
773                 }
774         }
775
776         sound_buffer nbuf;
777
778         Buffers.push_back(nbuf);
779
780         return (int)(Buffers.size()-1);
781 }
782
783 int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags)
784 {
785         SDL_assert( final_size != NULL );
786         SDL_assert( header != NULL );
787         SDL_assert( si != NULL );
788
789         if ( !OAL_inited ) {
790                 return 0;
791         }
792
793         int buf_idx = oal_get_free_buffer();
794
795         if (buf_idx < 0) {
796                 return -1;
797         }
798
799         *sid = buf_idx;
800
801         sound_buffer *buf = &Buffers[buf_idx];
802
803         oal_check_for_errors("oal_load_buffer() begin");
804
805         alGenBuffers(1, &buf->buf_id);
806
807         if ( !buf->buf_id ) {
808                 return -1;
809         }
810
811         ALenum format = AL_INVALID;
812         ALsizei size;
813         ALint bits, bps;
814         ALuint frequency;
815         ALvoid *data = NULL;
816
817         // the below conversion variables are only used when the wav format is not PCM.
818         ubyte *convert_buffer = NULL;           // storage for converted wav file
819         int convert_len;                                        // num bytes of converted wav file
820         uint src_bytes_used;                            // number of source bytes actually converted (should always be equal to original size)
821
822
823         switch (si->format) {
824                 case WAVE_FORMAT_PCM: {
825                         SDL_assert( si->data != NULL );
826
827                         bits = si->bits;
828                         bps  = si->avg_bytes_per_sec;
829                         size = si->size;
830
831 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
832                         // swap 16-bit sound data
833                         if (bits == 16) {
834                                 ushort *swap_tmp;
835
836                                 for (uint i=0; i<size; i=i+2) {
837                                         swap_tmp = (ushort*)(si->data + i);
838                                         *swap_tmp = INTEL_SHORT(*swap_tmp);
839                                 }
840                         }
841 #endif
842
843                         data = si->data;
844
845                         break;
846                 }
847
848                 case WAVE_FORMAT_ADPCM: {
849                         SDL_assert( si->data != NULL );
850
851                         // this ADPCM decoder decodes to 16-bit only so keep that in mind
852                         nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" ));
853
854                         int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16);
855
856                         // ACM conversion failed?
857                         if ( (rc == -1) || (src_bytes_used != si->size) ) {
858                                 alDeleteBuffers(1, &buf->buf_id);
859                                 buf->buf_id = 0;
860
861                                 if (convert_buffer != NULL) {
862                                         free(convert_buffer);
863                                 }
864
865                                 return -1;
866                         }
867
868                         bits = 16;
869                         bps  = (((si->n_channels * bits) / 8) * si->sample_rate);
870                         size = convert_len;
871                         data = convert_buffer;
872
873                         nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
874
875                         break;
876                 }
877
878                 default:
879                         nprintf(( "Sound", "Unsupported sound encoding\n" ));
880                         alDeleteBuffers(1, &buf->buf_id);
881                         buf->buf_id = 0;
882                         return -1;
883         }
884
885         // format is now in pcm
886         frequency = si->sample_rate;
887
888         if (bits == 16) {
889                 if (si->n_channels == 2) {
890                         format = AL_FORMAT_STEREO16;
891                 } else if (si->n_channels == 1) {
892                         format = AL_FORMAT_MONO16;
893                 }
894         } else if (bits == 8) {
895                 if (si->n_channels == 2) {
896                         format = AL_FORMAT_STEREO8;
897                 } else if (si->n_channels == 1) {
898                         format = AL_FORMAT_MONO8;
899                 }
900         }
901
902         if (format == AL_INVALID) {
903                 alDeleteBuffers(1, &buf->buf_id);
904                 buf->buf_id = 0;
905
906                 if (convert_buffer != NULL) {
907                         free(convert_buffer);
908                 }
909
910                 return -1;
911         }
912
913         Snd_sram += size;
914         *final_size = size;
915
916         alBufferData(buf->buf_id, format, data, size, frequency);
917
918         buf->chan_idx = -1;
919         buf->frequency = frequency;
920         buf->bits_per_sample = bits;
921         buf->nchannels = si->n_channels;
922         buf->nseconds = size / bps;
923         buf->nbytes = size;
924
925         if (convert_buffer != NULL) {
926                 free(convert_buffer);
927         }
928
929         oal_check_for_errors("oal_load_buffer() end");
930
931         return 0;
932 }
933
934 void oal_unload_buffer(int sid)
935 {
936         if ( !OAL_inited ) {
937                 return;
938         }
939
940         if ( (sid < 0) || (sid >= (int)Buffers.size()) ) {
941                 return;
942         }
943
944         oal_check_for_errors("oal_unload_buffer() begin");
945
946         sound_buffer *buf = &Buffers[sid];
947
948         if (buf->buf_id) {
949                 alDeleteBuffers(1, &buf->buf_id);
950                 buf->buf_id = 0;
951         }
952
953         oal_check_for_errors("oal_unload_buffer() end");
954 }
955
956 int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
957 {
958         if ( !OAL_inited ) {
959                 return -1;
960         }
961
962         int buf_idx = oal_get_free_buffer();
963
964         if (buf_idx < 0) {
965                 return -1;
966         }
967
968         sound_buffer *buf = &Buffers[buf_idx];
969
970         oal_check_for_errors("oal_load_buffer() begin");
971
972         alGenBuffers(1, &buf->buf_id);
973
974         if ( !buf->buf_id ) {
975                 return -1;
976         }
977
978         buf->chan_idx = -1;
979         buf->frequency = frequency;
980         buf->bits_per_sample = bits_per_sample;
981         buf->nchannels = nchannels;
982         buf->nseconds = nseconds;
983         buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
984
985         return buf_idx;
986 }
987
988 int oal_lock_data(int sid, ubyte *data, int size)
989 {
990         if ( !OAL_inited ) {
991                 return -1;
992         }
993
994         oal_check_for_errors("oal_lock_data() begin");
995
996         SDL_assert( sid >= 0 );
997         SDL_assert( sid < (int)Buffers.size() );
998
999         ALuint buf_id = Buffers[sid].buf_id;
1000         ALenum format;
1001
1002         if (Buffers[sid].bits_per_sample == 16) {
1003                 if (Buffers[sid].nchannels == 2) {
1004                         format = AL_FORMAT_STEREO16;
1005                 } else if (Buffers[sid].nchannels == 1) {
1006                         format = AL_FORMAT_MONO16;
1007                 } else {
1008                         return -1;
1009                 }
1010         } else if (Buffers[sid].bits_per_sample == 8) {
1011                 if (Buffers[sid].nchannels == 2) {
1012                         format = AL_FORMAT_STEREO8;
1013                 } else if (Buffers[sid].nchannels == 1) {
1014                         format = AL_FORMAT_MONO8;
1015                 } else {
1016                         return -1;
1017                 }
1018         } else {
1019                 return -1;
1020         }
1021
1022         Buffers[sid].nbytes = size;
1023
1024         alBufferData(buf_id, format, data, size, Buffers[sid].frequency);
1025
1026         if ( oal_check_for_errors("oal_lock_data() end") ) {
1027                 return -1;
1028         }
1029
1030         return 0;
1031 }
1032
1033 int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags)
1034 {
1035         if ( !OAL_inited ) {
1036                 return -1;
1037         }
1038
1039         SDL_assert( sid >= 0 );
1040         SDL_assert( sid < (int)Buffers.size() );
1041
1042         oal_check_for_errors("oal_play() begin");
1043
1044         int channel = oal_get_free_channel_idx(volume, snd_id, priority);
1045
1046         if (channel < 0) {
1047                 return -1;
1048         }
1049
1050         sound_channel *chan = &Channels[channel];
1051
1052         ALint status;
1053         alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1054
1055         if (status == AL_PLAYING) {
1056                 oal_stop_channel(channel);
1057         }
1058
1059         // set all the things
1060         chan->vol = volume;
1061         chan->flags = flags;
1062         chan->priority = priority;
1063         chan->last_position = 0;
1064         chan->buf_idx = sid;
1065         chan->snd_id = snd_id;
1066         chan->sig = channel_next_sig++;
1067
1068         Buffers[sid].chan_idx = channel;
1069
1070         alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f);
1071         alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1072         alSourcef(chan->source_id, AL_PITCH, 1.0f);
1073         alSourcef(chan->source_id, AL_GAIN, volume);
1074         alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1075         alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1076         alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE);
1077
1078         // Actually play it
1079         alSourcePlay(chan->source_id);
1080
1081         if (channel_next_sig < 0) {
1082                 channel_next_sig = 1;
1083         }
1084
1085         oal_check_for_errors("oal_play() end");
1086
1087         return chan->sig;
1088 }
1089
1090 int oal_play_3d( int sid, int snd_id, vector *pos, vector *vel, int min, int max, int looping, float max_volume, float estimated_vol, int priority)
1091 {
1092         if ( !OAL_inited ) {
1093                 return -1;
1094         }
1095
1096         SDL_assert( sid >= 0 );
1097         SDL_assert( sid < (int)Buffers.size() );
1098
1099         oal_check_for_errors("oal_play_3d() begin");
1100
1101         int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority);
1102
1103         if (channel < 0) {
1104                 return -1;
1105         }
1106
1107         sound_channel *chan = &Channels[channel];
1108
1109         ALint status;
1110         alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status);
1111
1112         if (status == AL_PLAYING) {
1113                 oal_stop_channel(channel);
1114         }
1115
1116         int flags = SND_FLAG_3D;
1117
1118         if (looping) {
1119                 flags |= SND_FLAG_LOOPING;
1120         }
1121
1122         // set all the things
1123         chan->vol = max_volume;
1124         chan->flags = flags;
1125         chan->priority = priority;
1126         chan->last_position = 0;
1127         chan->buf_idx = sid;
1128         chan->snd_id = snd_id;
1129         chan->sig = channel_next_sig++;
1130
1131         Buffers[sid].chan_idx = channel;
1132
1133         oal_update_source(channel, min, max, pos, vel);
1134
1135         alSourcef(chan->source_id, AL_PITCH, 1.0f);
1136         alSourcef(chan->source_id, AL_GAIN, max_volume);
1137         alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id);
1138         alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE);
1139         alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE);
1140
1141         // Actually play it
1142         alSourcePlay(chan->source_id);
1143
1144         if (channel_next_sig < 0) {
1145                 channel_next_sig = 1;
1146         }
1147
1148         oal_check_for_errors("oal_play_3d() end");
1149
1150         return chan->sig;
1151 }
1152
1153 void oal_do_frame()
1154 {
1155         ALint state, current_position;
1156
1157         oal_check_for_errors("oal_do_frame() begin");
1158
1159         int size = (int)Channels.size();
1160
1161         // make sure there aren't any looping voice messages
1162         for (int i = 0; i < size; i++) {
1163
1164                 if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) {
1165                         alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state);
1166
1167                         if (state != AL_PLAYING) {
1168                                 continue;
1169                         }
1170
1171                         alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, &current_position);
1172
1173                         if (current_position != 0) {
1174                                 if (current_position < Channels[i].last_position) {
1175                                         alSourceStop(Channels[i].source_id);
1176                                 } else {
1177                                         Channels[i].last_position = current_position;
1178                                 }
1179                         }
1180                 }
1181         }
1182
1183         oal_check_for_errors("oal_do_frame() end");
1184 }
1185
1186 int oal_update_source(int channel, int min, int max, vector *pos, vector *vel)
1187 {
1188         if ( !OAL_inited ) {
1189                 return 0;
1190         }
1191
1192         if (channel < 0) {
1193                 return 0;
1194         }
1195
1196         if ( !Channels[channel].flags & SND_FLAG_3D ) {
1197                 return 1;
1198         }
1199
1200         ALuint source_id = Channels[channel].source_id;
1201         ALfloat rolloff = 1.0f;
1202
1203         oal_check_for_errors("oal_update_source() begin");
1204
1205         if (pos) {
1206                 alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1207         }
1208
1209         if (vel) {
1210                 alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1211         } else {
1212                 alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1213         }
1214
1215         if (min >= 0) {
1216                 if (max <= min) {
1217                         rolloff = 0.0f;
1218                 } else {
1219                         const float MIN_GAIN = 0.05f;
1220                         float minf = i2fl(min);
1221                         float maxf = i2fl(max);
1222
1223                         // yep, just making this shit up
1224                         rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN;
1225
1226                         if (rolloff < 0.0f) {
1227                                 rolloff = 0.0f;
1228                         }
1229                 }
1230
1231                 alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff);
1232
1233                 alSourcei(source_id, AL_REFERENCE_DISTANCE, min);
1234                 alSourcei(source_id, AL_MAX_DISTANCE, max);
1235         }
1236
1237         oal_check_for_errors("oal_update_source() end");
1238
1239         return 0;
1240 }
1241
1242 int oal_update_listener(vector *pos, vector *vel, matrix *orient)
1243 {
1244         if ( !OAL_inited ) {
1245                 return 0;
1246         }
1247
1248         oal_check_for_errors("oal_update_listener() begin");
1249
1250         if (pos) {
1251                 alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z);
1252         }
1253
1254         if (vel) {
1255                 alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z);
1256         }
1257
1258         if (orient) {
1259                 ALfloat alOrient[6];
1260
1261                 alOrient[0] =  orient->v.fvec.xyz.x;
1262                 alOrient[1] =  orient->v.fvec.xyz.y;
1263                 alOrient[2] = -orient->v.fvec.xyz.z;
1264
1265                 alOrient[3] =  orient->v.uvec.xyz.x;
1266                 alOrient[4] =  orient->v.uvec.xyz.y;
1267                 alOrient[5] = -orient->v.uvec.xyz.z;
1268
1269                 alListenerfv(AL_ORIENTATION, alOrient);
1270         }
1271
1272         oal_check_for_errors("oal_update_listener() end");
1273
1274         return 0;
1275 }