1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 
24 #include "common/debug.h"
25 #include "common/endian.h"
26 #include "common/textconsole.h"
27 
28 #include "sky/disk.h"
29 #include "sky/logic.h"
30 #include "sky/sky.h"
31 #include "sky/skydefs.h"
32 #include "sky/sound.h"
33 #include "sky/struc.h"
34 
35 #include "audio/audiostream.h"
36 #include "audio/decoders/raw.h"
37 
38 namespace Sky {
39 
40 #define SOUND_FILE_BASE 60203
41 #define MAX_FX_NUMBER 393
42 #define SFXF_START_DELAY 0x80
43 #define SFXF_SAVE 0x20
44 
45 #include "common/pack-start.h"	// START STRUCT PACKING
46 
47 struct RoomList {
48 	uint8 room;
49 	uint8 adlibVolume;
50 	uint8 rolandVolume;
51 } PACKED_STRUCT;
52 
53 struct Sfx {
54 	uint8 soundNo;
55 	uint8 flags;
56 	RoomList roomList[10];
57 } PACKED_STRUCT;
58 
59 #include "common/pack-end.h"	// END STRUCT PACKING
60 
61 uint16 Sound::_speechConvertTable[8] = {
62 	0,									//;Text numbers to file numbers
63 	600,								//; 553 lines in section 0
64 	600+500,							//; 488 lines in section 1
65 	600+500+1330,						//;1303 lines in section 2
66 	600+500+1330+950,					//; 922 lines in section 3
67 	600+500+1330+950+1150,				//;1140 lines in section 4
68 	600+500+1330+950+1150+550,			//; 531 lines in section 5
69 	600+500+1330+950+1150+550+150,		//; 150 lines in section 6
70 };
71 
72 
73 static const Sfx fx_null = {
74 	0,
75 	0,
76 	{
77 		{ 200,127,127 },
78 		{ 255,0,0 }
79 	}
80 };
81 
82 static const Sfx fx_level_3_ping = {
83 	1,
84 	0,
85 	{
86 		{ 28,63,63 },
87 		{ 29,63,63 },
88 		{ 31,63,63 },
89 		{ 255,0,0 },
90 	}
91 };
92 
93 static const Sfx fx_factory_sound = {
94 	1,
95 	SFXF_SAVE,
96 	{
97 		{ 255,30,30 },
98 	}
99 };
100 
101 static const Sfx fx_crowbar_plaster = {
102 	1,
103 	0,
104 	{
105 		{ 255,127,127 },
106 	}
107 };
108 
109 static const Sfx fx_masonry_fall = {
110 	1,
111 	0,
112 	{
113 		{ 255,127,127 },
114 	}
115 };
116 
117 static const Sfx fx_prise_brick = {
118 	2,
119 	0,
120 	{
121 		{ 255,127,127 },
122 	}
123 };
124 
125 static const Sfx fx_rope_creak = {
126 	2,
127 	0,
128 	{
129 		{ 255,127,127 },
130 	}
131 };
132 
133 static const Sfx fx_ping = {
134 	3,
135 	0,
136 	{
137 		{ 255,127,127 },
138 	}
139 };
140 
141 static const Sfx fx_force_fire_door = {
142 	3,
143 	0,
144 	{
145 		{ 255,127,127 },
146 	}
147 };
148 
149 static const Sfx fx_brick_hit_foster = {
150 	3,
151 	10+SFXF_START_DELAY,
152 	{
153 		{ 255,127,127 },
154 	}
155 };
156 
157 static const Sfx fx_brick_hit_plank = {
158 	3,
159 	8+SFXF_START_DELAY,
160 	{
161 		{ 255,127,127 },
162 	}
163 };
164 
165 static const Sfx fx_rm3_lift_moving = {
166 	4,
167 	SFXF_SAVE,
168 	{
169 		{ 3,127,127 },
170 		{ 2,127,127 },
171 		{ 255,0,0 },
172 	}
173 };
174 
175 static const Sfx fx_weld = {
176 	4,
177 	0,
178 	{
179 		{ 15,127,127 },
180 		{ 7,127,127 },
181 		{ 6,60,60 },
182 		{ 12,60,60 },
183 		{ 13,60,60 },
184 		{ 255,0,0 },
185 	}
186 };
187 
188 static const Sfx fx_weld12 = {
189 	4,
190 	0,
191 	{
192 		{ 12,127,127 },
193 		{ 255,0,0 },
194 	}
195 };
196 
197 static const Sfx fx_spray_on_skin = {
198 	4,
199 	0,
200 	{
201 		{ 255,127,127 },
202 	}
203 };
204 
205 static const Sfx fx_plank_vibrating = {
206 	4,
207 	6+SFXF_START_DELAY,
208 	{
209 		{ 255,127,127 },
210 	}
211 };
212 
213 static const Sfx fx_press_bang = {
214 	5,
215 	0,
216 	{
217 		{ 0,50,100 },
218 		{ 255,0,0 },
219 	}
220 };
221 
222 static const Sfx fx_spanner_clunk = {
223 	5,
224 	0,
225 	{
226 		{ 255,127,127 },
227 	}
228 };
229 
230 static const Sfx fx_break_crystals = {
231 	5,
232 	0,
233 	{
234 		{ 96,127,127 },
235 		{ 255,0,0 },
236 	}
237 };
238 
239 static const Sfx fx_press_hiss = {
240 	6,
241 	0,
242 	{
243 		{ 0,40,40 },
244 		{ 255,0,0 },
245 	}
246 };
247 
248 static const Sfx fx_open_door = {
249 	6,
250 	0,
251 	{
252 		{ 255,127,127 },
253 	}
254 };
255 
256 static const Sfx fx_open_lamb_door = {
257 	6,
258 	0,
259 	{
260 		{ 20,127,127 },
261 		{ 21,127,127 },
262 		{ 255,0,0 },
263 	}
264 };
265 
266 static const Sfx fx_splash = {
267 	6,
268 	22+SFXF_START_DELAY,
269 	{
270 		{ 255,127,127 },
271 	}
272 };
273 
274 static const Sfx fx_disintegrate = {
275 	7,
276 	0,
277 	{
278 		{ 255,127,127 },
279 	}
280 };
281 
282 static const Sfx fx_buzzer = {
283 	7,
284 	4+SFXF_START_DELAY,
285 	{
286 		{ 255,127,127 },
287 	}
288 };
289 
290 static const Sfx fx_lathe = {
291 	7,
292 	SFXF_SAVE,
293 	{
294 		{ 4,60,60 },
295 		{ 2,20,20 },
296 		{ 255,0,0 },
297 	}
298 };
299 
300 static const Sfx fx_hit_crowbar_brick = {
301 	7,
302 	9+SFXF_START_DELAY,
303 	{
304 		{ 255,127,127 },
305 	}
306 };
307 
308 static const Sfx fx_hello_helga = {
309 	8,
310 	0,
311 	{
312 		{ 255,127,127 },
313 	}
314 };
315 
316 static const Sfx fx_statue_on_armor = {
317 	8,
318 	0,
319 	{
320 		{ 255,127,127 },
321 	}
322 };
323 
324 static const Sfx fx_lift_alarm = {
325 	8,
326 	SFXF_SAVE,
327 	{
328 		{ 2,63,63 },
329 		{ 255,0,0 },
330 	}
331 };
332 
333 static const Sfx fx_drop_crowbar = {
334 	8,
335 	5+SFXF_START_DELAY,
336 	{
337 		{ 255,127,127 },
338 	}
339 };
340 
341 static const Sfx fx_byee_helga = {
342 	9,
343 	3+SFXF_START_DELAY,
344 	{
345 		{ 255,127,127 },
346 	}
347 };
348 
349 static const Sfx fx_shed_door_creak = {
350 	10,
351 	0,
352 	{
353 		{ 255,127,127 },
354 	}
355 };
356 
357 static const Sfx fx_explosion = {
358 	10,
359 	0,
360 	{
361 		{ 255,127,127 },
362 	}
363 };
364 
365 static const Sfx fx_fire_crackle_in_pit = {
366 	 9,
367 	SFXF_SAVE,
368 	{
369 		{ 255,127,127 },
370 	}
371 };
372 
373 static const Sfx fx_remove_bar_grill = {
374 	10,
375 	7+SFXF_START_DELAY,
376 	{
377 		{ 255,127,127 },
378 	}
379 };
380 
381 static const Sfx fx_grill_creak = {
382 	10,
383 	43+SFXF_START_DELAY,
384 	{
385 		{ 255,127,127 },
386 	}
387 };
388 
389 static const Sfx fx_steam1 = {
390 	11,
391 	SFXF_SAVE,
392 	{
393 		{ 18,20,20 },
394 		{ 255,0,0 },
395 	}
396 };
397 
398 static const Sfx fx_steam2 = {
399 	11,
400 	SFXF_SAVE,
401 	{
402 		{ 18,63,63 },
403 		{ 255,0,0 },
404 	}
405 };
406 
407 static const Sfx fx_steam3 = {
408 	11,
409 	SFXF_SAVE,
410 	{
411 		{ 18,127,127 },
412 		{ 255,0,0 },
413 	}
414 };
415 
416 static const Sfx fx_crowbar_wooden = {
417 	11,
418 	0,
419 	{
420 		{ 255,127,127 },
421 	}
422 };
423 
424 static const Sfx fx_helmet_down_3 = {
425 	11,
426 	0,
427 	{
428 		{ 255,127,127 },
429 	}
430 };
431 
432 static const Sfx fx_guard_fall = {
433 	11,
434 	4,
435 	{
436 		{ 255,127,127 },
437 	}
438 };
439 
440 #if 0
441 static const Sfx fx_furnace = {
442 	11,
443 	0,
444 	{
445 		{ 3,90,90 },
446 		{ 255,0,0 },
447 	}
448 };
449 #endif
450 
451 static const Sfx fx_fall_thru_box = {
452 	12,
453 	0,
454 	{
455 		{ 255,127,127 },
456 	}
457 };
458 
459 static const Sfx fx_lazer = {
460 	12,
461 	0,
462 	{
463 		{ 255,127,127 },
464 	}
465 };
466 
467 static const Sfx fx_scanner = {
468 	12,
469 	0,
470 	{
471 		{ 255,127,127 },
472 	}
473 };
474 
475 static const Sfx fx_helmet_up_3 = {
476 	12,
477 	0,
478 	{
479 		{ 255,127,127 },
480 	}
481 };
482 
483 static const Sfx fx_liquid_bubble = {
484 	12,
485 	SFXF_SAVE,
486 	{
487 		{ 80,127,127 },
488 		{ 72,127,127 },
489 		{ 255,0,0 },
490 	}
491 };
492 
493 static const Sfx fx_liquid_drip = {
494 	13,
495 	6+SFXF_START_DELAY,
496 	{
497 		{ 255,127,127 },
498 	}
499 };
500 
501 static const Sfx fx_goo_drip = {
502 	13,
503 	5+SFXF_START_DELAY,
504 	{
505 		{ 255,127,127 },
506 	}
507 };
508 
509 static const Sfx fx_comp_bleeps = {
510 	13,
511 	0,
512 	{
513 		{ 255,127,127 },
514 	}
515 };
516 
517 static const Sfx fx_use_crowbar_grill = {
518 	13,
519 	34+SFXF_START_DELAY,
520 	{
521 		{ 255,127,127 },
522 	}
523 };
524 
525 static const Sfx fx_helmet_grind = {
526 	14,
527 	0,
528 	{
529 		{ 255,127,127 },
530 	}
531 };
532 
533 static const Sfx fx_lift_moving = {
534 	14,
535 	SFXF_SAVE,
536 	{
537 		{ 7,127,127 },
538 		{ 29,127,127 },
539 		{ 255,0,0 },
540 	}
541 };
542 
543 static const Sfx fx_use_secateurs = {
544 	14,
545 	18+SFXF_START_DELAY,
546 	{
547 		{ 255,127,127 },
548 	}
549 };
550 
551 static const Sfx fx_hit_joey1 = {
552 	14,
553 	7+SFXF_START_DELAY,
554 	{
555 		{ 255,127,127 },
556 	}
557 };
558 
559 static const Sfx fx_hit_joey2 = {
560 	14,
561 	13+SFXF_START_DELAY,
562 	{
563 		{ 255,127,127 },
564 	}
565 };
566 
567 static const Sfx fx_dani_phone_ring = {
568 	15,
569 	0,
570 	{
571 		{ 255,127,127 },
572 	}
573 };
574 
575 static const Sfx fx_sc74_pod_down = {
576 	15,
577 	0,
578 	{
579 		{ 255,127,127 },
580 	}
581 };
582 
583 static const Sfx fx_phone = {
584 	15,
585 	0,
586 	{
587 		{ 255,127,127 },
588 	}
589 };
590 
591 static const Sfx fx_25_weld = {
592 	15,
593 	0,
594 	{
595 		{ 255,127,127 },
596 	}
597 };
598 
599 static const Sfx fx_lift_open_7 = {
600 	15,
601 	0,
602 	{
603 		{ 7,127,127 },
604 		{ 255,0,0 },
605 	}
606 };
607 
608 static const Sfx fx_lift_close_7 = {
609 	16,
610 	0,
611 	{
612 		{ 7,127,127 },
613 		{ 255,0,0 },
614 	}
615 };
616 
617 static const Sfx fx_s2_helmet = {
618 	16,
619 	0,
620 	{
621 		{ 255,127,127 },
622 	}
623 };
624 
625 static const Sfx fx_hiss_in_nitrogen = {
626 	16,
627 	0,
628 	{
629 		{ 255,127,127 },
630 	}
631 };
632 
633 static const Sfx fx_dog_yap_indoors = {
634 	16,
635 	0,
636 	{
637 		{ 38,127,127 },
638 		{ 255,0,0 },
639 	}
640 };
641 
642 static const Sfx fx_dog_yap_outdoors = {
643 	16,
644 	0,
645 	{
646 		{ 31,127,127 },
647 		{ 30,40,40 },
648 		{ 32,40,40 },
649 		{ 33,40,40 },
650 		{ 255,0,0 },
651 	}
652 };
653 
654 static const Sfx fx_locker_creak_open = {
655 	17,
656 	0,
657 	{
658 		{ 255,127,127 },
659 	}
660 };
661 
662 static const Sfx fx_big_tent_gurgle = {
663 	17,
664 	0,
665 	{
666 		{ 255,127,127 },
667 	}
668 };
669 
670 static const Sfx fx_wind_howl = {
671 	17,
672 	SFXF_SAVE,
673 	{
674 		{ 1,127,127 },
675 		{ 255,0,0 },
676 	}
677 };
678 
679 static const Sfx fx_lift_open_29 = {
680 	17,
681 	0,
682 	{
683 		{ 29,127,127 },
684 		{ 255,0,0 },
685 	}
686 };
687 
688 static const Sfx fx_lift_arrive_7 = {
689 	17,
690 	0,
691 	{
692 		{ 7,63,63 },
693 		{ 255,0,0 },
694 	}
695 };
696 
697 static const Sfx fx_lift_close_29 = {
698 	18,
699 	0,
700 	{
701 		{ 29,127,127 },
702 		{ 28,127,127 },
703 		{ 255,0,0 },
704 	}
705 };
706 
707 static const Sfx fx_shaft_industrial_noise = {
708 	18,
709 	SFXF_SAVE,
710 	{
711 		{ 255,127,127 },
712 	}
713 };
714 
715 static const Sfx fx_gall_drop = {
716 	18,
717 	29+SFXF_START_DELAY,
718 	{
719 		{ 255,127,127 },
720 	}
721 };
722 
723 static const Sfx fx_door_slam_under = {
724 	19,
725 	0,
726 	{
727 		{ 255,127,127 },
728 	}
729 };
730 
731 static const Sfx fx_reichs_fish = {
732 	19,
733 	SFXF_SAVE,
734 	{
735 		{ 255,60,60 },
736 	}
737 };
738 
739 static const Sfx fx_judges_gavel1 = {
740 	19,
741 	13+SFXF_START_DELAY,
742 	{
743 		{ 255,60,60 },
744 	}
745 };
746 
747 static const Sfx fx_judges_gavel2 = {
748 	19,
749 	16+SFXF_START_DELAY,
750 	{
751 		{ 255,90,90 },
752 	}
753 };
754 
755 static const Sfx fx_judges_gavel3 = {
756 	19,
757 	19+SFXF_START_DELAY,
758 	{
759 		{ 255,127,127 },
760 	}
761 };
762 
763 static const Sfx fx_wind_3 = {
764 	20,
765 	SFXF_SAVE,
766 	{
767 		{ 255,60,60 },
768 	}
769 };
770 
771 static const Sfx fx_fact_sensor = {
772 	20,
773 	SFXF_SAVE,
774 	{
775 		{ 255,60,60 },
776 	}
777 };
778 
779 static const Sfx fx_medi_stab_gall = {
780 	20,
781 	17+SFXF_START_DELAY,
782 	{
783 		{ 255,127,127 },
784 	}
785 };
786 
787 static const Sfx fx_computer_3 = {
788 	21,
789 	SFXF_SAVE,
790 	{
791 		{ 255,127,127 },
792 	}
793 };
794 
795 static const Sfx fx_timber_cracking = {
796 	21,
797 	0,
798 	{
799 		{ 255,127,127 },
800 	}
801 };
802 
803 static const Sfx fx_anchor_fall = {
804 	22,
805 	0,
806 	{
807 		{ 255,127,127 },
808 	}
809 };
810 
811 static const Sfx fx_elevator_4 = {
812 	22,
813 	0,
814 	{
815 		{ 255,127,127 },
816 	}
817 };
818 
819 static const Sfx fx_star_trek_2 = {
820 	22,
821 	SFXF_SAVE,
822 	{
823 		{ 255,127,127 },
824 	}
825 };
826 
827 static const Sfx fx_lift_closing = {
828 	23,
829 	0,
830 	{
831 		{ 255,127,127 },
832 	}
833 };
834 
835 static const Sfx fx_heartbeat = {
836 	23,
837 	11+SFXF_START_DELAY,
838 	{
839 		{ 67,60,60 },
840 		{ 68,60,60 },
841 		{ 69,60,60 },
842 		{ 77,20,20 },
843 		{ 78,50,50 },
844 		{ 79,70,70 },
845 		{ 80,127,127 },
846 		{ 81,60,60 },
847 		{ 255,0,0 },
848 	}
849 };
850 
851 static const Sfx fx_pos_key = {
852 	25,
853 	2+SFXF_START_DELAY,
854 	{
855 		{ 255,127,127 },
856 	}
857 };
858 
859 static const Sfx fx_neg_key = {
860 	26,
861 	2+SFXF_START_DELAY,
862 	{
863 		{ 255,100,100 },
864 	}
865 };
866 
867 static const Sfx fx_orifice_swallow_drip = {
868 	28,
869 	0,
870 	{
871 		{ 255,127,127 },
872 	}
873 };
874 
875 static const Sfx *const musicList[] = {
876 	&fx_press_bang, // 256 banging of the press
877 	&fx_press_hiss, // 257 hissing press
878 	&fx_wind_howl, // 258 howling wind
879 	&fx_spanner_clunk, // 259 spanner in works
880 	&fx_reichs_fish, // 260 Reichs fish
881 	&fx_explosion, // 261 panel blows open
882 	&fx_wind_3, // 262 single steam
883 	&fx_open_door, // 263 general open door
884 	&fx_open_lamb_door, // 264 lamb door opens
885 	&fx_comp_bleeps, // 265 scanner bleeps
886 	&fx_helmet_down_3, // 266
887 	&fx_helmet_up_3, // 267
888 	&fx_helmet_grind, // 268
889 	&fx_lift_close_29, // 269 rm 29 lift closes
890 	&fx_lift_open_29, // 270 rm 29 lift opens
891 	&fx_computer_3, // 271 rm 29 lift arrives
892 	&fx_level_3_ping, // 272 background noise in room 4
893 	&fx_lift_alarm, // 273 loader alarm
894 	&fx_null, // 274 furnace room background noise
895 	&fx_rm3_lift_moving, // 275 lift moving in room 3
896 	&fx_lathe, // 276 jobsworth lathe
897 	&fx_factory_sound, // 277 factory background sound
898 	&fx_weld, // 278 do some welding
899 	&fx_lift_close_7, // 279 rm 7 lift closes
900 	&fx_lift_open_7, // 280 rm 7 lift opens
901 	&fx_lift_arrive_7, // 281 rm 7 lift arrives
902 	&fx_lift_moving, // 282 lift moving
903 	&fx_scanner, // 283 scanner operating
904 	&fx_force_fire_door, // 284 Force fire door open
905 	&fx_null, // 285 General door creak
906 	&fx_phone, // 286 telephone
907 	&fx_lazer, // 287 lazer
908 	&fx_lazer, // 288 lazer
909 	&fx_anchor_fall, // 289 electric   ;not used on amiga
910 	&fx_weld12, // 290 welding in room 12 (not joey)
911 	&fx_hello_helga, // 291 helga appears
912 	&fx_byee_helga, // 292 helga disapears
913 	&fx_null, // 293 smash through window               ;doesn't exist
914 	&fx_pos_key, // 294
915 	&fx_neg_key, // 295
916 	&fx_s2_helmet, // 296 ;helmet down section 2
917 	&fx_s2_helmet, // 297 ;  "      up    "    "
918 	&fx_lift_arrive_7, // 298 ;security door room 7
919 	&fx_null, // 299
920 	&fx_rope_creak, // 300
921 	&fx_crowbar_wooden, // 301
922 	&fx_fall_thru_box, // 302
923 	&fx_use_crowbar_grill, // 303
924 	&fx_use_secateurs, // 304
925 	&fx_grill_creak, // 305
926 	&fx_timber_cracking, // 306
927 	&fx_masonry_fall, // 307
928 	&fx_masonry_fall, // 308
929 	&fx_crowbar_plaster, // 309
930 	&fx_prise_brick, // 310
931 	&fx_brick_hit_foster, // 311
932 	&fx_spray_on_skin, // 312
933 	&fx_hit_crowbar_brick, // 313
934 	&fx_drop_crowbar, // 314
935 	&fx_fire_crackle_in_pit, // 315
936 	&fx_remove_bar_grill, // 316
937 	&fx_liquid_bubble, // 317
938 	&fx_liquid_drip, // 318
939 	&fx_guard_fall, // 319
940 	&fx_sc74_pod_down, // 320
941 	&fx_hiss_in_nitrogen, // 321
942 	&fx_null, // 322
943 	&fx_hit_joey1, // 323
944 	&fx_hit_joey2, // 324
945 	&fx_medi_stab_gall, // 325
946 	&fx_gall_drop, // 326
947 	&fx_null, // 327
948 	&fx_null, // 328
949 	&fx_null, // 329
950 	&fx_big_tent_gurgle, // 330
951 	&fx_null, // 331
952 	&fx_orifice_swallow_drip, // 332
953 	&fx_brick_hit_plank, // 333
954 	&fx_goo_drip, // 334
955 	&fx_plank_vibrating, // 335
956 	&fx_splash, // 336
957 	&fx_buzzer, // 337
958 	&fx_shed_door_creak, // 338
959 	&fx_dog_yap_outdoors, // 339
960 	&fx_dani_phone_ring, // 340
961 	&fx_locker_creak_open, // 341
962 	&fx_judges_gavel1, // 342
963 	&fx_dog_yap_indoors, // 343
964 	&fx_brick_hit_plank, // 344
965 	&fx_brick_hit_plank, // 345
966 	&fx_shaft_industrial_noise, // 346
967 	&fx_judges_gavel2, // 347
968 	&fx_judges_gavel3, // 348
969 	&fx_elevator_4, // 349
970 	&fx_lift_closing, // 350
971 	&fx_null, // 351
972 	&fx_null, // 352
973 	&fx_sc74_pod_down, // 353
974 	&fx_null, // 354
975 	&fx_null, // 355
976 	&fx_heartbeat, // 356
977 	&fx_star_trek_2, // 357
978 	&fx_null, // 358
979 	&fx_null, // 359
980 	&fx_null, // 350
981 	&fx_null, // 361
982 	&fx_null, // 362
983 	&fx_null, // 363
984 	&fx_null, // 364
985 	&fx_null, // 365
986 	&fx_break_crystals, // 366
987 	&fx_disintegrate, // 367
988 	&fx_statue_on_armor, // 368
989 	&fx_null, // 369
990 	&fx_null, // 360
991 	&fx_ping, // 371
992 	&fx_null, // 372
993 	&fx_door_slam_under, // 373
994 	&fx_null, // 374
995 	&fx_null, // 375
996 	&fx_null, // 376
997 	&fx_null, // 377
998 	&fx_null, // 378
999 	&fx_null, // 379
1000 	&fx_steam1, // 380
1001 	&fx_steam2, // 381
1002 	&fx_steam2, // 382
1003 	&fx_steam3, // 383
1004 	&fx_null, // 384
1005 	&fx_null, // 385
1006 	&fx_fact_sensor, // 386            Sensor in Potts' room
1007 	&fx_null, // 387
1008 	&fx_null, // 388
1009 	&fx_null, // 389
1010 	&fx_null, // 390
1011 	&fx_null, // 391
1012 	&fx_null, // 392
1013 	&fx_null, // 393
1014 	&fx_25_weld // 394            my anchor weld bodge
1015 };
1016 
1017 SfxQueue Sound::_sfxQueue[MAX_QUEUED_FX] = {
1018 	{ 0, 0, 0, 0},
1019 	{ 0, 0, 0, 0},
1020 	{ 0, 0, 0, 0},
1021 	{ 0, 0, 0, 0}
1022 };
1023 
Sound(Audio::Mixer * mixer,Disk * pDisk,uint8 pVolume)1024 Sound::Sound(Audio::Mixer *mixer, Disk *pDisk, uint8 pVolume) {
1025 	_skyDisk = pDisk;
1026 	_soundData = NULL;
1027 	_mixer = mixer;
1028 	_saveSounds[0] = _saveSounds[1] = 0xFFFF;
1029 	_mainSfxVolume = pVolume;
1030 	_isPaused = false;
1031 }
1032 
~Sound()1033 Sound::~Sound() {
1034 	_mixer->stopAll();
1035 	free(_soundData);
1036 }
1037 
playSound(uint32 id,byte * sound,uint32 size,Audio::SoundHandle * handle)1038 void Sound::playSound(uint32 id, byte *sound, uint32 size, Audio::SoundHandle *handle) {
1039 	byte flags = 0;
1040 	flags |= Audio::FLAG_UNSIGNED;
1041 	size -= sizeof(DataFileHeader);
1042 	byte *buffer = (byte *)malloc(size);
1043 	memcpy(buffer, sound+sizeof(DataFileHeader), size);
1044 
1045 	_mixer->stopID(id);
1046 
1047 	Audio::AudioStream *stream = Audio::makeRawStream(buffer, size, 11025, flags);
1048 	_mixer->playStream(Audio::Mixer::kSFXSoundType, handle, stream, id);
1049 }
1050 
loadSection(uint8 pSection)1051 void Sound::loadSection(uint8 pSection) {
1052 	fnStopFx();
1053 	_mixer->stopAll();
1054 
1055 	free(_soundData);
1056 	_soundData = _skyDisk->loadFile(pSection * 4 + SOUND_FILE_BASE);
1057 	uint16 asmOfs;
1058 	if (SkyEngine::_systemVars.gameVersion == 109) {
1059 		if (pSection == 0)
1060 			asmOfs = 0x78;
1061 		else
1062 			asmOfs = 0x7C;
1063 	} else
1064 		asmOfs = 0x7E;
1065 
1066 	if ((_soundData[asmOfs] != 0x3C) || (_soundData[asmOfs + 0x27] != 0x8D) ||
1067 		(_soundData[asmOfs + 0x28] != 0x1E) || (_soundData[asmOfs + 0x2F] != 0x8D) ||
1068 		(_soundData[asmOfs + 0x30] != 0x36))
1069 			error("Unknown sounddriver version");
1070 
1071 	_soundsTotal = _soundData[asmOfs + 1];
1072 	uint16 sRateTabOfs = READ_LE_UINT16(_soundData + asmOfs + 0x29);
1073 	_sfxBaseOfs = READ_LE_UINT16(_soundData + asmOfs + 0x31);
1074 	_sampleRates = _soundData + sRateTabOfs;
1075 
1076 	_sfxInfo = _soundData + _sfxBaseOfs;
1077 	// if we just restored a savegame, the sfxqueue holds the sound we need to restart
1078 	if (!(SkyEngine::_systemVars.systemFlags & SF_GAME_RESTORED))
1079 		for (uint8 cnt = 0; cnt < 4; cnt++)
1080 			_sfxQueue[cnt].count = 0;
1081 }
1082 
playSound(uint16 sound,uint16 volume,uint8 channel)1083 void Sound::playSound(uint16 sound, uint16 volume, uint8 channel) {
1084 	if (channel == 0)
1085 		_mixer->stopID(SOUND_CH0);
1086 	else
1087 		_mixer->stopID(SOUND_CH1);
1088 
1089 	if (!_soundData) {
1090 		warning("Sound::playSound(%04X, %04X) called with a section having been loaded", sound, volume);
1091 		return;
1092 	}
1093 
1094 	if (sound > _soundsTotal) {
1095 		debug(5, "Sound::playSound %d ignored, only %d sfx in file", sound, _soundsTotal);
1096 		return;
1097 	}
1098 
1099 	volume = (volume & 0x7F) << 1;
1100 	sound &= 0xFF;
1101 
1102 	// Note: All those tables are big endian. Don't ask me why. *sigh*
1103 
1104 	// Use the sample rate from game data, see bug #1507757.
1105 	uint16 sampleRate = READ_BE_UINT16(_sampleRates + (sound << 2));
1106 	if (sampleRate > 11025)
1107 		sampleRate = 11025;
1108 	uint32 dataOfs  = READ_BE_UINT16(_sfxInfo + (sound << 3) + 0) << 4;
1109 	uint32 dataSize = READ_BE_UINT16(_sfxInfo + (sound << 3) + 2);
1110 	uint32 dataLoop = READ_BE_UINT16(_sfxInfo + (sound << 3) + 6);
1111 	dataOfs += _sfxBaseOfs;
1112 
1113 	Audio::SeekableAudioStream *stream = Audio::makeRawStream(_soundData + dataOfs, dataSize, sampleRate,
1114 	                                                                Audio::FLAG_UNSIGNED, DisposeAfterUse::NO);
1115 
1116 	Audio::AudioStream *output = 0;
1117 	if (dataLoop) {
1118 		uint32 loopSta = dataSize - dataLoop;
1119 		uint32 loopEnd = dataSize;
1120 
1121 		output = Audio::makeLoopingAudioStream(stream, Audio::Timestamp(0, loopSta, sampleRate),
1122 		                                       Audio::Timestamp(0, loopEnd, sampleRate), 0);
1123 	} else {
1124 		output = stream;
1125 	}
1126 
1127 	if (channel == 0)
1128 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_ingameSound0, output, SOUND_CH0, volume, 0);
1129 	else
1130 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_ingameSound1, output, SOUND_CH1, volume, 0);
1131 }
1132 
fnStartFx(uint32 sound,uint8 channel)1133 void Sound::fnStartFx(uint32 sound, uint8 channel) {
1134 	_saveSounds[channel] = 0xFFFF;
1135 	if (sound < 256 || sound > MAX_FX_NUMBER || (SkyEngine::_systemVars.systemFlags & SF_FX_OFF))
1136 		return;
1137 
1138 	uint8 screen = (uint8)(Logic::_scriptVariables[SCREEN] & 0xff);
1139 	if (sound == 278 && screen == 25) // is this weld in room 25
1140 		sound= 394;
1141 
1142 	sound &= ~(1 << 8);
1143 
1144 	const Sfx *sfx = musicList[sound];
1145 	const RoomList *roomList = sfx->roomList;
1146 
1147 	int i = 0;
1148 	if (roomList[i].room != 0xff) // if room list empty then do all rooms
1149 		while (roomList[i].room != screen) { // check rooms
1150 			i++;
1151 			if (roomList[i].room == 0xff)
1152 				return;
1153 		}
1154 
1155 	// get fx volume
1156 
1157 	uint8 volume = _mainSfxVolume; // start with standard vol
1158 
1159 	if (SkyEngine::_systemVars.systemFlags & SF_SBLASTER)
1160 		volume = roomList[i].adlibVolume;
1161 	else if (SkyEngine::_systemVars.systemFlags & SF_ROLAND)
1162 		volume = roomList[i].rolandVolume;
1163 	volume = (volume * _mainSfxVolume) >> 8;
1164 
1165 	// Check the flags, the sound may come on after a delay.
1166 	if (sfx->flags & SFXF_START_DELAY) {
1167 		for (uint8 cnt = 0; cnt < MAX_QUEUED_FX; cnt++) {
1168 			if (_sfxQueue[cnt].count == 0) {
1169 				_sfxQueue[cnt].chan = channel;
1170 				_sfxQueue[cnt].fxNo = sfx->soundNo;
1171 				_sfxQueue[cnt].vol = volume;
1172 				_sfxQueue[cnt].count = sfx->flags & 0x7F;
1173 				return;
1174 			}
1175 		}
1176 		return; // ignore sound if it can't be queued
1177 	}
1178 
1179 	if (sfx->flags & SFXF_SAVE)
1180 		_saveSounds[channel] = sfx->soundNo | (volume << 8);
1181 
1182 	playSound(sfx->soundNo, volume, channel);
1183 }
1184 
checkFxQueue()1185 void Sound::checkFxQueue() {
1186 	for (uint8 cnt = 0; cnt < MAX_QUEUED_FX; cnt++) {
1187 		if (_sfxQueue[cnt].count) {
1188 			_sfxQueue[cnt].count--;
1189 			if (_sfxQueue[cnt].count == 0)
1190 				playSound(_sfxQueue[cnt].fxNo, _sfxQueue[cnt].vol, _sfxQueue[cnt].chan);
1191 		}
1192 	}
1193 }
1194 
restoreSfx()1195 void Sound::restoreSfx() {
1196 	// queue sfx, so they will be started when the player exits the control panel
1197 	memset(_sfxQueue, 0, sizeof(_sfxQueue));
1198 	uint8 queueSlot = 0;
1199 	if (_saveSounds[0] != 0xFFFF) {
1200 		_sfxQueue[queueSlot].fxNo = (uint8)_saveSounds[0];
1201 		_sfxQueue[queueSlot].vol = (uint8)(_saveSounds[0] >> 8);
1202 		_sfxQueue[queueSlot].chan = 0;
1203 		_sfxQueue[queueSlot].count = 1;
1204 		queueSlot++;
1205 	}
1206 	if (_saveSounds[1] != 0xFFFF) {
1207 		_sfxQueue[queueSlot].fxNo = (uint8)_saveSounds[1];
1208 		_sfxQueue[queueSlot].vol = (uint8)(_saveSounds[1] >> 8);
1209 		_sfxQueue[queueSlot].chan = 1;
1210 		_sfxQueue[queueSlot].count = 1;
1211 	}
1212 }
1213 
fnStopFx()1214 void Sound::fnStopFx() {
1215 	_mixer->stopID(SOUND_CH0);
1216 	_mixer->stopID(SOUND_CH1);
1217 	_saveSounds[0] = _saveSounds[1] = 0xFFFF;
1218 }
1219 
stopSpeech()1220 void Sound::stopSpeech() {
1221 	_mixer->stopID(SOUND_SPEECH);
1222 }
1223 
startSpeech(uint16 textNum)1224 bool Sound::startSpeech(uint16 textNum) {
1225 	if (!(SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH))
1226 		return false;
1227 	uint16 speechFileNum = _speechConvertTable[textNum >> 12] + (textNum & 0xFFF);
1228 
1229 	uint8 *speechData = _skyDisk->loadFile(speechFileNum + 50000);
1230 	if (!speechData) {
1231 		debug(9,"File %d (speechFile %d from section %d) wasn't found", speechFileNum + 50000, textNum & 0xFFF, textNum >> 12);
1232 		return false;
1233 	}
1234 
1235 	uint32 speechSize = ((DataFileHeader *)speechData)->s_tot_size - sizeof(DataFileHeader);
1236 	uint8 *playBuffer = (uint8 *)malloc(speechSize);
1237 	memcpy(playBuffer, speechData + sizeof(DataFileHeader), speechSize);
1238 
1239 	free(speechData);
1240 
1241 	// Workaround for BASS bug #897775 - some voice-overs are played at
1242 	// half speed in 0.0368 (the freeware CD version), in 0.0372 they sound
1243 	// just fine.
1244 
1245 	uint rate;
1246 	if (_skyDisk->determineGameVersion() == 368 && (textNum == 20905 || textNum == 20906))
1247 		rate = 22050;
1248 	else
1249 		rate = 11025;
1250 
1251 	_mixer->stopID(SOUND_SPEECH);
1252 
1253 	Audio::AudioStream *stream = Audio::makeRawStream(playBuffer, speechSize, rate, Audio::FLAG_UNSIGNED);
1254 	_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_ingameSpeech, stream, SOUND_SPEECH);
1255 	return true;
1256 }
1257 
fnPauseFx()1258 void Sound::fnPauseFx() {
1259 	if (!_isPaused) {
1260 		_isPaused = true;
1261 		_mixer->pauseID(SOUND_CH0, true);
1262 		_mixer->pauseID(SOUND_CH1, true);
1263 	}
1264 }
1265 
fnUnPauseFx()1266 void Sound::fnUnPauseFx() {
1267 	if (_isPaused) {
1268 		_isPaused = false;
1269 		_mixer->pauseID(SOUND_CH0, false);
1270 		_mixer->pauseID(SOUND_CH1, false);
1271 	}
1272 }
1273 
1274 } // End of namespace Sky
1275