1 
2 #include <SDL2/SDL.h>
3 #include <SDL2/SDL_audio.h>
4 
5 #include <math.h>
6 
7 #include "../config-opentomb.h"
8 
9 extern "C" {
10 #include <al.h>
11 #include <alc.h>
12 #ifdef HAVE_ALEXT_H
13 #include <alext.h>
14 #endif
15 }
16 
17 #include "../core/system.h"
18 #include "../core/vmath.h"
19 #include "../core/gl_text.h"
20 #include "../core/console.h"
21 #include "../script/script.h"
22 #include "../render/camera.h"
23 #include "../vt/vt_level.h"
24 #include "../entity.h"
25 #include "../room.h"
26 #include "../world.h"
27 #include "../engine.h"
28 #include "../game.h"
29 
30 #include "audio.h"
31 #include "audio_stream.h"
32 #include "audio_fx.h"
33 
34 #define STB_VORBIS_HEADER_ONLY
35 #include "stb_vorbis.c"
36 
37 static ALCdevice              *al_device      = NULL;
38 static ALCcontext             *al_context     = NULL;
39 
40 // Effect structure.
41 // Contains all global effect parameters.
42 typedef struct audio_effect_s
43 {
44     // General sound source parameters (similar to TR sound info).
45 
46     ALfloat     pitch;          // [PIT in TR] Global pitch shift.
47     ALfloat     gain;           // [VOL in TR] Global gain (volume).
48     ALfloat     range;          // [RAD in TR] Range (radius).
49     ALuint      chance;         // [CH  in TR] Chance to play.
50     ALuint      loop;           // 0 = none, 1 = W, 2 = R, 3 = L.
51     ALboolean   rand_pitch;     // Similar to flag 0x200000 (P) in native TRs.
52     ALboolean   rand_gain;      // Similar to flag 0x400000 (V) in native TRs.
53 
54     // Additional sound source parameters.
55     // These are not natively in TR engines, but can be later assigned by
56     // external script.
57 
58     ALboolean   rand_freq;          // Slightly randomize frequency.
59     ALuint      rand_pitch_var;     // Pitch randomizer bounds.
60     ALuint      rand_gain_var;      // Gain  randomizer bounds.
61     ALuint      rand_freq_var;      // Frequency randomizer bounds.
62 
63     // Sample reference parameters.
64 
65     ALuint      sample_index;       // First (or only) sample (buffer) index.
66     ALuint      sample_count;       // Sample amount to randomly select from.
67 }audio_effect_t, *audio_effect_p;
68 
69 // Audio emitter (aka SoundSource) structure.
70 
71 typedef struct audio_emitter_s
72 {
73     ALuint      emitter_index;  // Unique emitter index.
74     ALuint      sound_index;    // Sound index.
75     float       position[3];    // Vector coordinate.
76     uint16_t    flags;          // Flags - MEANING UNKNOWN!!!
77 }audio_emitter_t, *audio_emitter_p;
78 
79 // Main audio source class.
80 
81 // Sound source is a complex class, each member of which is linked with
82 // certain in-game entity or sound source, but also a kind of entity by itself.
83 // Number of simultaneously existing sound sources is fixed, and can't be more than
84 // MAX_CHANNELS global constant.
85 
86 class AudioSource
87 {
88 public:
89     AudioSource();  // Audio source constructor.
90    ~AudioSource();  // Audio source destructor.
91 
92     void Play();    // Make source active and play it.
93     void Pause();   // Pause source (leaving it active).
94     void Stop();    // Stop and destroy source.
95     void Update();  // Update source parameters.
96 
97     void SetBuffer(ALint buffer);           // Assign buffer to source.
98     void SetLooping(ALboolean is_looping);  // Set looping flag.
99     void SetPitch(ALfloat pitch_value);     // Set pitch shift.
100     void SetGain(ALfloat gain_value);       // Set gain (volume).
101     void SetRange(ALfloat range_value);     // Set max. audible distance.
102 
103     bool IsActive();            // Check if source is active.
104 
105     int32_t     emitter_ID;     // Entity of origin. -1 means no entity (hence - empty source).
106     uint32_t    emitter_type;   // 0 - ordinary entity, 1 - sound source, 2 - global sound.
107     uint32_t    effect_index;   // Effect index. Used to associate effect with entity for R/W flags.
108     uint32_t    sample_index;   // OpenAL sample (buffer) index. May be the same for different sources.
109     uint32_t    sample_count;   // How many buffers to use, beginning with sample_index.
110 
111     friend int Audio_IsEffectPlaying(int effect_ID, int entity_type, int entity_ID);
112 
113 private:
114     bool        active;         // Source gets autostopped and destroyed on next frame, if it's not set.
115     bool        is_water;       // Marker to define if sample is in underwater state or not.
116     ALuint      source_index;   // Source index. Should be unique for each source.
117 
118     void LinkEmitter();                             // Link source to parent emitter.
119     void SetPosition(const ALfloat pos_vector[]);   // Set source position.
120     void SetVelocity(const ALfloat vel_vector[]);   // Set source velocity (speed).
121 };
122 
123 
124 class StreamTrackBuffer
125 {
126 public:
127     StreamTrackBuffer();
128    ~StreamTrackBuffer();
129 
130     bool Load(int track_index);
131 
132 private:
133     bool Load_Ogg(const char *path);                        // Ogg file loading routine.
134     bool Load_Wad(const char *path, uint32_t track);        // Wad file loading routine.
135     bool Load_Wav(const char *path);                        // Wav file loading routine.
136     bool Load_WavRW(SDL_RWops *file);                       // Wav file loading routine.
137 
138 public:
139     int             track_index;
140     uint32_t        buffer_size;
141     uint32_t        buffer_part;
142     uint8_t        *buffer;
143     int             stream_type;         // Either BACKGROUND, ONESHOT or CHAT.
144     int             channels;
145     int             sample_bitsize;
146     int             rate;
147 };
148 
149 
150 // ======== PRIVATE PROTOTYPES =============
151 int  Audio_LogALError(int error_marker = 0);    // AL-specific error handler.
152 void Audio_LogOGGError(int code);               // Ogg-specific error handler.
153 
154 bool Audio_FillALBuffer(ALuint buf_number, Uint8* buffer_data, Uint32 buffer_size, int sample_bitsize, int channels, int frequency);
155 int  Audio_LoadALbufferFromWAV_Mem(ALuint buf_number, uint8_t *sample_pointer, uint32_t sample_size, uint32_t uncomp_sample_size = 0);
156 int  Audio_LoadALbufferFromWAV_File(ALuint buf_number, const char *fname);
157 void Audio_LoadOverridedSamples();
158 
159 int  Audio_GetFreeSource();
160 int  Audio_GetFreeStream();                         // Get free (stopped) stream.
161 int  Audio_TrackAlreadyPlayed(uint32_t track_index, int8_t mask = 0);     // Check if track played with given activation mask.
162 void Audio_UpdateStreams(float time);               // Update all streams.
163 int  Audio_IsInRange(int entity_type, int entity_ID, float range, float gain);
164 
165 void Audio_PauseAllSources();    // Used to pause all effects currently playing.
166 void Audio_StopAllSources();     // Used in audio deinit.
167 void Audio_ResumeAllSources();   // Used to resume all effects currently paused.
168 void Audio_UpdateSources();      // Main sound loop.
169 void Audio_UpdateListenerByCamera(struct camera_s *cam, float time);
170 void Audio_UpdateListenerByEntity(struct entity_s *ent);
171 int  Audio_IsTrackPlaying(uint32_t track_index);
172 
173 // ==== STREAMTRACK BUFFER CLASS IMPLEMENTATION =====
StreamTrackBuffer()174 StreamTrackBuffer::StreamTrackBuffer() :
175     track_index(-1),
176     buffer_size(0),
177     buffer(NULL),
178     stream_type(TR_AUDIO_STREAM_TYPE_ONESHOT),
179     channels(0),
180     sample_bitsize(0),
181     rate(0)
182 {
183 }
184 
185 
~StreamTrackBuffer()186 StreamTrackBuffer::~StreamTrackBuffer()
187 {
188     if(buffer)
189     {
190         buffer_size = 0;
191         free(buffer);
192         buffer = NULL;
193     }
194 }
195 
196 
Load(int track_index)197 bool StreamTrackBuffer::Load(int track_index)
198 {
199     if(this->track_index < 0)
200     {
201         this->track_index = track_index;
202         char file_path[1024];
203         int load_method = 0;
204 
205         if(!Script_GetSoundtrack(engine_lua, track_index, file_path, sizeof(file_path), &load_method, &stream_type))
206         {
207             return false;
208         }
209 
210         switch(load_method)
211         {
212             case TR_AUDIO_STREAM_METHOD_OGG:
213                 return Load_Ogg(file_path);
214 
215             case TR_AUDIO_STREAM_METHOD_WAD:
216                 return Load_Wad(file_path, track_index);
217 
218             case TR_AUDIO_STREAM_METHOD_WAV:
219                 return Load_Wav(file_path);
220 
221             default:
222                 return false;
223         }
224     }
225 
226     return (this->buffer != NULL);
227 }
228 
229 ///@TODO: fix vorbis streaming! ov_bitrate may differ in differ section
Load_Ogg(const char * path)230 bool StreamTrackBuffer::Load_Ogg(const char *path)
231 {
232     int err = 0;
233     stb_vorbis_alloc alloc;
234     alloc.alloc_buffer_length_in_bytes = 256 * 1024;
235     alloc.alloc_buffer = (char*)Sys_GetTempMem(alloc.alloc_buffer_length_in_bytes);
236     stb_vorbis *ov = stb_vorbis_open_filename(path, &err, &alloc);
237 
238     if(!ov)
239     {
240         Sys_DebugLog(SYS_LOG_FILENAME, "OGG: Couldn't open file: %s.", path);
241         Sys_ReturnTempMem(alloc.alloc_buffer_length_in_bytes);
242         return false;
243     }
244 
245     stb_vorbis_info info = stb_vorbis_get_info(ov);
246     channels = info.channels;
247     sample_bitsize = 16;
248     buffer_part = 96 * info.max_frame_size;
249     rate = info.sample_rate;
250 
251     {
252         const size_t temp_buf_size = 64 * 1024 * 1024;
253         size_t buffer_left = temp_buf_size / 2;
254         short *temp_buff = (short*)malloc(temp_buf_size);
255         size_t readed = 0;
256         buffer_size = 0;
257         while(0 != (readed = stb_vorbis_get_frame_short_interleaved(ov, channels, temp_buff + buffer_size, buffer_left)))
258         {
259             buffer_size += readed * channels;
260             buffer_left -= readed * channels;
261         }
262         buffer_size *= 2;
263         stb_vorbis_close(ov);
264         Sys_ReturnTempMem(alloc.alloc_buffer_length_in_bytes);
265 
266         if(buffer_size > 0)
267         {
268             buffer = (uint8_t*)malloc(buffer_size);
269             memcpy(buffer, temp_buff, buffer_size);
270             Con_Notify("file \"%s\" loaded with rate=%d, bitrate=%.1f", path, rate, ((float)info.sample_rate / 1000.0f));
271         }
272         free(temp_buff);
273     }
274 
275     return buffer_size > 0;
276 }
277 
278 
Load_Wad(const char * path,uint32_t track)279 bool StreamTrackBuffer::Load_Wad(const char *path, uint32_t track)
280 {
281     const int TR_AUDIO_STREAM_WAD_STRIDE = 268;
282     const int TR_AUDIO_STREAM_WAD_NAMELENGTH = 260;
283     const int TR_AUDIO_STREAM_WAD_COUNT = 130;
284     char track_name[TR_AUDIO_STREAM_WAD_NAMELENGTH];
285     SDL_RWops *file = NULL;
286     uint32_t offset = 0;
287     uint32_t length = 0;
288 
289     if(track > TR_AUDIO_STREAM_WAD_COUNT)
290     {
291         return false;
292     }
293 
294     file = SDL_RWFromFile(path, "rb");
295     if(file == NULL)
296     {
297         return false;
298     }
299 
300     if(SDL_RWseek(file, (track * TR_AUDIO_STREAM_WAD_STRIDE), RW_SEEK_SET) < 0)
301     {
302         SDL_RWclose(file);
303         return false;
304     }
305 
306     if(TR_AUDIO_STREAM_WAD_NAMELENGTH != SDL_RWread(file, track_name, 1, TR_AUDIO_STREAM_WAD_NAMELENGTH))
307     {
308         SDL_RWclose(file);
309         return false;
310     }
311 
312     if(1 != SDL_RWread(file, &length, sizeof(uint32_t), 1))
313     {
314         SDL_RWclose(file);
315         return false;
316     }
317 
318     if(1 != SDL_RWread(file, &offset, sizeof(uint32_t), 1))
319     {
320         SDL_RWclose(file);
321         return false;
322     }
323 
324     if(SDL_RWseek(file, offset, RW_SEEK_SET) < 0)
325     {
326         SDL_RWclose(file);
327         return false;
328     }
329 
330     return Load_WavRW(file);
331 }
332 
333 
Load_Wav(const char * path)334 bool StreamTrackBuffer::Load_Wav(const char *path)
335 {
336     return Load_WavRW(SDL_RWFromFile(path, "rb"));
337 }
338 
339 
Load_WavRW(SDL_RWops * file)340 bool StreamTrackBuffer::Load_WavRW(SDL_RWops *file)
341 {
342     SDL_AudioSpec wav_spec;
343     uint8_t      *wav_buffer;
344     uint32_t      wav_length;
345     if(SDL_LoadWAV_RW(file, 1, &wav_spec, &wav_buffer, &wav_length) == NULL)
346     {
347         Sys_DebugLog(SYS_LOG_FILENAME, "Error: can't load track");
348         return false;
349     }
350 
351     // Extract bitsize from SDL audio spec for further usage.
352     sample_bitsize = (uint8_t)(wav_spec.format & SDL_AUDIO_MASK_BITSIZE);
353     channels = wav_spec.channels;
354 
355     if(wav_spec.channels > 2)   // We can't use non-mono and barely can use stereo samples.
356     {
357         Sys_DebugLog(SYS_LOG_FILENAME, "Error: track has more than 2 channels!");
358         return false;
359     }
360 
361     // Check if bitsize is supported.
362     // We rarely encounter samples with exotic bitsizes, but just in case...
363     if((sample_bitsize != 32) && (sample_bitsize != 16) && (sample_bitsize != 8))
364     {
365         Sys_DebugLog(SYS_LOG_FILENAME, "Can't load sample - wrong bitsize (%d)", sample_bitsize);
366         return false;
367     }
368 
369     if(false)//use_SDL_resampler
370     {
371         int FrameSize = channels * 4; // sizeof(float);
372         SDL_AudioCVT cvt;
373         SDL_BuildAudioCVT(&cvt, wav_spec.format, wav_spec.channels, wav_spec.freq, AUDIO_F32, wav_spec.channels, 44100);
374 
375         cvt.len = wav_length;
376         buffer_size = wav_length * cvt.len_mult;
377         if(buffer_size % FrameSize)
378         {
379             buffer_size += FrameSize - (buffer_size % FrameSize);   // make align
380         }
381 
382         buffer = (uint8_t*)calloc(buffer_size, 1);
383         cvt.buf = buffer;
384         memcpy(cvt.buf, wav_buffer, cvt.len);
385 
386         if(cvt.needed)
387         {
388             SDL_ConvertAudio(&cvt);
389         }
390 
391         rate = 44100;
392     }
393     else    // Standard OpenAL sample loading process.
394     {
395         buffer_size = wav_length;
396         buffer = (uint8_t*)malloc(buffer_size);
397         buffer_part = 128 * 1024;
398         rate = wav_spec.freq;
399         memcpy(buffer, wav_buffer, buffer_size);
400     }
401 
402     SDL_FreeWAV(wav_buffer);
403     return true;
404 }
405 
406 // ========== GLOBALS ==============
407 ALfloat                     listener_position[3];
408 struct audio_settings_s     audio_settings = {0};
409 
410 
411 struct audio_world_data_s
412 {
413     uint32_t                        audio_emitters_count;   // Amount of audio emitters in level.
414     struct audio_emitter_s         *audio_emitters;         // Audio emitters.
415 
416     uint32_t                        audio_map_count;        // Amount of overall effects in engine.
417     int16_t                        *audio_map;              // Effect indexes.
418     uint32_t                        audio_effects_count;    // Amount of available effects in level.
419     struct audio_effect_s          *audio_effects;          // Effects and their parameters.
420 
421     uint32_t                        audio_buffers_count;    // Amount of samples.
422     ALuint                         *audio_buffers;          // Samples.
423     uint32_t                        audio_sources_count;    // Amount of runtime channels.
424     AudioSource                    *audio_sources;          // Channels.
425 
426     bool                            damp_active;            // Global flag for damping BGM tracks.
427     uint32_t                        stream_tracks_count;    // Amount of stream track channels.
428     struct stream_track_s          *stream_tracks;          // Stream tracks.
429 
430     uint32_t                        stream_buffers_count;    // Amount of stream track source buffers.
431     StreamTrackBuffer             **stream_buffers;
432 
433     uint32_t                        stream_track_map_count; // Stream track flag map count.
434     uint8_t                        *stream_track_map;       // Stream track flag map.
435 
436     struct stream_track_s           external_stream;
437 } audio_world_data;
438 
439 
440 // ======== AUDIOSOURCE CLASS IMPLEMENTATION ========
AudioSource()441 AudioSource::AudioSource()
442 {
443     active = false;
444     emitter_ID =  -1;
445     emitter_type = TR_AUDIO_EMITTER_ENTITY;
446     effect_index = 0;
447     sample_index = 0;
448     sample_count = 0;
449     is_water     = false;
450     alGenSources(1, &source_index);
451 
452     if(alIsSource(source_index))
453     {
454         alSourcef(source_index, AL_MIN_GAIN, 0.0);
455         alSourcef(source_index, AL_MAX_GAIN, 1.0);
456 
457 #ifdef HAVE_ALEXT_H
458         if(audio_settings.use_effects)
459         {
460             alSourcef(source_index, AL_ROOM_ROLLOFF_FACTOR, 1.0);
461             alSourcei(source_index, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,   AL_TRUE);
462             alSourcei(source_index, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO, AL_TRUE);
463             alSourcef(source_index, AL_AIR_ABSORPTION_FACTOR, 0.1);
464         }
465         else
466         {
467             alSourcef(source_index, AL_AIR_ABSORPTION_FACTOR, 0.0);
468         }
469 #endif
470     }
471 }
472 
473 
~AudioSource()474 AudioSource::~AudioSource()
475 {
476     if(alIsSource(source_index))
477     {
478         alSourceStop(source_index);
479         alDeleteSources(1, &source_index);
480     }
481 }
482 
483 
IsActive()484 bool AudioSource::IsActive()
485 {
486     return active;
487 }
488 
489 
Play()490 void AudioSource::Play()
491 {
492     if(alIsSource(source_index))
493     {
494         if(emitter_type == TR_AUDIO_EMITTER_GLOBAL)
495         {
496             alSourcei(source_index, AL_SOURCE_RELATIVE, AL_TRUE);
497             alSource3f(source_index, AL_POSITION, 0.0f, 0.0f, 0.0f);
498             alSource3f(source_index, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
499 
500             if(audio_settings.use_effects)
501             {
502                 Audio_UnsetFX(source_index);
503             }
504         }
505         else
506         {
507             alSourcei(source_index, AL_SOURCE_RELATIVE, AL_FALSE);
508             LinkEmitter();
509 
510             if(audio_settings.use_effects)
511             {
512                 Audio_SetFX(source_index);
513                 Audio_SetFXWaterStateForSource(source_index);
514             }
515         }
516 
517         alSourcePlay(source_index);
518         active = true;
519     }
520 }
521 
522 
Pause()523 void AudioSource::Pause()
524 {
525     if(alIsSource(source_index))
526     {
527         alSourcePause(source_index);
528     }
529 }
530 
531 
Stop()532 void AudioSource::Stop()
533 {
534     if(alIsSource(source_index))
535     {
536         alSourceStop(source_index);
537         active = false;
538     }
539 }
540 
541 
Update()542 void AudioSource::Update()
543 {
544     ALint   state;
545     ALfloat range, gain;
546 
547     alGetSourcei(source_index, AL_SOURCE_STATE, &state);
548 
549     // Disable and bypass source, if it is stopped.
550     if(state == AL_STOPPED)
551     {
552         active = false;
553         return;
554     }
555 
556     // Stop source, if it is disabled, but still playing.
557     if(!active && (state == AL_PLAYING))
558     {
559         Stop();
560         return;
561     }
562 
563     // Bypass source, if it is paused or global.
564     if( (state == AL_PAUSED) || (emitter_type == TR_AUDIO_EMITTER_GLOBAL) )
565     {
566         return;
567     }
568 
569     alGetSourcef(source_index, AL_GAIN, &gain);
570     alGetSourcef(source_index, AL_MAX_DISTANCE, &range);
571 
572     // Check if source is in listener's range, and if so, update position,
573     // else stop and disable it.
574     if(Audio_IsInRange(emitter_type, emitter_ID, range, gain))
575     {
576         LinkEmitter();
577 
578         if((audio_settings.use_effects) && (is_water != Audio_GetFXWaterState()))
579         {
580             Audio_SetFXWaterStateForSource(source_index);
581             is_water = !is_water;
582         }
583     }
584     else
585     {
586         Stop();
587     }
588 }
589 
590 
SetBuffer(ALint buffer)591 void AudioSource::SetBuffer(ALint buffer)
592 {
593     ALint buffer_index = audio_world_data.audio_buffers[buffer];
594 
595     if(alIsSource(source_index) && alIsBuffer(buffer_index))
596     {
597         alSourcei(source_index, AL_BUFFER, buffer_index);
598 
599         // For some reason, OpenAL sometimes produces "Invalid Operation" error here,
600         // so there's extra debug info - maybe it'll help some day.
601 
602         /*
603         if(Audio_LogALError(1))
604         {
605             int channels, bits, freq;
606 
607             alGetBufferi(buffer_index, AL_CHANNELS,  &channels);
608             alGetBufferi(buffer_index, AL_BITS,      &bits);
609             alGetBufferi(buffer_index, AL_FREQUENCY, &freq);
610 
611             Sys_DebugLog(SYS_LOG_FILENAME, "Erroneous buffer %d info: CH%d, B%d, F%d", buffer_index, channels, bits, freq);
612         }
613         */
614     }
615 }
616 
617 
SetLooping(ALboolean is_looping)618 void AudioSource::SetLooping(ALboolean is_looping)
619 {
620     alSourcei(source_index, AL_LOOPING, is_looping);
621 }
622 
623 
SetGain(ALfloat gain_value)624 void AudioSource::SetGain(ALfloat gain_value)
625 {
626     // Clamp gain value.
627     gain_value = (gain_value > 1.0) ? (1.0) : (gain_value);
628     gain_value = (gain_value < 0.0) ? (0.0) : (gain_value);
629 
630     alSourcef(source_index, AL_GAIN, gain_value * audio_settings.sound_volume);
631 }
632 
633 
SetPitch(ALfloat pitch_value)634 void AudioSource::SetPitch(ALfloat pitch_value)
635 {
636     // Clamp pitch value, as OpenAL tends to hang with incorrect ones.
637     pitch_value = (pitch_value < 0.1) ? (0.1) : (pitch_value);
638     pitch_value = (pitch_value > 2.0) ? (2.0) : (pitch_value);
639 
640     alSourcef(source_index, AL_PITCH, pitch_value);
641 }
642 
643 
SetRange(ALfloat range_value)644 void AudioSource::SetRange(ALfloat range_value)
645 {
646     // Source will become fully audible on 1/6 of overall position.
647     alSourcef(source_index, AL_REFERENCE_DISTANCE, range_value / 6.0);
648     alSourcef(source_index, AL_MAX_DISTANCE, range_value);
649 }
650 
651 
SetPosition(const ALfloat pos_vector[])652 void AudioSource::SetPosition(const ALfloat pos_vector[])
653 {
654     alSourcefv(source_index, AL_POSITION, pos_vector);
655 }
656 
657 
SetVelocity(const ALfloat vel_vector[])658 void AudioSource::SetVelocity(const ALfloat vel_vector[])
659 {
660     alSourcefv(source_index, AL_VELOCITY, vel_vector);
661 }
662 
663 
LinkEmitter()664 void AudioSource::LinkEmitter()
665 {
666     entity_p ent;
667 
668     switch(emitter_type)
669     {
670         case TR_AUDIO_EMITTER_ENTITY:
671             ent = World_GetEntityByID(emitter_ID);
672             if(ent)
673             {
674                 ALfloat  vec[3];
675                 vec3_copy(vec, ent->transform.M4x4 + 12);
676                 SetPosition(vec);
677                 vec3_copy(vec, ent->speed);
678                 SetVelocity(vec);
679             }
680             return;
681 
682         case TR_AUDIO_EMITTER_SOUNDSOURCE:
683             SetPosition(audio_world_data.audio_emitters[emitter_ID].position);
684             return;
685     }
686 }
687 
688 
Audio_CoreInit()689 void Audio_CoreInit()
690 {
691     ALCint paramList[] = {
692         ALC_STEREO_SOURCES,  TR_AUDIO_STREAM_NUMSOURCES,
693         ALC_MONO_SOURCES,   (TR_AUDIO_MAX_CHANNELS - TR_AUDIO_STREAM_NUMSOURCES),
694         ALC_FREQUENCY,       44100, 0};
695 
696     al_device = alcOpenDevice(NULL);
697     if (!al_device)
698     {
699         Sys_DebugLog(SYS_LOG_FILENAME, "InitAL: No AL audio devices!");
700         return;
701     }
702 
703     al_context = alcCreateContext(al_device, paramList);
704     if(!alcMakeContextCurrent(al_context))
705     {
706         Sys_DebugLog(SYS_LOG_FILENAME, "InitAL: AL context is not current!");
707         return;
708     }
709 
710     alSpeedOfSound(330.0 * 512.0);
711     alDopplerVelocity(330.0 * 510.0);
712     alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
713 
714     StreamTrack_Init(&audio_world_data.external_stream);
715 }
716 
717 
Audio_CoreDeinit()718 void Audio_CoreDeinit()
719 {
720     StreamTrack_Clear(&audio_world_data.external_stream);
721 
722     if(al_context)  // T4Larson <t4larson@gmail.com>: fixed
723     {
724         alcMakeContextCurrent(NULL);
725         alcDestroyContext(al_context);
726         al_context = NULL;
727     }
728 
729     if(al_device)
730     {
731         alcCloseDevice(al_device);
732         al_device = NULL;
733     }
734 }
735 
736 
Audio_StreamPlay(uint32_t track_index,const uint8_t mask)737 int Audio_StreamPlay(uint32_t track_index, const uint8_t mask)
738 {
739     int    target_stream = -1;
740 
741     // Don't even try to do anything with track, if its index is greater than overall amount of
742     // soundtracks specified in a stream track map count (which is derived from script).
743     if((track_index >= audio_world_data.stream_track_map_count) ||
744        (track_index >= audio_world_data.stream_buffers_count))
745     {
746         Con_AddLine("StreamPlay: CANCEL, track index is out of bounds.", FONTSTYLE_CONSOLE_WARNING);
747         return TR_AUDIO_STREAMPLAY_WRONGTRACK;
748     }
749 
750     // Don't play track, if it is already playing.
751     // This should become useless option, once proper one-shot trigger functionality is implemented.
752     if(Audio_IsTrackPlaying(track_index))
753     {
754         return TR_AUDIO_STREAMPLAY_IGNORED;
755     }
756 
757     // lua_GetSoundtrack returns stream type, file path and load method in last three
758     // provided arguments. That is, after calling this function we receive stream type
759     // in "stream_type" argument, file path into "file_path" argument and load method into
760     // "load_method" argument. Function itself returns false, if script wasn't found or
761     // request was broken; in this case, we quit.
762     if(!audio_world_data.stream_buffers[track_index])
763     {
764         Audio_CacheTrack(track_index);
765     }
766     StreamTrackBuffer *stb = audio_world_data.stream_buffers[track_index];
767     if(!stb)
768     {
769         Con_AddLine("StreamPlay: CANCEL, wrong track index or broken script.", FONTSTYLE_CONSOLE_WARNING);
770         return TR_AUDIO_STREAMPLAY_LOADERROR;
771     }
772 
773     // Don't try to play track, if it was already played by specified bit mask.
774     // Additionally, TrackAlreadyPlayed function applies specified bit mask to track map.
775     // Also, bit mask is valid only for non-looped tracks, since looped tracks are played
776     // in any way.
777     if((stb->stream_type != TR_AUDIO_STREAM_TYPE_BACKGROUND) &&
778         Audio_TrackAlreadyPlayed(track_index, mask))
779     {
780         return TR_AUDIO_STREAMPLAY_IGNORED;
781     }
782 
783     if(stb->stream_type != TR_AUDIO_STREAM_TYPE_ONESHOT)
784     {
785         Audio_StopStreams(stb->stream_type);
786     }
787 
788     // Entry found, now process to actual track loading.
789     target_stream = Audio_GetFreeStream();            // At first, we need to get free stream.
790     if(target_stream == -1)
791     {
792         Con_AddLine("StreamPlay: CANCEL, no free stream.", FONTSTYLE_CONSOLE_WARNING);
793         return TR_AUDIO_STREAMPLAY_NOFREESTREAM;  // No success, exit and don't play anything.
794     }
795 
796     stream_track_p s = audio_world_data.stream_tracks + target_stream;
797     s->track = stb->track_index;
798     s->type = stb->stream_type;
799     s->state = TR_AUDIO_STREAM_PLAYING;
800     s->current_volume = (s->type == TR_AUDIO_STREAM_TYPE_BACKGROUND) ? (0.0f) : (audio_settings.sound_volume);
801     while(StreamTrack_IsNeedUpdateBuffer(s) && (s->buffer_offset < stb->buffer_size))
802     {
803         size_t bytes = stb->buffer_part;
804         if(bytes > stb->buffer_size - s->buffer_offset)
805         {
806             bytes = stb->buffer_size - s->buffer_offset;
807         }
808         if(StreamTrack_UpdateBuffer(s, stb->buffer + s->buffer_offset, bytes, stb->sample_bitsize, stb->channels, stb->rate) <= 0)
809         {
810             break;
811         }
812     }
813 
814     if(audio_settings.use_effects)
815     {
816         StreamTrack_SetEffects(s, s->type == TR_AUDIO_STREAM_TYPE_CHAT);
817     }
818 
819     if(StreamTrack_Play(s) <= 0)
820     {
821         Con_AddLine("StreamPlay: CANCEL, stream play error.", FONTSTYLE_CONSOLE_WARNING);
822         return TR_AUDIO_STREAMPLAY_PLAYERROR;
823     }
824 
825     return TR_AUDIO_STREAMPLAY_PROCESSED;   // Everything is OK!
826 }
827 
828 
829 // Update routine for all streams. Should be placed into main loop.
Audio_UpdateStreams(float time)830 void Audio_UpdateStreams(float time)
831 {
832     stream_track_p s = audio_world_data.stream_tracks;
833     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
834     {
835         if(StreamTrack_UpdateState(s, time, audio_settings.sound_volume))
836         {
837             StreamTrackBuffer *stb = ((s->track >= 0) && (s->track < audio_world_data.stream_buffers_count)) ?
838                 (audio_world_data.stream_buffers[s->track]) : (NULL);
839 
840             while(stb && StreamTrack_IsNeedUpdateBuffer(s) && (s->buffer_offset < stb->buffer_size))
841             {
842                 size_t bytes = stb->buffer_part;
843                 if(bytes + s->buffer_offset > stb->buffer_size)
844                 {
845                     bytes = stb->buffer_size - s->buffer_offset;
846                 }
847                 if(StreamTrack_UpdateBuffer(s, stb->buffer + s->buffer_offset, bytes, stb->sample_bitsize, stb->channels, stb->rate) <= 0)
848                 {
849                     break;
850                 }
851             }
852 
853             if((s->buffer_offset >= stb->buffer_size) && (s->type == TR_AUDIO_STREAM_TYPE_BACKGROUND))
854             {
855                 s->buffer_offset = 0;
856             }
857         }
858     }
859 }
860 
861 
Audio_IsTrackPlaying(uint32_t track_index)862 int  Audio_IsTrackPlaying(uint32_t track_index)
863 {
864     stream_track_p s = audio_world_data.stream_tracks;
865     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
866     {
867         if(s->track == track_index)
868         {
869             return s->state != TR_AUDIO_STREAM_STOPPED;
870         }
871     }
872 
873     return 0;
874 }
875 
876 
Audio_TrackAlreadyPlayed(uint32_t track_index,int8_t mask)877 int  Audio_TrackAlreadyPlayed(uint32_t track_index, int8_t mask)
878 {
879     if(!mask)
880     {
881         return 0;   // No mask, play in any case.
882     }
883 
884     if(track_index >= audio_world_data.stream_track_map_count)
885     {
886         return 1;    // No such track, hence "already" played.
887     }
888     else
889     {
890         mask &= 0x3F;   // Clamp mask just in case.
891 
892         if(audio_world_data.stream_track_map[track_index] == mask)
893         {
894             return true;    // Immediately return true, if flags are directly equal.
895         }
896         else
897         {
898             int8_t played = audio_world_data.stream_track_map[track_index] & mask;
899             if(played == mask)
900             {
901                 return 1;    // Bits were set, hence already played.
902             }
903             else
904             {
905                 audio_world_data.stream_track_map[track_index] |= mask;
906                 return 0;   // Not yet played, set bits and return false.
907             }
908         }
909     }
910 }
911 
912 
Audio_GetFreeStream()913 int Audio_GetFreeStream()
914 {
915     int ret = TR_AUDIO_STREAMPLAY_NOFREESTREAM;
916     stream_track_p s = audio_world_data.stream_tracks;
917     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
918     {
919         if(s->state == TR_AUDIO_STREAM_STOPPED)
920         {
921             return i;
922         }
923         else if(s->state == TR_AUDIO_STREAM_PAUSED)
924         {
925             StreamTrack_Stop(s);
926             return i;
927         }
928     }
929 
930     return ret;
931 }
932 
933 
Audio_StopStreams(int stream_type)934 int  Audio_StopStreams(int stream_type)
935 {
936     int ret = 0;
937     stream_track_p s = audio_world_data.stream_tracks;
938     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
939     {
940         if((stream_type == -1) || (s->type == stream_type))
941         {
942             ret += (StreamTrack_Stop(s) > 0);
943         }
944     }
945 
946     return ret;
947 }
948 
949 
Audio_EndStreams(int stream_type)950 int  Audio_EndStreams(int stream_type)
951 {
952     int ret = 0;
953     stream_track_p s = audio_world_data.stream_tracks;
954     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
955     {
956         if((stream_type == -1) || (s->type == stream_type))
957         {
958             if(s->state == TR_AUDIO_STREAM_PLAYING)
959             {
960                 s->state = TR_AUDIO_STREAM_STOPPING;
961                 ret++;
962             }
963         }
964     }
965 
966     return ret;
967 }
968 
969 
Audio_PauseStreams(int stream_type)970 int  Audio_PauseStreams(int stream_type)
971 {
972     int ret = 0;
973 
974     stream_track_p s = audio_world_data.stream_tracks;
975     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
976     {
977         if((stream_type == -1) || (s->type == stream_type))
978         {
979             ret += (StreamTrack_Pause(s) > 0);
980         }
981     }
982 
983     return ret;
984 }
985 
986 
Audio_ResumeStreams(int stream_type)987 int  Audio_ResumeStreams(int stream_type)
988 {
989     int ret = 0;
990 
991     stream_track_p s = audio_world_data.stream_tracks;
992     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i, ++s)
993     {
994         if(((stream_type == -1) || (s->type == stream_type)) && (s->state == TR_AUDIO_STREAM_PAUSED))
995         {
996             ret += (StreamTrack_Play(s) > 0);
997         }
998     }
999 
1000     return ret;
1001 }
1002 
1003 
1004 // ======== Audio source global methods ========
Audio_IsInRange(int entity_type,int entity_ID,float range,float gain)1005 int  Audio_IsInRange(int entity_type, int entity_ID, float range, float gain)
1006 {
1007     ALfloat  vec[3] = {0.0, 0.0, 0.0}, dist;
1008     entity_p ent;
1009 
1010     switch(entity_type)
1011     {
1012         case TR_AUDIO_EMITTER_ENTITY:
1013             ent = World_GetEntityByID(entity_ID);
1014             if(!ent)
1015             {
1016                 return 0;
1017             }
1018             vec3_copy(vec, ent->transform.M4x4 + 12);
1019             break;
1020 
1021         case TR_AUDIO_EMITTER_SOUNDSOURCE:
1022             if((uint32_t)entity_ID + 1 > audio_world_data.audio_emitters_count)
1023             {
1024                 return 0;
1025             }
1026             vec3_copy(vec, audio_world_data.audio_emitters[entity_ID].position);
1027             break;
1028 
1029         case TR_AUDIO_EMITTER_GLOBAL:
1030             return 1;
1031 
1032         default:
1033             return 0;
1034     }
1035 
1036     dist = vec3_dist_sq(listener_position, vec);
1037 
1038     // We add 1/4 of overall distance to fix up some issues with
1039     // pseudo-looped sounds that are called at certain frames in animations.
1040 
1041     dist /= (gain + 1.25);
1042 
1043     return dist < range * range;
1044 }
1045 
1046 
Audio_UpdateSources()1047 void Audio_UpdateSources()
1048 {
1049     if(audio_world_data.audio_sources_count < 1)
1050     {
1051         return;
1052     }
1053 
1054     alGetListenerfv(AL_POSITION, listener_position);
1055 
1056     for(uint32_t i = 0; i < audio_world_data.audio_emitters_count; i++)
1057     {
1058         Audio_Send(audio_world_data.audio_emitters[i].sound_index, TR_AUDIO_EMITTER_SOUNDSOURCE, i);
1059     }
1060 
1061     for(uint32_t i = 0; i < audio_world_data.audio_sources_count; i++)
1062     {
1063         audio_world_data.audio_sources[i].Update();
1064     }
1065 }
1066 
1067 
Audio_PauseAllSources()1068 void Audio_PauseAllSources()
1069 {
1070     for(uint32_t i = 0; i < audio_world_data.audio_sources_count; i++)
1071     {
1072         if(audio_world_data.audio_sources[i].IsActive())
1073         {
1074             audio_world_data.audio_sources[i].Pause();
1075         }
1076     }
1077 }
1078 
1079 
Audio_StopAllSources()1080 void Audio_StopAllSources()
1081 {
1082     for(uint32_t i = 0; i < audio_world_data.audio_sources_count; i++)
1083     {
1084         audio_world_data.audio_sources[i].Stop();
1085     }
1086 }
1087 
1088 
Audio_ResumeAllSources()1089 void Audio_ResumeAllSources()
1090 {
1091     for(uint32_t i = 0; i < audio_world_data.audio_sources_count; i++)
1092     {
1093         if(audio_world_data.audio_sources[i].IsActive())
1094         {
1095             audio_world_data.audio_sources[i].Play();
1096         }
1097     }
1098 }
1099 
1100 
Audio_GetFreeSource()1101 int Audio_GetFreeSource()   ///@FIXME: add condition (compare max_dist with new source dist)
1102 {
1103     for(uint32_t i = 0; i < audio_world_data.audio_sources_count; i++)
1104     {
1105         if(audio_world_data.audio_sources[i].IsActive() == false)
1106         {
1107             return i;
1108         }
1109     }
1110 
1111     return -1;
1112 }
1113 
1114 
Audio_IsEffectPlaying(int effect_ID,int entity_type,int entity_ID)1115 int Audio_IsEffectPlaying(int effect_ID, int entity_type, int entity_ID)
1116 {
1117     for(uint32_t i = 0; i < audio_world_data.audio_sources_count; i++)
1118     {
1119         if( (audio_world_data.audio_sources[i].emitter_type == (uint32_t)entity_type) &&
1120             (audio_world_data.audio_sources[i].emitter_ID   == ( int32_t)entity_ID  ) &&
1121             (audio_world_data.audio_sources[i].effect_index == (uint32_t)effect_ID  ) &&
1122             audio_world_data.audio_sources[i].IsActive())
1123         {
1124             ALint state;
1125             alGetSourcei(audio_world_data.audio_sources[i].source_index, AL_SOURCE_STATE, &state);
1126             if(state == AL_PLAYING)
1127             {
1128                 return i;
1129             }
1130         }
1131     }
1132 
1133     return -1;
1134 }
1135 
1136 
Audio_Send(int effect_ID,int entity_type,int entity_ID)1137 int Audio_Send(int effect_ID, int entity_type, int entity_ID)
1138 {
1139     int32_t         source_number;
1140     uint16_t        random_value;
1141     ALfloat         random_float;
1142     audio_effect_p  effect = NULL;
1143     AudioSource    *source = NULL;
1144 
1145     // If there are no audio buffers or effect index is wrong, don't process.
1146     if((audio_world_data.audio_buffers_count < 1) || (effect_ID < 0))
1147     {
1148         return TR_AUDIO_SEND_IGNORED;
1149     }
1150 
1151     // Remap global engine effect ID to local effect ID.
1152     if((uint32_t)effect_ID >= audio_world_data.audio_map_count)
1153     {
1154         return TR_AUDIO_SEND_NOSAMPLE;  // Sound is out of bounds; stop.
1155     }
1156 
1157     int real_ID = (int)audio_world_data.audio_map[effect_ID];
1158 
1159     // Pre-step 1: if there is no effect associated with this ID, bypass audio send.
1160 
1161     if(real_ID == -1)
1162     {
1163         return TR_AUDIO_SEND_NOSAMPLE;
1164     }
1165     else
1166     {
1167         effect = audio_world_data.audio_effects + real_ID;
1168     }
1169 
1170     // Pre-step 2: check if sound non-looped and chance to play isn't zero,
1171     // then randomly select if it should be played or not.
1172 
1173     if((effect->loop != TR_AUDIO_LOOP_LOOPED) && (effect->chance > 0))
1174     {
1175         random_value = rand() % 0x7FFF;
1176         if(effect->chance < random_value)
1177         {
1178             // Bypass audio send, if chance test is not passed.
1179             return TR_AUDIO_SEND_IGNORED;
1180         }
1181     }
1182 
1183     // Pre-step 3: Calculate if effect's hearing sphere intersect listener's hearing sphere.
1184     // If it's not, bypass audio send (cause we don't want it to occupy channel, if it's not
1185     // heard).
1186 
1187     if(Audio_IsInRange(entity_type, entity_ID, effect->range, effect->gain ) == false)
1188     {
1189         return TR_AUDIO_SEND_IGNORED;
1190     }
1191 
1192     // Pre-step 4: check if R (Rewind) flag is set for this effect, if so,
1193     // find any effect with similar ID playing for this entity, and stop it.
1194     // Otherwise, if W (Wait) or L (Looped) flag is set, and same effect is
1195     // playing for current entity, don't send it and exit function.
1196 
1197     source_number = Audio_IsEffectPlaying(effect_ID, entity_type, entity_ID);
1198 
1199     if(source_number != -1)
1200     {
1201         if(effect->loop == TR_AUDIO_LOOP_REWIND)
1202         {
1203             audio_world_data.audio_sources[source_number].Stop();
1204         }
1205         else if(effect->loop) // Any other looping case (Wait / Loop).
1206         {
1207             return TR_AUDIO_SEND_IGNORED;
1208         }
1209     }
1210     else
1211     {
1212         source_number = Audio_GetFreeSource();  // Get free source.
1213     }
1214 
1215     if(source_number != -1)  // Everything is OK, we're sending audio to channel.
1216     {
1217         int buffer_index;
1218 
1219         // Step 1. Assign buffer to source.
1220 
1221         if(effect->sample_count > 1)
1222         {
1223             // Select random buffer, if effect info contains more than 1 assigned samples.
1224             random_value = rand() % (effect->sample_count);
1225             buffer_index = random_value + effect->sample_index;
1226         }
1227         else
1228         {
1229             // Just assign buffer to source, if there is only one assigned sample.
1230             buffer_index = effect->sample_index;
1231         }
1232 
1233         source = &audio_world_data.audio_sources[source_number];
1234 
1235         source->SetBuffer(buffer_index);
1236 
1237         // Step 2. Check looped flag, and if so, set source type to looped.
1238 
1239         if(effect->loop == TR_AUDIO_LOOP_LOOPED)
1240         {
1241             source->SetLooping(AL_TRUE);
1242         }
1243         else
1244         {
1245             source->SetLooping(AL_FALSE);
1246         }
1247 
1248         // Step 3. Apply internal sound parameters.
1249 
1250         source->emitter_ID   = entity_ID;
1251         source->emitter_type = entity_type;
1252         source->effect_index = effect_ID;
1253 
1254         // Step 4. Apply sound effect properties.
1255 
1256         if(effect->rand_pitch)  // Vary pitch, if flag is set.
1257         {
1258             random_float = rand() % effect->rand_pitch_var;
1259             random_float = effect->pitch + ((random_float - 25.0) / 200.0);
1260             source->SetPitch(random_float);
1261         }
1262         else
1263         {
1264             source->SetPitch(effect->pitch);
1265         }
1266 
1267         if(effect->rand_gain)   // Vary gain, if flag is set.
1268         {
1269             random_float = rand() % effect->rand_gain_var;
1270             random_float = effect->gain + (random_float - 25.0) / 200.0;
1271             source->SetGain(random_float);
1272         }
1273         else
1274         {
1275             source->SetGain(effect->gain);
1276         }
1277 
1278         source->SetRange(effect->range);    // Set audible range.
1279 
1280         source->Play();                     // Everything is OK, play sound now!
1281 
1282         return TR_AUDIO_SEND_PROCESSED;
1283     }
1284     else
1285     {
1286         return TR_AUDIO_SEND_NOCHANNEL;
1287     }
1288 }
1289 
1290 
Audio_Kill(int effect_ID,int entity_type,int entity_ID)1291 int Audio_Kill(int effect_ID, int entity_type, int entity_ID)
1292 {
1293     int playing_sound = Audio_IsEffectPlaying(effect_ID, entity_type, entity_ID);
1294 
1295     if(playing_sound != -1)
1296     {
1297         audio_world_data.audio_sources[playing_sound].Stop();
1298         return TR_AUDIO_SEND_PROCESSED;
1299     }
1300 
1301     return TR_AUDIO_SEND_IGNORED;
1302 }
1303 
1304 
Audio_LoadOverridedSamples()1305 void Audio_LoadOverridedSamples()
1306 {
1307     int  num_samples, num_sounds;
1308     int  sample_index, sample_count;
1309     char sample_name_mask[256];
1310     char sample_name[256];
1311 
1312     if(Script_GetOverridedSamplesInfo(engine_lua, &num_samples, &num_sounds, sample_name_mask))
1313     {
1314         int buffer_counter = 0;
1315 
1316         for(uint32_t i = 0; i < audio_world_data.audio_map_count; i++)
1317         {
1318             if(audio_world_data.audio_map[i] != -1)
1319             {
1320                 if(Script_GetOverridedSample(engine_lua, i, &sample_index, &sample_count))
1321                 {
1322                     for(int j = 0; j < sample_count; j++, buffer_counter++)
1323                     {
1324                         snprintf(sample_name, sizeof(sample_name), sample_name_mask, (sample_index + j));
1325                         if(Sys_FileFound(sample_name, 0))
1326                         {
1327                             Audio_LoadALbufferFromWAV_File(audio_world_data.audio_buffers[buffer_counter], sample_name);
1328                         }
1329                     }
1330                 }
1331                 else
1332                 {
1333                     buffer_counter += audio_world_data.audio_effects[(audio_world_data.audio_map[i])].sample_count;
1334                 }
1335             }
1336         }
1337     }
1338 }
1339 
1340 
Audio_InitGlobals()1341 void Audio_InitGlobals()
1342 {
1343     audio_settings.music_volume = 0.7;
1344     audio_settings.sound_volume = 0.8;
1345     audio_settings.use_effects  = true;
1346     audio_settings.listener_is_player = false;
1347 
1348     audio_world_data.audio_sources = NULL;
1349     audio_world_data.audio_sources_count = 0;
1350     audio_world_data.audio_buffers = NULL;
1351     audio_world_data.audio_buffers_count = 0;
1352     audio_world_data.audio_effects = NULL;
1353     audio_world_data.audio_effects_count = 0;
1354 
1355     audio_world_data.stream_tracks = NULL;
1356     audio_world_data.stream_tracks_count = 0;
1357     audio_world_data.stream_track_map = NULL;
1358     audio_world_data.stream_track_map_count = 0;
1359 }
1360 
1361 
Audio_Init(uint32_t num_Sources)1362 void Audio_Init(uint32_t num_Sources)
1363 {
1364     // FX should be inited first, as source constructor checks for FX slot to be created.
1365     if(audio_settings.use_effects)
1366     {
1367         Audio_InitFX();
1368     }
1369 
1370     // Generate new source array.
1371     num_Sources -= TR_AUDIO_STREAM_NUMSOURCES;          // Subtract sources reserved for music.
1372     audio_world_data.audio_sources_count = num_Sources;
1373     audio_world_data.audio_sources = new AudioSource[num_Sources];
1374 
1375     // Generate stream tracks array.
1376     audio_world_data.stream_tracks_count = TR_AUDIO_STREAM_NUMSOURCES - 1;
1377     audio_world_data.stream_tracks = (stream_track_p)malloc(audio_world_data.stream_tracks_count * sizeof(stream_track_t));
1378     for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i)
1379     {
1380         StreamTrack_Init(audio_world_data.stream_tracks + i);
1381     }
1382 }
1383 
1384 
Audio_CacheTrack(int id)1385 void Audio_CacheTrack(int id)
1386 {
1387     if((id >= 0) && (id < audio_world_data.stream_buffers_count) && !audio_world_data.stream_buffers[id])
1388     {
1389         StreamTrackBuffer *stb = new StreamTrackBuffer();
1390         if(stb->Load(id))
1391         {
1392             audio_world_data.stream_buffers[id] = stb;
1393         }
1394         else
1395         {
1396             delete stb;
1397         }
1398     }
1399 }
1400 
1401 
Audio_GenSamples(class VT_Level * tr)1402 void Audio_GenSamples(class VT_Level *tr)
1403 {
1404     uint8_t      *pointer = tr->samples_data;
1405     int8_t        flag;
1406     uint32_t      ind1, ind2;
1407     uint32_t      comp_size, uncomp_size;
1408     uint32_t      i;
1409 
1410     // Generate stream tracks buffers
1411     audio_world_data.stream_buffers = NULL;
1412     audio_world_data.stream_buffers_count = Script_GetNumTracks(engine_lua);
1413     if(audio_world_data.stream_buffers_count > 0)
1414     {
1415         audio_world_data.stream_buffers = (StreamTrackBuffer**)calloc(audio_world_data.stream_buffers_count, sizeof(StreamTrackBuffer*));
1416         Audio_CacheTrack(Script_GetSecretTrackNumber(engine_lua));
1417     }
1418 
1419     // Generate new buffer array.
1420     audio_world_data.audio_buffers_count = tr->samples_count;
1421     audio_world_data.audio_buffers = (ALuint*)malloc(audio_world_data.audio_buffers_count * sizeof(ALuint));
1422     memset(audio_world_data.audio_buffers, 0, sizeof(ALuint) * audio_world_data.audio_buffers_count);
1423     alGenBuffers(audio_world_data.audio_buffers_count, audio_world_data.audio_buffers);
1424 
1425     // Generate stream track map array.
1426     // We use scripted amount of tracks to define map bounds.
1427     // If script had no such parameter, we define map bounds by default.
1428     audio_world_data.stream_track_map_count = Script_GetNumTracks(engine_lua);
1429     if(audio_world_data.stream_track_map_count == 0) audio_world_data.stream_track_map_count = TR_AUDIO_STREAM_MAP_SIZE;
1430     audio_world_data.stream_track_map = (uint8_t*)malloc(audio_world_data.stream_track_map_count * sizeof(uint8_t));
1431     memset(audio_world_data.stream_track_map, 0, sizeof(uint8_t) * audio_world_data.stream_track_map_count);
1432 
1433     // Generate new audio effects array.
1434     audio_world_data.audio_effects_count = tr->sound_details_count;
1435     audio_world_data.audio_effects =  (audio_effect_t*)malloc(tr->sound_details_count * sizeof(audio_effect_t));
1436     memset(audio_world_data.audio_effects, 0xFF, sizeof(audio_effect_t) * tr->sound_details_count);
1437 
1438     // Generate new audio emitters array.
1439     audio_world_data.audio_emitters_count = tr->sound_sources_count;
1440     audio_world_data.audio_emitters = (audio_emitter_t*)malloc(tr->sound_sources_count * sizeof(audio_emitter_t));
1441     memset(audio_world_data.audio_emitters, 0, sizeof(audio_emitter_t) * tr->sound_sources_count);
1442 
1443     // Copy sound map.
1444     audio_world_data.audio_map = tr->soundmap;
1445     tr->soundmap = NULL;                   /// without it VT destructor free(tr->soundmap)
1446 
1447     // Cycle through raw samples block and parse them to OpenAL buffers.
1448 
1449     // Different TR versions have different ways of storing samples.
1450     // TR1:     sample block size, sample block, num samples, sample offsets.
1451     // TR2/TR3: num samples, sample offsets. (Sample block is in MAIN.SFX.)
1452     // TR4/TR5: num samples, (uncomp_size-comp_size-sample_data) chain.
1453     //
1454     // Hence, we specify certain parse method for each game version.
1455 
1456     if(pointer)
1457     {
1458         switch(tr->game_version)
1459         {
1460             case TR_I:
1461             case TR_I_DEMO:
1462             case TR_I_UB:
1463                 audio_world_data.audio_map_count = TR_AUDIO_MAP_SIZE_TR1;
1464 
1465                 for(i = 0; i < audio_world_data.audio_buffers_count-1; i++)
1466                 {
1467                     pointer = tr->samples_data + tr->sample_indices[i];
1468                     uint32_t size = tr->sample_indices[i + 1] - tr->sample_indices[i];
1469                     Audio_LoadALbufferFromWAV_Mem(audio_world_data.audio_buffers[i], pointer, size);
1470                 }
1471                 i = audio_world_data.audio_buffers_count-1;
1472                 Audio_LoadALbufferFromWAV_Mem(audio_world_data.audio_buffers[i], pointer, (tr->samples_count - tr->sample_indices[i]));
1473                 break;
1474 
1475             case TR_II:
1476             case TR_II_DEMO:
1477             case TR_III:
1478                 audio_world_data.audio_map_count = (tr->game_version == TR_III) ? (TR_AUDIO_MAP_SIZE_TR3) : (TR_AUDIO_MAP_SIZE_TR2);
1479                 ind1 = 0;
1480                 ind2 = 0;
1481                 flag = 0;
1482                 i = 0;
1483                 while(pointer < tr->samples_data + tr->samples_data_size - 4)
1484                 {
1485                     pointer = tr->samples_data + ind2;
1486                     if(!memcmp(pointer, "RIFF", 4))
1487                     {
1488                         if(flag == 0x00)
1489                         {
1490                             ind1 = ind2;
1491                             flag = 0x01;
1492                         }
1493                         else
1494                         {
1495                             uncomp_size = ind2 - ind1;
1496                             Audio_LoadALbufferFromWAV_Mem(audio_world_data.audio_buffers[i], tr->samples_data + ind1, uncomp_size);
1497                             i++;
1498                             if(i > audio_world_data.audio_buffers_count - 1)
1499                             {
1500                                 break;
1501                             }
1502                             ind1 = ind2;
1503                         }
1504                     }
1505                     ind2++;
1506                 }
1507                 uncomp_size = tr->samples_data_size - ind1;
1508                 pointer = tr->samples_data + ind1;
1509                 if(i < audio_world_data.audio_buffers_count)
1510                 {
1511                     Audio_LoadALbufferFromWAV_Mem(audio_world_data.audio_buffers[i], pointer, uncomp_size);
1512                 }
1513                 break;
1514 
1515             case TR_IV:
1516             case TR_IV_DEMO:
1517             case TR_V:
1518                 audio_world_data.audio_map_count = (tr->game_version == TR_V) ? (TR_AUDIO_MAP_SIZE_TR5) : (TR_AUDIO_MAP_SIZE_TR4);
1519 
1520                 for(i = 0; i < tr->samples_count; i++)
1521                 {
1522                     // Parse sample sizes.
1523                     // Always use comp_size as block length, as uncomp_size is used to cut raw sample data.
1524                     uncomp_size = *((uint32_t*)pointer);
1525                     pointer += 4;
1526                     comp_size   = *((uint32_t*)pointer);
1527                     pointer += 4;
1528 
1529                     // Load WAV sample into OpenAL buffer.
1530                     Audio_LoadALbufferFromWAV_Mem(audio_world_data.audio_buffers[i], pointer, comp_size, uncomp_size);
1531 
1532                     // Now we can safely move pointer through current sample data.
1533                     pointer += comp_size;
1534                 }
1535                 break;
1536 
1537             default:
1538                 audio_world_data.audio_map_count = TR_AUDIO_MAP_SIZE_NONE;
1539                 free(tr->samples_data);
1540                 tr->samples_data = NULL;
1541                 tr->samples_data_size = 0;
1542                 return;
1543         }
1544 
1545         free(tr->samples_data);
1546         tr->samples_data = NULL;
1547         tr->samples_data_size = 0;
1548     }
1549 
1550     // Cycle through SoundDetails and parse them into native OpenTomb
1551     // audio effects structure.
1552     for(i = 0; i < audio_world_data.audio_effects_count; i++)
1553     {
1554         if(tr->game_version < TR_III)
1555         {
1556             audio_world_data.audio_effects[i].gain   = (float)(tr->sound_details[i].volume) / 32767.0; // Max. volume in TR1/TR2 is 32767.
1557             audio_world_data.audio_effects[i].chance = tr->sound_details[i].chance;
1558         }
1559         else if(tr->game_version > TR_III)
1560         {
1561             audio_world_data.audio_effects[i].gain   = (float)(tr->sound_details[i].volume) / 255.0; // Max. volume in TR3 is 255.
1562             audio_world_data.audio_effects[i].chance = tr->sound_details[i].chance * 255;
1563         }
1564         else
1565         {
1566             audio_world_data.audio_effects[i].gain   = (float)(tr->sound_details[i].volume) / 255.0; // Max. volume in TR3 is 255.
1567             audio_world_data.audio_effects[i].chance = tr->sound_details[i].chance * 127;
1568         }
1569 
1570         audio_world_data.audio_effects[i].rand_gain_var  = 50;
1571         audio_world_data.audio_effects[i].rand_pitch_var = 50;
1572 
1573         audio_world_data.audio_effects[i].pitch = (float)(tr->sound_details[i].pitch) / 127.0 + 1.0;
1574         audio_world_data.audio_effects[i].range = (float)(tr->sound_details[i].sound_range) * 1024.0;
1575 
1576         audio_world_data.audio_effects[i].rand_pitch = (tr->sound_details[i].flags_2 & TR_AUDIO_FLAG_RAND_PITCH);
1577         audio_world_data.audio_effects[i].rand_gain  = (tr->sound_details[i].flags_2 & TR_AUDIO_FLAG_RAND_VOLUME);
1578 
1579         switch(tr->game_version)
1580         {
1581             case TR_I:
1582             case TR_I_DEMO:
1583             case TR_I_UB:
1584                 switch(tr->sound_details[i].num_samples_and_flags_1 & 0x03)
1585                 {
1586                     case 0x02:
1587                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_LOOPED;
1588                         break;
1589                     case 0x01:
1590                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_REWIND;
1591                         break;
1592                     default:
1593                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_NONE;
1594                 }
1595                 break;
1596 
1597             case TR_II:
1598             case TR_II_DEMO:
1599                 switch(tr->sound_details[i].num_samples_and_flags_1 & 0x03)
1600                 {
1601                     /*case 0x02:
1602                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_REWIND;
1603                         break;*/
1604                     case 0x01:
1605                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_REWIND;
1606                         break;
1607                     case 0x03:
1608                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_LOOPED;
1609                         break;
1610                     default:
1611                         audio_world_data.audio_effects[i].loop = TR_AUDIO_LOOP_NONE;
1612                 }
1613                 break;
1614 
1615             default:
1616                 audio_world_data.audio_effects[i].loop = (tr->sound_details[i].num_samples_and_flags_1 & TR_AUDIO_LOOP_LOOPED);
1617                 break;
1618         }
1619 
1620         audio_world_data.audio_effects[i].sample_index =  tr->sound_details[i].sample;
1621         audio_world_data.audio_effects[i].sample_count = (tr->sound_details[i].num_samples_and_flags_1 >> 2) & TR_AUDIO_SAMPLE_NUMBER_MASK;
1622     }
1623 
1624     // Try to override samples via script.
1625     // If there is no script entry exist, we just leave default samples.
1626     // NB! We need to override samples AFTER audio effects array is inited, as override
1627     //     routine refers to existence of certain audio effect in level.
1628 
1629     Audio_LoadOverridedSamples();
1630 
1631     // Hardcoded version-specific fixes!
1632 
1633     switch(tr->game_version)
1634     {
1635         case TR_I:
1636         case TR_I_DEMO:
1637         case TR_I_UB:
1638             // Fix for underwater looped sound.
1639             if ((audio_world_data.audio_map[TR_AUDIO_SOUND_UNDERWATER]) >= 0)
1640             {
1641                 audio_world_data.audio_effects[(audio_world_data.audio_map[TR_AUDIO_SOUND_UNDERWATER])].loop = TR_AUDIO_LOOP_LOOPED;
1642             }
1643             break;
1644         case TR_II:
1645             // Fix for helicopter sound range.
1646             if ((audio_world_data.audio_map[297]) >= 0)
1647             {
1648                 audio_world_data.audio_effects[(audio_world_data.audio_map[297])].range *= 10.0;
1649             }
1650             break;
1651     }
1652 
1653     // Cycle through sound emitters and
1654     // parse them to native OpenTomb sound emitters structure.
1655 
1656     for(i = 0; i < audio_world_data.audio_emitters_count; i++)
1657     {
1658         audio_world_data.audio_emitters[i].emitter_index = i;
1659         audio_world_data.audio_emitters[i].sound_index   =  tr->sound_sources[i].sound_id;
1660         audio_world_data.audio_emitters[i].position[0]   =  tr->sound_sources[i].x;
1661         audio_world_data.audio_emitters[i].position[1]   =  tr->sound_sources[i].z;
1662         audio_world_data.audio_emitters[i].position[2]   = -tr->sound_sources[i].y;
1663         audio_world_data.audio_emitters[i].flags         =  tr->sound_sources[i].flags;
1664     }
1665 }
1666 
1667 
Audio_DeInit()1668 int Audio_DeInit()
1669 {
1670     Audio_StopAllSources();
1671     Audio_StopStreams();
1672 
1673     if(audio_world_data.audio_sources)
1674     {
1675         audio_world_data.audio_sources_count = 0;
1676         delete[] audio_world_data.audio_sources;
1677         audio_world_data.audio_sources = NULL;
1678     }
1679 
1680     if(audio_world_data.audio_emitters)
1681     {
1682         audio_world_data.audio_emitters_count = 0;
1683         free(audio_world_data.audio_emitters);
1684         audio_world_data.audio_emitters = NULL;
1685     }
1686 
1687     if(audio_world_data.stream_tracks)
1688     {
1689         for(uint32_t i = 0; i < audio_world_data.stream_tracks_count; ++i)
1690         {
1691             StreamTrack_Clear(audio_world_data.stream_tracks + i);
1692         }
1693         free(audio_world_data.stream_tracks);
1694         audio_world_data.stream_tracks = NULL;
1695     }
1696     audio_world_data.stream_tracks_count = 0;
1697 
1698     if(audio_world_data.stream_track_map)
1699     {
1700         audio_world_data.stream_track_map_count = 0;
1701         free(audio_world_data.stream_track_map);
1702         audio_world_data.stream_track_map = NULL;
1703     }
1704 
1705     ///@CRITICAL: You must to delete all sources before buffers deleting!!!
1706 
1707     if(audio_world_data.audio_buffers)
1708     {
1709         alDeleteBuffers(audio_world_data.audio_buffers_count, audio_world_data.audio_buffers);
1710         audio_world_data.audio_buffers_count = 0;
1711         free(audio_world_data.audio_buffers);
1712         audio_world_data.audio_buffers = NULL;
1713     }
1714 
1715     if(audio_world_data.audio_effects)
1716     {
1717         audio_world_data.audio_effects_count = 0;
1718         free(audio_world_data.audio_effects);
1719         audio_world_data.audio_effects = NULL;
1720     }
1721 
1722     if(audio_world_data.audio_map)
1723     {
1724         audio_world_data.audio_map_count = 0;
1725         free(audio_world_data.audio_map);
1726         audio_world_data.audio_map = NULL;
1727     }
1728 
1729     Audio_DeinitFX();
1730 
1731     if(audio_world_data.stream_buffers)
1732     {
1733         for(uint32_t i = 0; i < audio_world_data.stream_buffers_count; i++)
1734         {
1735             if(audio_world_data.stream_buffers[i])
1736             {
1737                 delete audio_world_data.stream_buffers[i];
1738             }
1739             audio_world_data.stream_buffers[i] = NULL;
1740         }
1741         audio_world_data.stream_buffers_count = 0;
1742         free(audio_world_data.stream_buffers);
1743         audio_world_data.stream_buffers = NULL;
1744     }
1745 
1746     return 1;
1747 }
1748 
1749 
Audio_LogALError(int error_marker)1750 int  Audio_LogALError(int error_marker)
1751 {
1752     ALenum err = alGetError();
1753     if(err != AL_NO_ERROR)
1754     {
1755         Sys_DebugLog(SYS_LOG_FILENAME, "OpenAL error: %s / %d", alGetString(err), error_marker);
1756     }
1757     return err;
1758 }
1759 
1760 
1761 /*void Audio_LogOGGError(int code)
1762 {
1763     switch(code)
1764     {
1765         case OV_EREAD:
1766             Sys_DebugLog(SYS_LOG_FILENAME, "OGG error: Read from media.");
1767             break;
1768         case OV_ENOTVORBIS:
1769             Sys_DebugLog(SYS_LOG_FILENAME, "OGG error: Not Vorbis data.");
1770             break;
1771         case OV_EVERSION:
1772             Sys_DebugLog(SYS_LOG_FILENAME, "OGG error: Vorbis version mismatch.");
1773             break;
1774         case OV_EBADHEADER:
1775             Sys_DebugLog(SYS_LOG_FILENAME, "OGG error: Invalid Vorbis header.");
1776             break;
1777         case OV_EFAULT:
1778             Sys_DebugLog(SYS_LOG_FILENAME, "OGG error: Internal logic fault (bug or heap/stack corruption.");
1779             break;
1780         default:
1781             Sys_DebugLog(SYS_LOG_FILENAME, "OGG error: Unknown Ogg error.");
1782             break;
1783     }
1784 }*/
1785 
1786 
Audio_LoadALbufferFromWAV_Mem(ALuint buf_number,uint8_t * sample_pointer,uint32_t sample_size,uint32_t uncomp_sample_size)1787 int Audio_LoadALbufferFromWAV_Mem(ALuint buf_number, uint8_t *sample_pointer, uint32_t sample_size, uint32_t uncomp_sample_size)
1788 {
1789     SDL_AudioSpec wav_spec;
1790     Uint8        *wav_buffer;
1791     Uint32        wav_length;
1792 
1793     SDL_RWops *src = SDL_RWFromMem(sample_pointer, sample_size);
1794 
1795     // Decode WAV structure with SDL methods.
1796     // SDL automatically defines file format (PCM/ADPCM), so we shouldn't bother
1797     // about if it is TR4 compressed samples or TRLE uncompressed samples.
1798 
1799     if(SDL_LoadWAV_RW(src, 1, &wav_spec, &wav_buffer, &wav_length) == NULL)
1800     {
1801         Sys_DebugLog(SYS_LOG_FILENAME, "Error: can't load sample #%03d from sample block!", buf_number);
1802         return -1;
1803     }
1804 
1805     // Uncomp_sample_size explicitly specifies amount of raw sample data
1806     // to load into buffer. It is only used in TR4/5 with ADPCM samples,
1807     // because full-sized ADPCM sample contains a bit of silence at the end,
1808     // which should be removed. That's where uncomp_sample_size comes into
1809     // business.
1810     // Note that we also need to compare if uncomp_sample_size is smaller
1811     // than native wav length, because for some reason many TR5 uncomp sizes
1812     // are messed up and actually more than actual sample size.
1813 
1814     if((uncomp_sample_size == 0) || (wav_length < uncomp_sample_size))
1815     {
1816         uncomp_sample_size = wav_length;
1817     }
1818 
1819     // Find out sample format and load it correspondingly.
1820     // Note that with OpenAL, we can have samples of different formats in same level.
1821 
1822     bool result = Audio_FillALBuffer(buf_number, wav_buffer, uncomp_sample_size, wav_spec.format & SDL_AUDIO_MASK_BITSIZE, wav_spec.channels, wav_spec.freq);
1823 
1824     SDL_FreeWAV(wav_buffer);
1825 
1826     return (result) ? (0) : (-3);   // Zero means success.
1827 }
1828 
1829 
Audio_LoadALbufferFromWAV_File(ALuint buf_number,const char * fname)1830 int Audio_LoadALbufferFromWAV_File(ALuint buf_number, const char *fname)
1831 {
1832     SDL_RWops     *file;
1833     SDL_AudioSpec  wav_spec;
1834     Uint8         *wav_buffer;
1835     Uint32         wav_length;
1836 
1837     file = SDL_RWFromFile(fname, "rb");
1838 
1839     if(!file)
1840     {
1841         Con_Warning("file \"%s\" not exists", fname);
1842         return -1;
1843     }
1844 
1845     if(SDL_LoadWAV_RW(file, 1, &wav_spec, &wav_buffer, &wav_length) == NULL)
1846     {
1847         SDL_RWclose(file);
1848         Con_Warning("file \"%s\" has wrog format", fname);
1849         return -2;
1850     }
1851     SDL_RWclose(file);
1852 
1853     bool result = Audio_FillALBuffer(buf_number, wav_buffer, wav_length, wav_spec.format & SDL_AUDIO_MASK_BITSIZE, wav_spec.channels, wav_spec.freq);
1854 
1855     SDL_FreeWAV(wav_buffer);
1856 
1857     return (result) ? (0) : (-3);   // Zero means success.
1858 }
1859 
1860 
Audio_FillALBuffer(ALuint buf_number,Uint8 * buffer_data,Uint32 buffer_size,int sample_bitsize,int channels,int frequency)1861 bool Audio_FillALBuffer(ALuint buf_number, Uint8* buffer_data, Uint32 buffer_size, int sample_bitsize, int channels, int frequency)
1862 {
1863     if(channels > 2)   // We can't use non-mono and barely can use stereo samples.
1864     {
1865         Sys_DebugLog(SYS_LOG_FILENAME, "Error: sample %03d has more than 2 channels!", buf_number);
1866         return false;
1867     }
1868 
1869     // Check if bitsize is supported.
1870     // We rarely encounter samples with exotic bitsizes, but just in case...
1871     if((sample_bitsize != 32) && (sample_bitsize != 16) && (sample_bitsize != 8))
1872     {
1873         Sys_DebugLog(SYS_LOG_FILENAME, "Can't load sample - wrong bitsize (%d)", sample_bitsize);
1874         return false;
1875     }
1876 
1877     // Standard OpenAL sample loading process.
1878         ALenum sample_format = 0x00;
1879 
1880         if(channels == 1)
1881         {
1882             switch(sample_bitsize)
1883             {
1884                 case 8:
1885                     sample_format = AL_FORMAT_MONO8;
1886                     break;
1887                 case 16:
1888                     sample_format = AL_FORMAT_MONO16;
1889                     break;
1890 #ifdef HAVE_ALEXT_H
1891                 case 32:
1892                     sample_format = AL_FORMAT_MONO_FLOAT32;
1893                     break;
1894 #endif
1895             }
1896         }
1897         else
1898         {
1899             switch(sample_bitsize)
1900             {
1901                 case 8:
1902                     sample_format = AL_FORMAT_STEREO8;
1903                     break;
1904                 case 16:
1905                     sample_format = AL_FORMAT_STEREO16;
1906                     break;
1907 #ifdef HAVE_ALEXT_H
1908                 case 32:
1909                     sample_format = AL_FORMAT_STEREO_FLOAT32;
1910                     break;
1911 #endif
1912             }
1913         }
1914 
1915         alBufferData(buf_number, sample_format, buffer_data, buffer_size, frequency);
1916 
1917     return true;
1918 }
1919 
1920 
1921 /**
1922  * Updates listener parameters by camera structure. For correct speed calculation
1923  * that function have to be called every game frame.
1924  * @param cam - pointer to the camera structure.
1925  */
Audio_UpdateListenerByCamera(struct camera_s * cam,float time)1926 void Audio_UpdateListenerByCamera(struct camera_s *cam, float time)
1927 {
1928     ALfloat v[6];       // vec3 - forvard, vec3 - up
1929 
1930     vec3_copy(v + 0, cam->transform.M4x4 + 8);   // cam_OZ
1931     vec3_copy(v + 3, cam->transform.M4x4 + 4);   // cam_OY
1932     alListenerfv(AL_ORIENTATION, v);
1933 
1934     vec3_copy(v, cam->transform.M4x4 + 12);
1935     alListenerfv(AL_POSITION, v);
1936 
1937     vec3_sub(v, cam->transform.M4x4 + 12, cam->prev_pos);
1938     v[3] = 1.0 / time;
1939     vec3_mul_scalar(v, v, v[3]);
1940     alListenerfv(AL_VELOCITY, v);
1941     vec3_copy(cam->prev_pos, cam->transform.M4x4 + 12);
1942 
1943     if(cam->current_room)
1944     {
1945         bool old_state = Audio_GetFXWaterState();
1946         bool water_state = cam->current_room->content->room_flags & TR_ROOM_FLAG_WATER;
1947         Audio_SetFXWaterState(water_state);
1948         if(water_state)
1949         {
1950             Audio_SetFXRoomType(TR_AUDIO_FX_WATER);
1951         }
1952         else
1953         {
1954             Audio_SetFXRoomType(cam->current_room->content->reverb_info);
1955         }
1956 
1957         if(water_state != old_state)
1958         {
1959             if(water_state)
1960             {
1961                 Audio_Send(TR_AUDIO_SOUND_UNDERWATER);
1962             }
1963             else
1964             {
1965                 Audio_Kill(TR_AUDIO_SOUND_UNDERWATER);
1966             }
1967         }
1968     }
1969 }
1970 
1971 
Audio_UpdateListenerByEntity(struct entity_s * ent)1972 void Audio_UpdateListenerByEntity(struct entity_s *ent)
1973 {
1974     ///@FIXME: Add entity listener updater here.
1975 }
1976 
1977 
Audio_Update(float time)1978 void Audio_Update(float time)
1979 {
1980     Audio_UpdateSources();
1981     Audio_UpdateStreams(time);
1982     Audio_UpdateListenerByCamera(&engine_camera, time);
1983 }
1984 
1985 
Audio_GetStreamExternal()1986 struct stream_track_s *Audio_GetStreamExternal()
1987 {
1988     return &audio_world_data.external_stream;
1989 }
1990