1 #include "sound.h"
2 
3 // max volume factor: means that the interval 0% -> 100% is split in 5
4 int32_t MAX_VOLUME_FACTOR = 5;
5 
6 // General helper that unifies the playing
7 static void play_sound (eSounds sound, int32_t x, int32_t vol, int32_t freq);
8 
9 
10 /** @brief play a weapon or item fire sample according to @a type, panned using @a x.
11   *
12   * This just plays what weapon[]/item[] globals hold for a sound.
13   *
14   * @param[in] type The weapon or item type.
15   * @param[in] x The x-coordinate where the sound is played.
16   * @param[in] vol The volume (0 - 255)
17   * @param[in] freq Frequency, 1000 is normal, 500 is half, 2000 is double and so on.
18 **/
play_fire_sound(int32_t type,int32_t x,int32_t vol,int32_t freq)19 void play_fire_sound(int32_t type, int32_t x, int32_t vol, int32_t freq)
20 {
21 	int32_t sndNum = -1;
22 
23 	if (type >= WEAPONS) {
24 		if (item[type - WEAPONS].sound > -1)
25 			sndNum = item[type - WEAPONS].sound;
26 	} else {
27 		if (weapon[type].sound > -1)
28 			sndNum = weapon[type].sound;
29 	}
30 
31 	if ( (sndNum > -1) && (sndNum < SND_COUNT) )
32 		play_sound(static_cast<eSounds>(sndNum), x, vol, freq);
33 }
34 
35 
36 /** @brief play a weapon or item explosion sample according to @a type, panned using @a x.
37   *
38   * This plays the sound listed in weapon[]/item[] globals unless special rules
39   * apply.
40   *
41   * @param[in] type The weapon or item type.
42   * @param[in] x The x-coordinate where the sound is played.
43   * @param[in] vol The volume (0 - 255)
44   * @param[in] freq Frequency, 1000 is normal, 500 is half, 2000 is double and so on.
45 **/
play_explosion_sound(int32_t type,int32_t x,int32_t vol,int32_t freq)46 void play_explosion_sound(int32_t type, int32_t x, int32_t vol, int32_t freq)
47 {
48 	int32_t sndNum = -1;
49 
50 	if (SHAPED_CHARGE == type)
51 		sndNum = SND_EXPL_SHAPED_CHARGE;
52 	else if (WIDE_BOY == type)
53 		sndNum = SND_EXPL_WIDE_BOY;
54 	else if (CUTTER == type)
55 		sndNum = SND_EXPL_CUTTER;
56 	else if ( (SML_NAPALM <= type) && (LRG_NAPALM >= type)) {
57 		sndNum = SND_EXPL_NAPALM;
58 		freq += 333 * (LRG_NAPALM - type);
59 	} else if (NAPALM_JELLY == type) {
60 		sndNum = SND_EXPL_NAPALM_BURN;
61 		freq  += (rand() % 200) - 100;
62 		vol   -= rand() % 64;
63 	} else if (PERCENT_BOMB == type)
64 		sndNum = SND_EXPL_PER_CENT_BOMB;
65 	else if (REDUCER == type)
66 		sndNum = SND_EXPL_REDUCER;
67 	else if ( ((DIRT_BALL   <= type) && (SMALL_DIRT_SPREAD >= type))
68 	       || ((RIOT_CHARGE <= type) && (RIOT_BLAST        >= type)) )
69 		sndNum = SND_EXPL_DIRT_BALL_BOMB;
70 	else {
71 		// Default handling
72 		if (type >= WEAPONS)
73 			sndNum = item[type - WEAPONS].sound + SND_EXPL_MISS_SML;
74 		else
75 			sndNum = weapon[type].sound + SND_EXPL_MISS_SML;
76 	}
77 
78 	if ( (sndNum > -1) && (sndNum < SND_COUNT) )
79 		play_sound(static_cast<eSounds>(sndNum), x, vol, freq);
80 }
81 
82 
83 /** @brief plays the currently set background music modified by set volume factor
84 **/
play_music()85 void play_music()
86 {
87     if (env.loadBackgroundMusic())
88        play_sound(SND_BG_MUSIC, 128, 255, 1000);
89 }
90 
91 
92 /** @brief play a natural sample according to @a type, panned using @a x.
93   *
94   * @param[in] type The natural type.
95   * @param[in] x The x-coordinate where the sound is played.
96   * @param[in] vol The volume (0 - 255)
97   * @param[in] freq Frequency, 1000 is normal, 500 is half, 2000 is double and so on.
98 **/
99 
play_natural_sound(int32_t type,int32_t x,int32_t vol,int32_t freq)100 void play_natural_sound(int32_t type, int32_t x, int32_t vol, int32_t freq)
101 {
102 	int32_t sndNum = -1;
103 
104 	if (SML_METEOR == type) {
105 		sndNum = naturals[SML_METEOR - WEAPONS].sound;
106 		vol   -= rand() % 128;
107 		freq  += 100 + (rand() % 100);
108 	} else if (MED_METEOR == type) {
109 		sndNum = naturals[MED_METEOR - WEAPONS].sound;
110 		vol   -= rand() % 64;
111 		freq  += rand() % 100;
112 	} else if (LRG_METEOR == type) {
113 		sndNum = naturals[LRG_METEOR - WEAPONS].sound;
114 		vol   -= rand() % 64;
115 		freq  += rand() % 250;
116 	} else if (SML_LIGHTNING == type) {
117 		sndNum = naturals[SML_LIGHTNING - WEAPONS].sound;
118 		vol   -= rand() % 128;
119 		freq  += 100 + (rand() % 100);
120 	} else if (MED_LIGHTNING == type) {
121 		sndNum = naturals[MED_LIGHTNING - WEAPONS].sound;
122 		vol   -= rand() % 64;
123 		freq  += rand() % 100;
124 	} else if (LRG_LIGHTNING == type) {
125 		sndNum = naturals[LRG_LIGHTNING - WEAPONS].sound;
126 		vol   -= rand() % 64;
127 		freq  += rand() % 250;
128 	} else if (DIRT_FRAGMENT == type) {
129 		sndNum = SND_NATU_DIRT_FALL;
130 		vol   -= rand() % 64;
131 		// freq is manipulated by the call
132 	}
133 
134 	if ( (sndNum > -1) && (sndNum < SND_COUNT)
135 	  && ( (SND_NATU_DIRT_FALL != sndNum)
136 		|| (global.used_voices < (env.voices - 8))) )
137 		play_sound(static_cast<eSounds>(sndNum), x, vol, freq);
138 }
139 
140 
141 /** @brief play an interface sample according to @a sound.
142   *
143   * @param[in] sound The sound to play.
144 **/
145 
play_interface_sound(eSounds sound)146 void play_interface_sound(eSounds sound)
147 {
148 	if (SND_INTE_BUTTON_CLICK == sound)
149 		play_sound(sound, env.halfWidth, 128, 1000);
150 }
151 
152 
153 // Global helpers implementation
play_sound(eSounds sound,int32_t x,int32_t vol,int32_t freq)154 static void play_sound(eSounds sound, int32_t x, int32_t vol, int32_t freq)
155 {
156 	if (global.used_voices < env.voices) {
157 		int32_t xVol = (vol * env.volume_factor) / MAX_VOLUME_FACTOR;
158 
159 		if ( (sound < SND_BG_MUSIC)
160 		  && env.sounds[sound]
161 		  && (vol  > 0)
162 		  && (freq > 0) ) {
163 			play_sample(env.sounds[sound],
164 			            xVol,
165 			            x <= 0 ? 31
166 			            : x >= env.screenWidth ? 192
167 			            : 31 + (x * 191 / env.screenWidth),
168 			            freq, false);
169 		} else if (SND_BG_MUSIC == sound)
170 			play_sample(env.background_music, xVol, x, freq, true);
171 
172 		++global.used_voices;
173 	}
174 }
175