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