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