1 /*
2 BStone: A Source port of
3 Blake Stone: Aliens of Gold and Blake Stone: Planet Strike
4
5 Copyright (c) 1992-2013 Apogee Entertainment, LLC
6 Copyright (c) 2013-2015 Boris I. Bendovsky (bibendovsky@hotmail.com)
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the
20 Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24
25 #include "bstone_audio_mixer.h"
26 #include <cassert>
27 #include <algorithm>
28 #include <functional>
29 #include "3d_def.h"
30 #include "bstone_adlib_music_decoder.h"
31 #include "bstone_adlib_sfx_decoder.h"
32 #include "bstone_pcm_decoder.h"
33
34
35 const int ATABLEMAX = 15;
36
37 extern bool sqPlayedOnce;
38 extern uint8_t lefttable[ATABLEMAX][ATABLEMAX * 2];
39 extern uint8_t righttable[ATABLEMAX][ATABLEMAX * 2];
40
41
42 namespace bstone
43 {
44
45
CacheItem()46 AudioMixer::CacheItem::CacheItem() :
47 is_active(),
48 is_invalid(),
49 sound_type(ST_NONE),
50 samples_count(),
51 decoded_count(),
52 decoder()
53 {
54 }
55
CacheItem(const CacheItem & that)56 AudioMixer::CacheItem::CacheItem(
57 const CacheItem& that) :
58 is_active(that.is_active),
59 is_invalid(that.is_invalid),
60 sound_type(that.sound_type),
61 samples_count(that.samples_count),
62 decoded_count(that.decoded_count),
63 samples(that.samples)
64 {
65 if (that.decoder)
66 {
67 decoder.reset(that.decoder->clone());
68 }
69 else
70 {
71 decoder = nullptr;
72 }
73 }
74
~CacheItem()75 AudioMixer::CacheItem::~CacheItem()
76 {
77 }
78
operator =(const CacheItem & that)79 AudioMixer::CacheItem& AudioMixer::CacheItem::operator=(
80 const CacheItem& that)
81 {
82 if (&that != this)
83 {
84 is_active = that.is_active;
85 is_invalid = that.is_invalid;
86 sound_type = that.sound_type;
87 samples_count = that.samples_count;
88 decoded_count = that.decoded_count;
89 samples = that.samples;
90
91 if (that.decoder)
92 {
93 decoder.reset(that.decoder->clone());
94 }
95 else
96 {
97 decoder = nullptr;
98 }
99 }
100
101 return *this;
102 }
103
is_decoded() const104 bool AudioMixer::CacheItem::is_decoded() const
105 {
106 return decoded_count == samples_count;
107 }
108
initialize()109 void AudioMixer::Positions::initialize()
110 {
111 player = {};
112
113 actors.clear();
114 actors.resize(MAXACTORS);
115
116 doors.clear();
117 doors.resize(MAXDOORS);
118
119 wall = {};
120 }
121
fixed_copy_to(Positions & target)122 void AudioMixer::Positions::fixed_copy_to(
123 Positions& target)
124 {
125 player = target.player;
126
127 std::copy(
128 actors.cbegin(),
129 actors.cend(),
130 target.actors.begin());
131
132 std::copy(
133 doors.cbegin(),
134 doors.cend(),
135 target.doors.begin());
136
137 wall = target.wall;
138 }
139
is_audible() const140 bool AudioMixer::Sound::is_audible() const
141 {
142 return left_volume > 0.0F && right_volume > 0.0F;
143 }
144
AudioMixer()145 AudioMixer::AudioMixer() :
146 is_initialized_(),
147 dst_rate_(),
148 device_id_(),
149
150 #if BSTONE_AUDIO_MIXER_USE_THREAD
151 mutex_(),
152 thread_(),
153 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
154
155 mix_samples_count_(),
156 buffer_(),
157 mix_buffer_(),
158 is_data_available_(),
159
160 #if BSTONE_AUDIO_MIXER_USE_THREAD
161 quit_thread_(),
162 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
163
164 sounds_(),
165 commands_(),
166 mute_(),
167 adlib_music_cache_(),
168 adlib_sfx_cache_(),
169 pcm_cache_(),
170 positions_(),
171 player_channels_state_(),
172 is_music_playing_(),
173 is_any_sfx_playing_(),
174 sfx_volume_(),
175 music_volume_(),
176 mix_size_ms_()
177 {
178 // Initialize atomic fields
179 //
180
181 is_data_available_ = false;
182
183 #if BSTONE_AUDIO_MIXER_USE_THREAD
184 quit_thread_ = false;
185 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
186
187 player_channels_state_ = 0;
188 is_music_playing_ = false;
189 is_any_sfx_playing_ = false;
190 sfx_volume_ = 1.0F;
191 music_volume_ = 1.0F;
192 }
193
~AudioMixer()194 AudioMixer::~AudioMixer()
195 {
196 uninitialize();
197 }
198
initialize(int dst_rate,int mix_size_ms)199 bool AudioMixer::initialize(
200 int dst_rate,
201 int mix_size_ms)
202 {
203 uninitialize();
204
205 if (dst_rate == 0)
206 {
207 dst_rate_ = get_default_rate();
208 }
209 else
210 {
211 dst_rate_ = std::max(dst_rate, get_min_rate());
212 }
213
214 if (mix_size_ms == 0)
215 {
216 mix_size_ms_ = get_default_mix_size_ms();
217 }
218 else
219 {
220 mix_size_ms_ = std::max(mix_size_ms, get_min_mix_size_ms());
221 }
222
223 mix_samples_count_ = calculate_mix_samples_count(
224 dst_rate_,
225 mix_size_ms_);
226
227 SDL_AudioSpec src_spec;
228 src_spec.freq = dst_rate_;
229 src_spec.format = AUDIO_S16SYS;
230 src_spec.channels = static_cast<uint8_t>(get_max_channels());
231 src_spec.samples = static_cast<uint16_t>(mix_samples_count_);
232 src_spec.callback = callback_proxy;
233 src_spec.userdata = this;
234
235 SDL_AudioSpec dst_spec;
236
237 device_id_ = ::SDL_OpenAudioDevice(
238 nullptr,
239 0,
240 &src_spec,
241 &dst_spec,
242 SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
243
244 if (device_id_ == 0)
245 {
246 return false;
247 }
248
249 bool is_succeed = true;
250
251
252 if (is_succeed)
253 {
254 positions_.initialize();
255 }
256
257 #if BSTONE_AUDIO_MIXER_USE_THREAD
258 std::thread thread;
259
260 if (is_succeed)
261 {
262 thread = std::thread(mix_proxy, this);
263 }
264 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
265
266 if (is_succeed)
267 {
268 is_initialized_ = true;
269 mix_samples_count_ = dst_spec.samples;
270
271 const auto total_samples = get_max_channels() * mix_samples_count_;
272
273 buffer_.resize(total_samples);
274 mix_buffer_.resize(total_samples);
275
276 adlib_music_cache_.resize(LASTMUSIC);
277 adlib_sfx_cache_.resize(NUMSOUNDS);
278 pcm_cache_.resize(NUMSOUNDS);
279
280 commands_.initialize(get_max_commands());
281
282 #if BSTONE_AUDIO_MIXER_USE_THREAD
283 thread_ = std::move(thread);
284 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
285
286 ::SDL_PauseAudioDevice(device_id_, 0);
287 }
288 else
289 {
290 uninitialize();
291 }
292
293 return is_succeed;
294 }
295
uninitialize()296 void AudioMixer::uninitialize()
297 {
298 is_initialized_ = false;
299
300 if (device_id_ != 0)
301 {
302 ::SDL_PauseAudioDevice(device_id_, 1);
303 ::SDL_CloseAudioDevice(device_id_);
304 device_id_ = 0;
305 }
306
307 #if BSTONE_AUDIO_MIXER_USE_THREAD
308 if (thread_.joinable())
309 {
310 quit_thread_ = true;
311 thread_.join();
312 }
313 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
314
315 dst_rate_ = 0;
316 mix_samples_count_ = 0;
317 Samples().swap(buffer_);
318 MixSamples().swap(mix_buffer_);
319 is_data_available_ = false;
320
321 #if BSTONE_AUDIO_MIXER_USE_THREAD
322 quit_thread_ = false;
323 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
324
325 Sounds().swap(sounds_);
326 commands_.uninitialize();
327 mute_ = false;
328 Cache().swap(adlib_music_cache_);
329 Cache().swap(adlib_sfx_cache_);
330 Cache().swap(pcm_cache_);
331 player_channels_state_ = 0;
332 is_music_playing_ = false;
333 is_any_sfx_playing_ = false;
334 mix_size_ms_ = 0;
335 }
336
is_initialized() const337 bool AudioMixer::is_initialized() const
338 {
339 return is_initialized_;
340 }
341
play_adlib_music(int music_index,const void * data,int data_size)342 bool AudioMixer::play_adlib_music(
343 int music_index,
344 const void* data,
345 int data_size)
346 {
347 return play_sound(
348 ST_ADLIB_MUSIC,
349 0,
350 music_index,
351 data,
352 data_size);
353 }
354
play_adlib_sound(int sound_index,int priority,const void * data,int data_size,int actor_index,ActorType actor_type,ActorChannel actor_channel)355 bool AudioMixer::play_adlib_sound(
356 int sound_index,
357 int priority,
358 const void* data,
359 int data_size,
360 int actor_index,
361 ActorType actor_type,
362 ActorChannel actor_channel)
363 {
364 return play_sound(
365 ST_ADLIB_SFX,
366 priority,
367 sound_index,
368 data,
369 data_size,
370 actor_index,
371 actor_type,
372 actor_channel);
373 }
374
play_pcm_sound(int sound_index,int priority,const void * data,int data_size,int actor_index,ActorType actor_type,ActorChannel actor_channel)375 bool AudioMixer::play_pcm_sound(
376 int sound_index,
377 int priority,
378 const void* data,
379 int data_size,
380 int actor_index,
381 ActorType actor_type,
382 ActorChannel actor_channel)
383 {
384 return play_sound(
385 ST_PCM,
386 priority,
387 sound_index,
388 data,
389 data_size,
390 actor_index,
391 actor_type,
392 actor_channel);
393 }
394
update_positions()395 bool AudioMixer::update_positions()
396 {
397 if (!is_initialized())
398 {
399 return false;
400 }
401
402
403 auto& state = positions_;
404
405 state.player.view_x = viewx;
406 state.player.view_y = viewy;
407 state.player.view_cos = viewcos;
408 state.player.view_sin = viewsin;
409
410 state.actors.resize(MAXACTORS);
411
412 for (int i = 0; i < MAXACTORS; ++i)
413 {
414 auto& actor = state.actors[i];
415
416 actor.x = objlist[i].x;
417 actor.y = objlist[i].y;
418 }
419
420 state.doors.resize(MAXDOORS);
421
422 for (int i = 0; i < MAXDOORS; ++i)
423 {
424 auto& door = state.doors[i];
425
426 door.x = (doorobjlist[i].tilex << TILESHIFT) +
427 (1 << (TILESHIFT - 1));
428
429 door.y = (doorobjlist[i].tiley << TILESHIFT) +
430 (1 << (TILESHIFT - 1));
431 }
432
433 state.wall.x = (pwallx << TILESHIFT) + (1 << (TILESHIFT - 1));
434 state.wall.y = (pwally << TILESHIFT) + (1 << (TILESHIFT - 1));
435
436 const int wall_offset = (65535 * pwallpos) / 63;
437
438 switch (pwalldir) {
439 case di_east:
440 state.wall.x += wall_offset;
441 break;
442
443 case di_north:
444 state.wall.y -= wall_offset;
445 break;
446
447 case di_south:
448 state.wall.y += wall_offset;
449 break;
450
451 case di_west:
452 state.wall.x -= wall_offset;
453 break;
454
455 default:
456 break;
457 }
458
459 return true;
460 }
461
stop_music()462 bool AudioMixer::stop_music()
463 {
464 if (!is_initialized())
465 {
466 return false;
467 }
468
469 commands_.push(
470 [] (Command& command)
471 {
472 command.command = CMD_STOP_MUSIC;
473 }
474 );
475
476 return true;
477 }
478
stop_all_sfx()479 bool AudioMixer::stop_all_sfx()
480 {
481 if (!is_initialized())
482 {
483 return false;
484 }
485
486 commands_.push(
487 [] (Command& command)
488 {
489 command.command = CMD_STOP_ALL_SFX;
490 }
491 );
492
493 return true;
494 }
495
set_mute(bool value)496 bool AudioMixer::set_mute(
497 bool value)
498 {
499 if (!is_initialized())
500 {
501 return false;
502 }
503
504 mute_ = value;
505
506 return true;
507 }
508
set_sfx_volume(float volume)509 bool AudioMixer::set_sfx_volume(
510 float volume)
511 {
512 if (!is_initialized())
513 {
514 return false;
515 }
516
517 if (volume < 0.0F)
518 {
519 volume = 0.0F;
520 }
521
522 if (volume > 1.0F)
523 {
524 volume = 1.0F;
525 }
526
527 sfx_volume_ = volume;
528
529 return true;
530 }
531
set_music_volume(float volume)532 bool AudioMixer::set_music_volume(
533 float volume)
534 {
535 if (!is_initialized())
536 {
537 return false;
538 }
539
540 if (volume < 0.0F)
541 {
542 volume = 0.0F;
543 }
544
545 if (volume > 1.0F)
546 {
547 volume = 1.0F;
548 }
549
550 music_volume_ = volume;
551
552 return true;
553 }
554
is_music_playing() const555 bool AudioMixer::is_music_playing() const
556 {
557 if (!is_initialized())
558 {
559 return false;
560 }
561
562 return is_music_playing_;
563 }
564
is_any_sfx_playing() const565 bool AudioMixer::is_any_sfx_playing() const
566 {
567 if (!is_initialized())
568 {
569 return false;
570 }
571
572 return is_any_sfx_playing_;
573 }
574
is_player_channel_playing(ActorChannel channel) const575 bool AudioMixer::is_player_channel_playing(
576 ActorChannel channel) const
577 {
578 return (player_channels_state_ & (1 << channel)) != 0;
579 }
580
get_min_rate()581 int AudioMixer::get_min_rate()
582 {
583 return 11025;
584 }
585
get_default_rate()586 int AudioMixer::get_default_rate()
587 {
588 return 44100;
589 }
590
get_min_mix_size_ms()591 int AudioMixer::get_min_mix_size_ms()
592 {
593 return 20;
594 }
595
get_default_mix_size_ms()596 int AudioMixer::get_default_mix_size_ms()
597 {
598 return 40;
599 }
600
get_max_channels()601 int AudioMixer::get_max_channels()
602 {
603 return 2;
604 }
605
get_max_commands()606 int AudioMixer::get_max_commands()
607 {
608 return 128;
609 }
610
callback(uint8_t * dst_data,int dst_length)611 void AudioMixer::callback(
612 uint8_t* dst_data,
613 int dst_length)
614 {
615 if (!mute_ && is_data_available_)
616 {
617 std::uninitialized_copy_n(
618 reinterpret_cast<const uint8_t*>(buffer_.data()),
619 dst_length,
620 dst_data);
621 }
622 else
623 {
624 std::uninitialized_fill_n(dst_data, dst_length, 0);
625 }
626
627 is_data_available_ = false;
628 }
629
mix()630 void AudioMixer::mix()
631 {
632 #if BSTONE_AUDIO_MIXER_USE_THREAD
633 while (!quit_thread_)
634 {
635 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
636 handle_commands();
637
638 if (!is_data_available_ && !sounds_.empty())
639 {
640 mix_samples();
641 is_data_available_ = true;
642 #if BSTONE_AUDIO_MIXER_USE_THREAD
643 }
644 else
645 {
646 ::sys_default_sleep_for();
647 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
648 }
649 #if BSTONE_AUDIO_MIXER_USE_THREAD
650 }
651 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
652 }
653
mix_samples()654 void AudioMixer::mix_samples()
655 {
656 spatialize_sounds();
657
658 float sfx_volume = sfx_volume_;
659 float music_volume = music_volume_;
660
661 float min_left_sample = 32767;
662 float max_left_sample = -32768;
663
664 float min_right_sample = 32767;
665 float max_right_sample = -32768;
666
667 for (int i = 0; i < mix_samples_count_; ++i)
668 {
669 float left_sample = 0.0F;
670 float right_sample = 0.0F;
671
672 for (auto sound = sounds_.begin(); sound != sounds_.end(); )
673 {
674 if (!decode_sound(*sound))
675 {
676 set_player_channel_state(*sound, false);
677 sound = sounds_.erase(sound);
678 continue;
679 }
680
681 auto cache_item = sound->cache;
682
683 if (sound->decode_offset == cache_item->decoded_count)
684 {
685 ++sound;
686 continue;
687 }
688
689 float volume_scale;
690
691 switch (sound->type)
692 {
693 case ST_ADLIB_MUSIC:
694 volume_scale = 8.0F * music_volume;
695 break;
696
697 case ST_ADLIB_SFX:
698 volume_scale = 8.0F * sfx_volume;
699 break;
700
701 default:
702 volume_scale = sfx_volume;
703 break;
704 }
705
706 if (sound->is_audible())
707 {
708 float sample = volume_scale *
709 cache_item->samples[sound->decode_offset];
710
711 left_sample += sound->left_volume * sample;
712 right_sample += sound->right_volume * sample;
713 }
714
715 ++sound->decode_offset;
716
717 if (sound->decode_offset == cache_item->decoded_count)
718 {
719 if (cache_item->is_decoded())
720 {
721 if (sound->type == ST_ADLIB_MUSIC)
722 {
723 sqPlayedOnce = true;
724 sound->decode_offset = 0;
725 }
726 else
727 {
728 set_player_channel_state(*sound, false);
729 sound = sounds_.erase(sound);
730 continue;
731 }
732 }
733 }
734
735 ++sound;
736 }
737
738 mix_buffer_[(2 * i) + 0] = left_sample;
739 min_left_sample = std::min(left_sample, min_left_sample);
740 max_left_sample = std::max(left_sample, max_left_sample);
741
742 mix_buffer_[(2 * i) + 1] = right_sample;
743 min_right_sample = std::min(right_sample, min_right_sample);
744 max_right_sample = std::max(right_sample, max_right_sample);
745 }
746
747 //
748 // Calculate normalizations factors.
749 //
750
751 bool normalize_left = false;
752 float normalize_left_scale = 1.0F;
753
754 if (min_left_sample < -32768 && -min_left_sample > max_left_sample)
755 {
756 normalize_left = true;
757 normalize_left_scale = -32768.0F / min_left_sample;
758 }
759 else if (max_left_sample > 32767 && max_left_sample >= -min_left_sample)
760 {
761 normalize_left = true;
762 normalize_left_scale = 32767.0F / max_left_sample;
763 }
764
765 bool normalize_right = false;
766 float normalize_right_scale = 1.0F;
767
768 if (min_right_sample < -32768 && -min_right_sample > max_right_sample)
769 {
770 normalize_right = true;
771 normalize_right_scale = -32768.0F / min_right_sample;
772 }
773 else if (max_right_sample > 32767 && max_right_sample >= -min_right_sample)
774 {
775 normalize_right = true;
776 normalize_right_scale = 32767.0F / max_right_sample;
777 }
778
779
780 //
781 // Normalize and output.
782 //
783
784 for (int i = 0; i < mix_samples_count_; ++i)
785 {
786 float left_sample = mix_buffer_[(2 * i) + 0];
787 float right_sample = mix_buffer_[(2 * i) + 1];
788
789 if (normalize_left)
790 {
791 left_sample *= normalize_left_scale;
792 }
793
794 left_sample = std::min(left_sample, 32767.0F);
795 left_sample = std::max(left_sample, -32768.0F);
796
797 if (normalize_right) {
798 right_sample *= normalize_right_scale;
799 }
800
801 right_sample = std::min(right_sample, 32767.0F);
802 right_sample = std::max(right_sample, -32768.0F);
803
804 buffer_[(2 * i) + 0] = static_cast<int16_t>(left_sample);
805 buffer_[(2 * i) + 1] = static_cast<int16_t>(right_sample);
806 }
807
808 int music_count = is_music_playing() ? 1 : 0;
809 is_any_sfx_playing_ = ((sounds_.size() - music_count) > 0);
810 }
811
handle_commands()812 void AudioMixer::handle_commands()
813 {
814 Command command;
815
816 while (commands_.pop(command))
817 {
818 switch (command.command)
819 {
820 case CMD_PLAY:
821 handle_play_command(command);
822 break;
823
824 case CMD_STOP_MUSIC:
825 handle_stop_music_command();
826 break;
827
828 default:
829 break;
830 }
831 }
832 }
833
handle_play_command(const Command & command)834 void AudioMixer::handle_play_command(
835 const Command& command)
836 {
837 auto cache_item = command.sound.cache;
838
839 if (!cache_item)
840 {
841 return;
842 }
843
844 if (!initialize_cache_item(command, *cache_item))
845 {
846 return;
847 }
848
849 if (command.sound.type != ST_ADLIB_MUSIC &&
850 command.sound.actor_index >= 0)
851 {
852 // Search existing sound which can override a
853 // new one because of priority.
854
855 for (const auto& sound : sounds_)
856 {
857 if (sound.priority > command.sound.priority &&
858 sound.actor_index == command.sound.actor_index &&
859 sound.actor_type == command.sound.actor_type &&
860 sound.actor_channel == command.sound.actor_channel)
861 {
862 return;
863 }
864 }
865
866 // Remove sounds which will be overwritten.
867
868 for (auto i = sounds_.begin(); i != sounds_.end(); )
869 {
870 if (i->actor_index == command.sound.actor_index &&
871 i->actor_type == command.sound.actor_type &&
872 i->actor_channel == command.sound.actor_channel)
873 {
874 set_player_channel_state(*i, false);
875 i = sounds_.erase(i);
876 }
877 else
878 {
879 ++i;
880 }
881 }
882 }
883
884 if (command.sound.type == ST_ADLIB_MUSIC)
885 {
886 is_music_playing_ = true;
887 }
888 else
889 {
890 is_any_sfx_playing_ = true;
891 }
892
893 auto sound = command.sound;
894 sound.decode_offset = 0;
895 sounds_.push_back(sound);
896
897 set_player_channel_state(sound, true);
898 }
899
handle_stop_music_command()900 void AudioMixer::handle_stop_music_command()
901 {
902 is_music_playing_ = false;
903
904 for (auto i = sounds_.begin(); i != sounds_.end(); )
905 {
906 if (i->type != ST_ADLIB_MUSIC) {
907 ++i;
908 }
909 else
910 {
911 *(i->cache) = CacheItem();
912 i = sounds_.erase(i);
913 }
914 }
915 }
916
handle_stop_all_sfx_command()917 void AudioMixer::handle_stop_all_sfx_command()
918 {
919 is_any_sfx_playing_ = false;
920
921 sounds_.remove_if(
922 [] (const Sound& sound)
923 {
924 return sound.type != ST_ADLIB_MUSIC;
925 }
926 );
927 }
928
initialize_cache_item(const Command & command,CacheItem & cache_item)929 bool AudioMixer::initialize_cache_item(
930 const Command& command,
931 CacheItem& cache_item)
932 {
933 if (cache_item.is_active)
934 {
935 return !cache_item.is_invalid;
936 }
937
938 cache_item = CacheItem();
939
940 bool is_succeed = true;
941 auto decoder = std::unique_ptr<AudioDecoder>{};
942
943 if (is_succeed)
944 {
945 decoder.reset(
946 create_decoder_by_sound_type(
947 command.sound.type));
948
949 is_succeed = (decoder != nullptr);
950 }
951
952 if (is_succeed)
953 {
954 is_succeed = decoder->initialize(
955 command.data,
956 command.data_size,
957 dst_rate_);
958 }
959
960 int samples_count = 0;
961
962 if (is_succeed)
963 {
964 samples_count = decoder->get_dst_length_in_samples();
965 is_succeed = (samples_count > 0);
966 }
967
968 cache_item.is_active = true;
969
970 if (is_succeed)
971 {
972 cache_item.sound_type = command.sound.type;
973 cache_item.samples_count = samples_count;
974 cache_item.samples.resize(samples_count);
975 cache_item.decoder.swap(decoder);
976 }
977 else
978 {
979 cache_item.is_invalid = true;
980 }
981
982 return is_succeed;
983 }
984
decode_sound(const Sound & sound)985 bool AudioMixer::decode_sound(
986 const Sound& sound)
987 {
988 auto cache_item = sound.cache;
989
990 if (!cache_item)
991 {
992 return false;
993 }
994
995 if (!cache_item->is_active)
996 {
997 return false;
998 }
999
1000 if (cache_item->is_invalid)
1001 {
1002 return false;
1003 }
1004
1005 if (cache_item->is_decoded())
1006 {
1007 return true;
1008 }
1009
1010 int ahead_count = std::min(
1011 sound.decode_offset + mix_samples_count_,
1012 cache_item->samples_count);
1013
1014 if (ahead_count <= cache_item->decoded_count)
1015 {
1016 return true;
1017 }
1018
1019 int planned_count = std::min(
1020 cache_item->samples_count - cache_item->decoded_count,
1021 mix_samples_count_);
1022
1023 int actual_count = cache_item->decoder->decode(
1024 planned_count,
1025 &cache_item->samples[cache_item->decoded_count]);
1026
1027 cache_item->decoded_count += actual_count;
1028
1029 return true;
1030 }
1031
spatialize_sound(Sound & sound)1032 void AudioMixer::spatialize_sound(
1033 Sound& sound)
1034 {
1035 sound.left_volume = 1.0F;
1036 sound.right_volume = 1.0F;
1037
1038 if (sound.type == ST_ADLIB_MUSIC)
1039 {
1040 return;
1041 }
1042
1043 if (sound.actor_index <= 0)
1044 {
1045 return;
1046 }
1047
1048 Location* location = nullptr;
1049
1050 switch (sound.actor_type)
1051 {
1052 case AT_ACTOR:
1053 location = &positions_.actors[sound.actor_index];
1054 break;
1055
1056 case AT_DOOR:
1057 location = &positions_.doors[sound.actor_index];
1058 break;
1059
1060 case AT_WALL:
1061 location = &positions_.wall;
1062 break;
1063
1064 default:
1065 return;
1066 }
1067
1068 int gx = location->x;
1069 int gy = location->y;
1070
1071 //
1072 // translate point to view centered coordinates
1073 //
1074 gx -= positions_.player.view_x;
1075 gy -= positions_.player.view_y;
1076
1077 //
1078 // calculate newx
1079 //
1080 int xt = ::FixedByFrac(gx, positions_.player.view_cos);
1081 int yt = ::FixedByFrac(gy, positions_.player.view_sin);
1082 int x = (xt - yt) >> TILESHIFT;
1083
1084 //
1085 // calculate newy
1086 //
1087 xt = ::FixedByFrac(gx, positions_.player.view_sin);
1088 yt = ::FixedByFrac(gy, positions_.player.view_cos);
1089
1090 int y = (yt + xt) >> TILESHIFT;
1091
1092 if (y <= -ATABLEMAX)
1093 {
1094 y = -ATABLEMAX;
1095 }
1096
1097 if (y >= ATABLEMAX)
1098 {
1099 y = ATABLEMAX - 1;
1100 }
1101
1102 if (x < 0)
1103 {
1104 x = -x;
1105 }
1106
1107 if (x >= ATABLEMAX)
1108 {
1109 x = ATABLEMAX - 1;
1110 }
1111
1112 int left = 9 - lefttable[x][y + ATABLEMAX];
1113 int right = 9 - righttable[x][y + ATABLEMAX];
1114
1115 sound.left_volume = left / 9.0F;
1116 sound.right_volume = right / 9.0F;
1117 }
1118
spatialize_sounds()1119 void AudioMixer::spatialize_sounds()
1120 {
1121 for (auto& sound : sounds_)
1122 {
1123 spatialize_sound(sound);
1124 }
1125 }
1126
play_sound(SoundType sound_type,int priority,int sound_index,const void * data,int data_size,int actor_index,ActorType actor_type,ActorChannel actor_channel)1127 bool AudioMixer::play_sound(
1128 SoundType sound_type,
1129 int priority,
1130 int sound_index,
1131 const void* data,
1132 int data_size,
1133 int actor_index,
1134 ActorType actor_type,
1135 ActorChannel actor_channel)
1136 {
1137 if (!is_initialized())
1138 {
1139 return false;
1140 }
1141
1142 if (!is_sound_type_valid(sound_type))
1143 {
1144 return false;
1145 }
1146
1147 if (priority < 0)
1148 {
1149 return false;
1150 }
1151
1152 if (!data)
1153 {
1154 return false;
1155 }
1156
1157 if (data_size <= 0)
1158 {
1159 return false;
1160 }
1161
1162 if (actor_index >= MAXACTORS)
1163 {
1164 return false;
1165 }
1166
1167 switch (actor_channel) {
1168 case AC_VOICE:
1169 case AC_WEAPON:
1170 case AC_ITEM:
1171 case AC_HIT_WALL:
1172 case AC_NO_WAY:
1173 case AC_INTERROGATION:
1174 break;
1175
1176 default:
1177 throw std::invalid_argument("Invalid actor channel.");
1178 }
1179
1180 commands_.push(
1181 [&] (Command& command)
1182 {
1183 command.command = CMD_PLAY;
1184 command.sound.type = sound_type;
1185 command.sound.priority = priority;
1186 command.sound.cache = get_cache_item(sound_type, sound_index);
1187 command.sound.actor_index = actor_index;
1188 command.sound.actor_type = actor_type;
1189 command.sound.actor_channel = actor_channel;
1190 command.data = data;
1191 command.data_size = data_size;
1192 }
1193 );
1194
1195 return true;
1196 }
1197
lock()1198 void AudioMixer::lock()
1199 {
1200 #if BSTONE_AUDIO_MIXER_USE_THREAD
1201 mutex_.lock();
1202 #else
1203 ::SDL_LockAudioDevice(device_id_);
1204 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
1205 }
1206
unlock()1207 void AudioMixer::unlock()
1208 {
1209 #if BSTONE_AUDIO_MIXER_USE_THREAD
1210 mutex_.unlock();
1211 #else
1212 ::SDL_UnlockAudioDevice(device_id_);
1213 #endif // BSTONE_AUDIO_MIXER_USE_THREAD
1214 }
1215
callback_proxy(void * user_data,uint8_t * dst_data,int dst_length)1216 void AudioMixer::callback_proxy(
1217 void* user_data,
1218 uint8_t* dst_data,
1219 int dst_length)
1220 {
1221 assert(user_data);
1222
1223 auto mixer = static_cast<AudioMixer*>(user_data);
1224
1225 #if !BSTONE_AUDIO_MIXER_USE_THREAD
1226 mixer->mix();
1227 #endif // !BSTONE_AUDIO_MIXER_USE_THREAD
1228
1229 mixer->callback(dst_data, dst_length);
1230 }
1231
mix_proxy(void * user_data)1232 int AudioMixer::mix_proxy(
1233 void* user_data)
1234 {
1235 assert(user_data);
1236
1237 auto mixer = static_cast<AudioMixer*>(user_data);
1238 mixer->mix();
1239
1240 return 0;
1241 }
1242
calculate_mix_samples_count(int dst_rate,int mix_size_ms)1243 int AudioMixer::calculate_mix_samples_count(
1244 int dst_rate,
1245 int mix_size_ms)
1246 {
1247 int exact_count = (dst_rate * mix_size_ms) / 1000;
1248 int actual_count = 1;
1249
1250 while (actual_count < exact_count)
1251 {
1252 actual_count *= 2;
1253 }
1254
1255 if (actual_count > 65536)
1256 {
1257 actual_count = 65536;
1258 }
1259
1260 return actual_count;
1261 }
1262
get_cache_item(SoundType sound_type,int sound_index)1263 AudioMixer::CacheItem* AudioMixer::get_cache_item(
1264 SoundType sound_type,
1265 int sound_index)
1266 {
1267 if (!is_sound_index_valid(sound_index, sound_type))
1268 {
1269 return nullptr;
1270 }
1271
1272 switch (sound_type)
1273 {
1274 case ST_ADLIB_MUSIC:
1275 return &adlib_music_cache_[sound_index];
1276
1277 case ST_ADLIB_SFX:
1278 return &adlib_sfx_cache_[sound_index];
1279
1280 case ST_PCM:
1281 return &pcm_cache_[sound_index];
1282
1283 default:
1284 return nullptr;
1285 }
1286 }
1287
set_player_channel_state(const Sound & sound,bool state)1288 void AudioMixer::set_player_channel_state(
1289 const Sound& sound,
1290 bool state)
1291 {
1292 if (sound.type == ST_ADLIB_MUSIC)
1293 {
1294 return;
1295 }
1296
1297 if (sound.actor_type != AT_ACTOR)
1298 {
1299 return;
1300 }
1301
1302 if (sound.actor_index > 0)
1303 {
1304 return;
1305 }
1306
1307 int mask = 1 << sound.actor_channel;
1308
1309 if (state)
1310 {
1311 player_channels_state_ |= mask;
1312 }
1313 else
1314 {
1315 player_channels_state_ &= ~mask;
1316 }
1317 }
1318
create_decoder_by_sound_type(SoundType sound_type)1319 AudioDecoder* AudioMixer::create_decoder_by_sound_type(
1320 SoundType sound_type)
1321 {
1322 switch (sound_type)
1323 {
1324 case ST_ADLIB_MUSIC:
1325 return new AdlibMusicDecoder();
1326
1327 case ST_ADLIB_SFX:
1328 return new AdlibSfxDecoder();
1329
1330 case ST_PCM:
1331 return new PcmDecoder();
1332
1333 default:
1334 return nullptr;
1335 }
1336 }
1337
is_sound_type_valid(SoundType sound_type)1338 bool AudioMixer::is_sound_type_valid(
1339 SoundType sound_type)
1340 {
1341 switch (sound_type)
1342 {
1343 case ST_ADLIB_MUSIC:
1344 case ST_ADLIB_SFX:
1345 case ST_PCM:
1346 return true;
1347
1348 default:
1349 return false;
1350 }
1351 }
1352
is_sound_index_valid(int sound_index,SoundType sound_type)1353 bool AudioMixer::is_sound_index_valid(
1354 int sound_index,
1355 SoundType sound_type)
1356 {
1357 switch (sound_type)
1358 {
1359 case ST_ADLIB_MUSIC:
1360 return sound_index >= 0 && sound_index < LASTMUSIC;
1361
1362 case ST_ADLIB_SFX:
1363 case ST_PCM:
1364 return sound_index >= 0 && sound_index < NUMSOUNDS;
1365
1366 default:
1367 return false;
1368 }
1369 }
1370
1371
1372 } // bstone
1373