CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

AUDIO.CPP (31150B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\audio.cpv   2.17   16 Oct 1995 16:50:20   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : AUDIO.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : September 10, 1993                                           *
     28  *                                                                                             *
     29  *                  Last Update : May 4, 1995 [JLB]                                            *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Is_Speaking -- Checks to see if the eva voice is still playing.                           *
     34  *   Sound_Effect -- General purpose sound player.                                             *
     35  *   Sound_Effect -- Plays a sound effect in the tactical map.                                 *
     36  *   Speak -- Computer speaks to the player.                                                   *
     37  *   Speak_AI -- Handles starting the EVA voices.                                              *
     38  *   Stop_Speaking -- Forces the EVA voice to stop talking.                                    *
     39  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     40 
     41 #include	"function.h"
     42 
     43 
     44 
     45 
     46 /*
     47 ** 
     48 ** 
     49 ** Win32lib stubs
     50 ** 
     51 ** 
     52 ** 
     53 */
     54 
     55 
     56 SFX_Type					SoundType;
     57 Sample_Type				SampleType;
     58 
     59 int File_Stream_Sample(char const *filename, BOOL real_time_start) {return 1;};
     60 int File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start)  {return 1;};
     61 void __cdecl Sound_Callback(void) {};
     62 void __cdecl far maintenance_callback(void) {};
     63 void *Load_Sample(char const *filename) {return NULL;};
     64 long Load_Sample_Into_Buffer(char const *filename, void *buffer, long size) {return 0;}
     65 long Sample_Read(int fh, void *buffer, long size) {return 0;};
     66 void Free_Sample(void const *sample) {};
     67 BOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels) {return 0;};
     68 void Sound_End(void) {};
     69 void Stop_Sample(int handle) {};
     70 BOOL Sample_Status(int handle) {return 0;};
     71 BOOL Is_Sample_Playing(void const * sample) {return 0;};
     72 void Stop_Sample_Playing(void const * sample) {};
     73 int Play_Sample(void const *sample, int priority, int volume, signed short panloc) {return 1;};
     74 int Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id) {return 1;};
     75 int Set_Sound_Vol(int volume) {return 0;};
     76 int Set_Score_Vol(int volume) {return 0;};
     77 void Fade_Sample(int handle, int ticks) {};
     78 int Get_Free_Sample_Handle(int priority) {return 1;};
     79 int Get_Digi_Handle(void) {return 1;}
     80 long Sample_Length(void const *sample) {return 0;};
     81 void Restore_Sound_Buffers (void) {};
     82 BOOL Set_Primary_Buffer_Format(void) {return 0;};
     83 BOOL Start_Primary_Sound_Buffer (BOOL forced) {return 0;};
     84 void Stop_Primary_Sound_Buffer (void) {};
     85 
     86 
     87 
     88 
     89 
     90 
     91 
     92 
     93 
     94 
     95 
     96 
     97 /***************************************************************************
     98 **	Controls what special effects may occur on the sound effect.
     99 */
    100 typedef enum {
    101 	IN_NOVAR,			// No variation or alterations allowed.
    102 	IN_JUV,				// Juvenile sound effect alternate option.
    103 	IN_VAR,				// Infantry variance response modification.
    104 } ContextType;
    105 
    106 // static struct { // MBL 02.21.2019
    107 // Had to name the struct for VS 2017 distributed build. ST - 4/10/2019 3:59PM
    108 struct SoundEffectNameStruct {
    109 	char const *Name;		// Digitized voice file name.
    110 	int			Priority;	// Playback priority of this sample.
    111 	ContextType	Where;		// In what game context does this sample exist.
    112 } SoundEffectName[VOC_COUNT] = {
    113 
    114 	/*
    115 	**	Special voices (typically associated with the commando).
    116 	*/
    117 	{"BOMBIT1",		20, IN_NOVAR},		//	VOC_RAMBO_PRESENT		"I've got a present for	ya"
    118 	{"CMON1",		20, IN_NOVAR},		//	VOC_RAMBO_CMON			"c'mon"
    119 	{"GOTIT1",		20, IN_NOVAR},		//	VOC_RAMBO_UGOTIT		"you got it" *
    120 	{"KEEPEM1",		20, IN_NOVAR},		//	VOC_RAMBO_COMIN		"keep 'em commin'"
    121 	{"LAUGH1",		20, IN_NOVAR},		//	VOC_RAMBO_LAUGH		"hahaha"
    122 	{"LEFTY1",		20, IN_NOVAR},		//	VOC_RAMBO_LEFTY		"that was left handed" *
    123 	{"NOPRBLM1",	20, IN_NOVAR},		//	VOC_RAMBO_NOPROB		"no problem"
    124 //	{"OHSH1",		20, IN_NOVAR},		//	VOC_RAMBO_OHSH			"oh shiiiiii...."
    125 	{"ONIT1",		20, IN_NOVAR},		//	VOC_RAMBO_ONIT			"I'm on it"
    126 	{"RAMYELL1",	20, IN_NOVAR},		//	VOC_RAMBO_YELL			"ahhhhhhh"
    127 	{"ROKROLL1",	20, IN_NOVAR},		//	VOC_RAMBO_ROCK			"time to rock and roll"
    128 	{"TUFFGUY1",	20, IN_NOVAR},		//	VOC_RAMBO_TUFF			"real tuff guy" *
    129 	{"YEAH1",		20, IN_NOVAR},		//	VOC_RAMBO_YEA			"yea" *
    130 	{"YES1",			20, IN_NOVAR},		//	VOC_RAMBO_YES			"yes" *
    131 	{"YO1",			20, IN_NOVAR},		//	VOC_RAMBO_YO			"yo"
    132 
    133 	/*
    134 	**	Civilian voices (technicians too).
    135 	*/
    136 	{"GIRLOKAY",	20, IN_NOVAR},		//	VOC_GIRL_OKAY
    137 	{"GIRLYEAH",	20, IN_NOVAR},		//	VOC_GIRL_YEAH
    138 	{"GUYOKAY1",	20, IN_NOVAR},		//	VOC_GUY_OKAY
    139 	{"GUYYEAH1",	20, IN_NOVAR},		//	VOC_GUY_YEAH
    140 
    141 	/*
    142 	**	Infantry and vehicle responses.
    143 	*/
    144 	{"2DANGR1",		10,	IN_VAR},	//	VOC_2DANGER			"negative, too dangerous"
    145 	{"ACKNO",		10,	IN_VAR},	//	VOC_ACKNOWL			"acknowledged"
    146 	{"AFFIRM1",		10,	IN_VAR},	//	VOC_AFFIRM			"affirmative"
    147 	{"AWAIT1",		10,	IN_VAR},	//	VOC_AWAIT1			"awaiting orders"
    148 //	{"BACKUP",		10,	IN_VAR},	// VOC_BACKUP			"send backup"
    149 //	{"HELP",			10,	IN_VAR},	// VOC_HELP				"send help"
    150 	{"MOVOUT1",		10,	IN_VAR},	//	VOC_MOVEOUT			"movin' out"
    151 	{"NEGATV1",		10,	IN_VAR},	//	VOC_NEGATIVE		"negative"
    152 	{"NOPROB",		10,	IN_VAR},	// VOC_NO_PROB			"not a problem"
    153 	{"READY",		10,	IN_VAR},	// VOC_READY			"ready and waiting"
    154 	{"REPORT1",		10,	IN_VAR},	//	VOC_REPORT			"reporting"
    155 	{"RITAWAY",		10,	IN_VAR},	// VOC_RIGHT_AWAY		"right away sir"
    156 	{"ROGER",		10,	IN_VAR},	// VOC_ROGER			"roger"
    157 //	{"SIR1",			10,	IN_VAR},	//	VOC_SIR1				"sir?"
    158 //	{"SQUAD1",		10,	IN_VAR},	//	VOC_SQUAD1			"squad reporting"
    159 //	{"TARGET1",		10,	IN_VAR},	//	VOC_PRACTICE		"target practice"
    160 	{"UGOTIT",		10,	IN_VAR},	// VOC_UGOTIT			"you got it"
    161 	{"UNIT1",		10,	IN_VAR},	//	VOC_UNIT1			"unit reporting"
    162 	{"VEHIC1",		10,	IN_VAR},	//	VOC_VEHIC1			"vehicle reporting"
    163 	{"YESSIR1",		10,	IN_VAR},	//	VOC_YESSIR			"yes sir"
    164 
    165 	/*
    166 	**	Sound effects that have a juvenile counterpart.
    167 	*/
    168 	{"BAZOOK1", 	1,		IN_JUV},	// VOC_BAZOOKA			Gunfire
    169 	{"BLEEP2", 		1,		IN_JUV},	// VOC_BLEEP			Clean metal bing
    170 	{"BOMB1", 		1,		IN_JUV},	// VOC_BOMB1			Crunchy parachute bomb type explosion
    171 	{"BUTTON", 		1,		IN_JUV},	// VOC_BUTTON			Dungeon Master button click
    172 	{"COMCNTR1",	10,	IN_JUV},	// VOC_RADAR_ON		Elecronic static with beeps
    173 	{"CONSTRU2",	10,	IN_JUV},	// VOC_CONSTRUCTION	construction sounds
    174 	{"CRUMBLE", 	1,		IN_JUV},	// VOC_CRUMBLE			muffled crumble sound
    175 	{"FLAMER2", 	4,		IN_JUV},	// VOC_FLAMER1			flame thrower
    176 	{"GUN18",		4, 	IN_JUV},	// VOC_RIFLE			rifle shot
    177 	{"GUN19",		4, 	IN_JUV},	// VOC_M60				machine gun burst -- 6 rounds
    178 	{"GUN20",		4, 	IN_JUV},	// VOC_GUN20			bat hitting heavy metal door
    179 	{"GUN5",			4, 	IN_JUV},	// VOC_M60A				medium machine gun burst
    180 	{"GUN8",			4, 	IN_JUV},	// VOC_MINI				mini gun burst
    181 	{"GUNCLIP1",	1, 	IN_JUV},	// VOC_RELOAD			gun clip reload
    182 	{"HVYDOOR1", 	5,		IN_JUV},	// VOC_SLAM				metal plates slamming together
    183 	{"HVYGUN10",	1,		IN_JUV},	//	VOC_HVYGUN10		loud sharp cannon
    184 	{"ION1", 		1,		IN_JUV},	// VOC_ION_CANNON		partical beam
    185 	{"MGUN11", 		1,		IN_JUV},	// VOC_MGUN11			alternate tripple burst
    186 	{"MGUN2", 		1,		IN_JUV},	// VOC_MGUN2			M-16 tripple burst
    187 	{"NUKEMISL",	1,		IN_JUV},	//	VOC_NUKE_FIRE		long missile sound
    188 	{"NUKEXPLO",	1,		IN_JUV},	//	VOC_NUKE_EXPLODE	long but not loud explosion
    189 	{"OBELRAY1",	1,		IN_JUV},	//	VOC_LASER			humming laser beam
    190 	{"OBELPOWR",	1,		IN_JUV},	// VOC_LASER_POWER	warming-up sound of laser beam
    191 	{"POWRDN1",		1,		IN_JUV},	//	VOC_RADAR_OFF		doom door slide
    192 	{"RAMGUN2",		1,		IN_JUV},	//	VOC_SNIPER			silenced rifle fire
    193 	{"ROCKET1",		1,		IN_JUV},	//	VOC_ROCKET1			rocket launch variation #1
    194 	{"ROCKET2",		1,		IN_JUV},	//	VOC_ROCKET2			rocket launch variation #2
    195 	{"SAMMOTR2",	1, 	IN_JUV},	// VOC_MOTOR			dentists drill
    196 	{"SCOLD2",		1, 	IN_JUV},	// VOC_SCOLD			cannot perform action feedback tone
    197 	{"SIDBAR1C", 	1,		IN_JUV},	// VOC_SIDEBAR_OPEN	xylophone clink
    198 	{"SIDBAR2C", 	1,		IN_JUV},	// VOC_SIDEBAR_CLOSE	xylophone clink
    199 	{"SQUISH2", 	1,		IN_JUV},	// VOC_SQUISH2			crushing infantry
    200 	{"TNKFIRE2",	1, 	IN_JUV},	// VOC_TANK1			sharp tank fire with recoil
    201 	{"TNKFIRE3",	1, 	IN_JUV},	// VOC_TANK2			sharp tank fire
    202 	{"TNKFIRE4",	1, 	IN_JUV},	// VOC_TANK3			sharp tank fire
    203 	{"TNKFIRE6",	1, 	IN_JUV},	// VOC_TANK4			big gun tank fire
    204 	{"TONE15",		0, 	IN_JUV},	// VOC_UP				credits counting up
    205 	{"TONE16",		0, 	IN_JUV},	// VOC_DOWN				credits counting down
    206 	{"TONE2",		1, 	IN_JUV},	// VOC_TARGET			target sound
    207 	{"TONE5",		10,	IN_JUV},	// VOC_SONAR			sonar echo
    208 	{"TOSS",			1, 	IN_JUV},	// VOC_TOSS				air swish
    209 	{"TRANS1",		1, 	IN_JUV},	// VOC_CLOAK			stealth tank
    210 	{"TREEBRN1",	1, 	IN_JUV},	// VOC_BURN				burning crackle
    211 	{"TURRFIR5",	1, 	IN_JUV},	// VOC_TURRET			muffled gunfire
    212 	{"XPLOBIG4",	5,		IN_JUV},	//	VOC_XPLOBIG4		very long muffled explosion
    213 	{"XPLOBIG6",	5,		IN_JUV},	//	VOC_XPLOBIG6		very long muffled explosion
    214 	{"XPLOBIG7",	5,		IN_JUV},	//	VOC_XPLOBIG7		very long muffled explosion
    215 	{"XPLODE",		1,		IN_JUV},	// VOC_XPLODE			long soft muffled explosion
    216 	{"XPLOS",		4, 	IN_JUV},	// VOC_XPLOS			short crunchy explosion
    217 	{"XPLOSML2",	5,		IN_JUV},	//	VOC_XPLOSML2		muffled mechanical explosion
    218 
    219 	/*
    220 	**	Generic sound effects (no variations).
    221 	*/
    222 	{"NUYELL1", 	10,	IN_NOVAR},	// VOC_SCREAM1			short infantry scream
    223 	{"NUYELL3", 	10,	IN_NOVAR},	// VOC_SCREAM3			short infantry scream
    224 	{"NUYELL4", 	10,	IN_NOVAR},	// VOC_SCREAM4			short infantry scream
    225 	{"NUYELL5", 	10,	IN_NOVAR},	// VOC_SCREAM5			short infantry scream
    226 	{"NUYELL6", 	10,	IN_NOVAR},	// VOC_SCREAM6			short infantry scream
    227 	{"NUYELL7", 	10,	IN_NOVAR},	// VOC_SCREAM7			short infantry scream
    228 	{"NUYELL10", 	10,	IN_NOVAR},	// VOC_SCREAM10		short infantry scream
    229 	{"NUYELL11", 	10,	IN_NOVAR},	// VOC_SCREAM11		short infantry scream
    230 	{"NUYELL12", 	10,	IN_NOVAR},	// VOC_SCREAM12		short infantry scream
    231 	{"YELL1", 		1,		IN_NOVAR},	// VOC_YELL1			long infantry scream
    232 
    233 	{"MYES1", 		10,	IN_NOVAR},	// VOC_YES				"Yes?"
    234 	{"MCOMND1", 	10,	IN_NOVAR},	// VOC_COMMANDER		"Commander?"
    235 	{"MHELLO1", 	10,	IN_NOVAR},	//	VOC_HELLO			"Hello?"
    236 	{"MHMMM1", 		10,	IN_NOVAR},	//	VOC_HMMM				"Hmmm?"
    237 //	{"MHASTE1", 	10,	IN_NOVAR},	//	VOC_PROCEED1		"I will proceed, post haste."
    238 //	{"MONCE1", 		10,	IN_NOVAR},	//	VOC_PROCEED2		"I will proceed, at once."
    239 //	{"MIMMD1", 		10,	IN_NOVAR},	//	VOC_PROCEED3		"I will proceed, immediately."
    240 //	{"MPLAN1", 		10,	IN_NOVAR},	//	VOC_EXCELLENT1		"That is an excellent plan."
    241 //	{"MPLAN2", 		10,	IN_NOVAR},	//	VOC_EXCELLENT2		"Yes, that is an excellent plan."
    242 	{"MPLAN3", 		10,	IN_NOVAR},	//	VOC_EXCELLENT3		"A wonderful plan."
    243 //	{"MACTION1", 	10,	IN_NOVAR},	//	VOC_EXCELLENT4		"Astounding plan of action commander."
    244 //	{"MREMARK1", 	10,	IN_NOVAR},	// VOC_EXCELLENT5		"Remarkable contrivance."
    245 	{"MCOURSE1", 	10,	IN_NOVAR},	// VOC_OF_COURSE		"Of course."
    246 	{"MYESYES1", 	10,	IN_NOVAR},	// VOC_YESYES			"Yes yes yes."
    247 	{"MTIBER1", 	10,	IN_NOVAR},	//	VOC_QUIP1			"Mind the Tiberium."
    248 //	{"MMG1", 		10,	IN_NOVAR},	//	VOC_QUIP2			"A most remarkable  Metasequoia Glyptostroboides."
    249 	{"MTHANKS1", 	10,	IN_NOVAR},	//	VOC_THANKS			"Thank you."
    250 
    251 	{"CASHTURN", 	1,		IN_NOVAR},	//	VOC_CASHTURN		Sound of money being piled up.
    252 	{"BLEEP2", 		10,	IN_NOVAR},	//	VOC_BLEEPY3			Clean computer bleep sound.
    253 	{"DINOMOUT", 	10,	IN_NOVAR},	//	VOC_DINOMOUT		Movin' out in dino-speak.
    254 	{"DINOYES", 	10,	IN_NOVAR},	//	VOC_DINOYES			Yes Sir in dino-speak.
    255 	{"DINOATK1", 	10,	IN_NOVAR},	//	VOC_DINOATK1		Dino attack sound.
    256 	{"DINODIE1", 	10,	IN_NOVAR},	//	VOC_DINODIE1		Dino die sound.
    257 	{"BEACON", 		10,	IN_NOVAR },	//	VOC_BEACON			Beacon sound.
    258 
    259 #ifdef PETROGLYPH_EXAMPLE_MOD
    260 	{"NUKE_LOB", 	10,	IN_NOVAR}	//	VOC_NUKE_LOB		Mod expansion unit firing sound
    261 #endif //PETROGLYPH_EXAMPLE_MOD
    262 
    263 };
    264 
    265 
    266 //
    267 // External handlers. ST - 2/20/2019 3:41PM
    268 //
    269 extern void On_Sound_Effect(int sound_index, int variation, COORDINATE coord);
    270 // extern void On_Speech(int speech_index); // MBL 02.06.2020
    271 extern void On_Speech(int speech_index, HouseClass *house);
    272 extern void On_Ping(const HouseClass* player_ptr, COORDINATE coord);
    273 
    274 /***********************************************************************************************
    275  * Sound_Effect -- Plays a sound effect in the tactical map.                                   *
    276  *                                                                                             *
    277  *    This routine is used when a sound effect occurs in the game world. It handles fading     *
    278  *    the sound according to distance.                                                         *
    279  *                                                                                             *
    280  * INPUT:   voc   -- The sound effect number to play.                                          *
    281  *                                                                                             *
    282  *          coord -- The world location that the sound originates from.                        *
    283  *                                                                                             *
    284  * OUTPUT:  none                                                                               *
    285  *                                                                                             *
    286  * WARNINGS:   none                                                                            *
    287  *                                                                                             *
    288  * HISTORY:                                                                                    *
    289  *   11/12/1994 JLB : Created.                                                                 *
    290  *   01/05/1995 JLB : Reduces sound more dramatically when off screen.                         *
    291  *=============================================================================================*/
    292 void Sound_Effect(VocType voc, COORDINATE coord, int variation)
    293 {
    294 	//
    295 	// Intercept sound effect calls. ST - 2/20/2019 3:37PM
    296 	//
    297 	On_Sound_Effect((int)voc, variation, coord);
    298 			
    299 #if (0)			
    300 	unsigned			distance;
    301 	CELL				cell_pos;
    302 	int pan_value;
    303 
    304 	if (!Options.Volume || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
    305 		return;
    306 	}
    307 	if (coord) {
    308 		cell_pos = Coord_Cell(coord);
    309 	}
    310 
    311 	distance  = 0xFF;
    312 	pan_value = 0;
    313 	if (coord && !Map.In_View(cell_pos)) {
    314 		distance = Map.Cell_Distance(cell_pos, Coord_Cell(Map.TacticalCoord));
    315 		distance = (unsigned int)MIN((int)distance, (int)MAP_CELL_W);
    316 		distance = Cardinal_To_Fixed(MAP_CELL_W, distance);
    317 		distance = MIN(distance, 0xFFu);
    318 		distance ^= 0xFF;
    319 
    320 		distance /= 2;
    321 		distance = MAX(distance, 25U);
    322 
    323 		pan_value  = Cell_X(cell_pos);
    324 		pan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) >> 1);
    325 		if (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth >> 1)) {
    326 			pan_value *= 0x8000;
    327 			pan_value /= (MAP_CELL_W >> 2);
    328 			pan_value = Bound(pan_value, -0x7FFF, 0x7FFF);
    329 //			pan_value  = MAX((int)pan_value, (int)-0x7FFF);
    330 //			pan_value  = MIN((int)pan_value, 0x7FFF);
    331 		} else {
    332 			pan_value  = 0;
    333 		}
    334 	}
    335 
    336 	Sound_Effect(voc, (VolType)Fixed_To_Cardinal(distance, Options.Volume), variation, pan_value);
    337 #endif
    338 }
    339 
    340 
    341 /***********************************************************************************************
    342  * Sound_Effect -- General purpose sound player.                                               *
    343  *                                                                                             *
    344  *    This is used for general purpose sound effects. These are sounds that occur outside      *
    345  *    of the game world. They do not have a corresponding game world location as their source. *
    346  *                                                                                             *
    347  * INPUT:   voc      -- The sound effect number to play.                                       *
    348  *                                                                                             *
    349  *          volume   -- The volume to assign to this sound effect.                             *
    350  *                                                                                             *
    351  * OUTPUT:  Returns with the sound handle (-1 if no sound was played).                         *
    352  *                                                                                             *
    353  * WARNINGS:   none                                                                            *
    354  *                                                                                             *
    355  * HISTORY:                                                                                    *
    356  *   11/12/1994 JLB : Created.                                                                 *
    357  *   11/12/1994 JLB : Handles cache logic.                                                     *
    358  *   05/04/1995 JLB : Variation adjustments.                                                   *
    359  *=============================================================================================*/
    360 int Sound_Effect(VocType voc, VolType volume, int variation, signed short pan_value)
    361 {
    362 	char name[_MAX_FNAME+_MAX_EXT];				// Working filename of sound effect.
    363 
    364 	if (!Options.Volume || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
    365 		return(-1);
    366 	}
    367 
    368 	/*
    369 	**	Fetch a pointer to the sound effect data. Modify the sound as appropriate and desired.
    370 	*/
    371 	char const * ext = ".AUD";
    372 	if (Special.IsJuvenile && SoundEffectName[voc].Where == IN_JUV) {
    373 		ext = ".JUV";
    374 	} else {
    375 		if (SoundEffectName[voc].Where == IN_VAR) {
    376 
    377 			/*
    378 			**	For infantry, use a variation on the response. For vehicles, always
    379 			**	use the vehicle response table.
    380 			*/
    381 			if (variation < 0) {
    382 				if (ABS(variation) % 2) {
    383 					ext = ".V00";
    384 				} else {
    385 					ext = ".V02";
    386 				}
    387 			} else {
    388 				if (variation % 2) {
    389 					ext = ".V01";
    390 				} else {
    391 					ext = ".V03";
    392 				}
    393 			}
    394 		}
    395 	}
    396 	_makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);
    397 	void const * ptr = MixFileClass::Retrieve(name);
    398 
    399 	/*
    400 	**	If the sound data pointer is not null, then presume that it is valid.
    401 	*/
    402 	if (ptr) {
    403 		return(Play_Sample(ptr, Fixed_To_Cardinal(SoundEffectName[voc].Priority, (int)volume), (int)volume, pan_value));
    404 	}
    405 	return(-1);
    406 }
    407 
    408 
    409 /*
    410 **	This elaborates all the EVA speech voices.
    411 */
    412 char const * Speech[VOX_COUNT] =  {
    413 	"ACCOM1",		//	mission accomplished
    414 	"FAIL1",			//	your mission has failed
    415 	"BLDG1",			//	unable to comply, building in progress
    416 	"CONSTRU1",		//	construction complete
    417 	"UNITREDY",		//	unit ready
    418 	"NEWOPT1",		//	new construction options
    419 	"DEPLOY1",		//	cannot deploy here
    420 	"GDIDEAD1",		//	GDI unit destroyed
    421 	"NODDEAD1",		//	Nod unit destroyed
    422 	"CIVDEAD1",		//	civilian killed
    423 //	"EVAYES1",		//	affirmative
    424 //	"EVANO1",		//	negative
    425 //	"UPUNIT1",		//	upgrade complete, new unit available
    426 //	"UPSTRUC1",		//	upgrade complete, new structure available
    427 	"NOCASH1",		//	insufficient funds
    428 	"BATLCON1",		//	battle control terminated
    429 	"REINFOR1",		//	reinforcements have arrived
    430 	"CANCEL1",		//	canceled
    431 	"BLDGING1",		//	building
    432 	"LOPOWER1",		//	low power
    433 	"NOPOWER1",		//	insufficient power
    434 	"MOCASH1",		//	need more funds
    435 	"BASEATK1",		//	our base is under attack
    436 	"INCOME1",		//	incoming missile
    437 	"ENEMYA",		//	enemy planes approaching
    438 	"NUKE1",			//	nuclear warhead approaching - VOX_INCOMING_NUKE
    439 //	"RADOK1",		//	radiation levels are acceptable
    440 //	"RADFATL1",		//	radiation levels are fatal
    441 	"NOBUILD1",		//	unable to build more
    442 	"PRIBLDG1",		//	primary building selected
    443 //	"REPDONE1",		//	repairs completed
    444 	"NODCAPT1",		//	Nod building captured
    445 	"GDICAPT1",		//	GDI building captured
    446 //	"SOLD1",			//	structure sold
    447 	"IONCHRG1",		//	ion cannon charging
    448 	"IONREDY1",		//	ion cannon ready
    449 	"NUKAVAIL",		//	nuclear weapon available
    450 	"NUKLNCH1",		//	nuclear weapon launched - VOX_NUKE_LAUNCHED
    451 	"UNITLOST",		// unit lost
    452 	"STRCLOST",		// structure lost
    453 	"NEEDHARV",		//	need harvester
    454 	"SELECT1",		// select target
    455 	"AIRREDY1",		// airstrike ready
    456 	"NOREDY1",		//	not ready
    457 	"TRANSSEE",		// Nod transport sighted
    458 	"TRANLOAD",		// Nod transport loaded
    459 	"ENMYAPP1",		//	enemy approaching
    460 	"SILOS1",		//	silos needed
    461 	"ONHOLD1",		//	on hold
    462 	"REPAIR1",		//	repairing
    463 	"ESTRUCX",		//	enemy structure destroyed
    464 	"GSTRUC1",		//	GDI structure destroyed
    465 	"NSTRUC1",		//	NOD structure destroyed
    466 	"ENMYUNIT",		// Enemy unit destroyed
    467 //	"GUKILL1",		//	gold unit destroyed
    468 //	"GSTRUD1",		//	gold structure destroyed
    469 //	"GONLINE1",		//	gold player online
    470 //	"GLEFT1",		//	gold player has departed
    471 //	"GOLDKILT",		//	gold player destroyed
    472 //	"GOLDWIN",		//	gold player is victorious
    473 //	"RUKILL1",		//	red unit destroyed
    474 //	"RSTRUD1",		//	red structure destroyed
    475 //	"RONLINE1",		//	red player online
    476 //	"RLEFT1",		//	red player has departed
    477 //	"REDKILT",		//	red player destroyed
    478 //	"REDWIN",		//	red player is victorious
    479 //	"GYUKILL1",		//	grey unit destroyed
    480 //	"GYSTRUD1",		//	grey structure destroyed
    481 //	"GYONLINE",		//	grey player online
    482 //	"GYLEFT1",		//	grey player has departed
    483 //	"GREYKILT",		//	grey player destroyed
    484 //	"GREYWIN",		//	grey player is victorious
    485 //	"OUKILL1",		//	orange unit destroyed
    486 //	"OSTRUD1",		//	orange structure destroyed
    487 //	"OONLINE1",		//	orange player online
    488 //	"OLEFT1",		//	orange player has departed
    489 //	"ORANKILT",		//	orange player destroyed
    490 //	"ORANWIN",		//	orange player is victorious
    491 //	"GNUKILL1",		//	green unit destroyed
    492 //	"GNSTRUD1",		//	green structure destroyed
    493 //	"GNONLINE",		//	green player online
    494 //	"GNLEFT1",		//	green player has departed
    495 //	"GRENKILT",		//	green player destroyed
    496 //	"GRENWIN",		//	green player is victorious
    497 //	"BUKILL1",		//	blue unit destroyed
    498 //	"BSTRUD1",		//	blue structure destroyed
    499 //	"BONLINE1",		//	blue player online
    500 //	"BLEFT1",		//	blue player has departed
    501 //	"BLUEKILT",		//	blue player destroyed
    502 //	"BLUEWIN"		//	blue player is victorious
    503 };
    504 static VoxType CurrentVoice = VOX_NONE;
    505 
    506 
    507 /***********************************************************************************************
    508  * Speak -- Computer speaks to the player.                                                     *
    509  *                                                                                             *
    510  *    This routine is used to have the game computer (EVA) speak to the player.                *
    511  *                                                                                             *
    512  * INPUT:   voice -- The voice number to speak (see defines.h).                                *
    513  *                                                                                             *
    514  * OUTPUT:  Returns with the handle of the playing speech (-1 if no voice started).            *
    515  *                                                                                             *
    516  * WARNINGS:   none                                                                            *
    517  *                                                                                             *
    518  * HISTORY:                                                                                    *
    519  *   11/12/1994 JLB : Created.                                                                 *
    520  *=============================================================================================*/
    521 void Speak(VoxType voice, HouseClass *house, COORDINATE coord)
    522 {
    523 	// MBL 02.22.2019
    524 	if (voice == VOX_NONE)
    525 	{
    526 		return;
    527 	}
    528 
    529 	//
    530 	// Intercept speech calls. ST - 2/20/2019 3:37PM
    531 	//
    532 	// On_Speech((int)voice); // MBL 02.06.2020
    533 	On_Speech((int)voice, house);
    534 	if (coord) {
    535 		On_Ping(house, coord);
    536 	}
    537 
    538 #if (0)	
    539 	if (Options.Volume && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {
    540 		SpeakQueue = voice;
    541 	}
    542 #endif
    543 }
    544 
    545 
    546 /***********************************************************************************************
    547  * Speak_AI -- Handles starting the EVA voices.                                                *
    548  *                                                                                             *
    549  *    This starts the EVA voice talking as well. If there is any speech request in the queue,  *
    550  *    it will be started when the current voice is finished. Call this routine as often as     *
    551  *    possible (once per game tick is sufficient).                                             *
    552  *                                                                                             *
    553  * INPUT:   none                                                                               *
    554  *                                                                                             *
    555  * OUTPUT:  none                                                                               *
    556  *                                                                                             *
    557  * WARNINGS:   none                                                                            *
    558  *                                                                                             *
    559  * HISTORY:                                                                                    *
    560  *   12/27/1994 JLB : Created.                                                                 *
    561  *=============================================================================================*/
    562 void Speak_AI(void)
    563 {
    564 // MBL 06.17.2019 KO
    565 #if 0
    566 	static VoxType _last = VOX_NONE;
    567 	if (SampleType == 0) return;
    568 
    569 	if (!Is_Sample_Playing(SpeechBuffer)) {
    570 		CurrentVoice = VOX_NONE;
    571 		if (SpeakQueue != VOX_NONE) {
    572 			if (SpeakQueue != _last) {
    573 				char name[_MAX_FNAME+_MAX_EXT];
    574 
    575 				_makepath(name, NULL, NULL, Speech[SpeakQueue], ".AUD");
    576 				if (CCFileClass(name).Read(SpeechBuffer, SPEECH_BUFFER_SIZE)) {
    577 					Play_Sample(SpeechBuffer, 254, Options.Volume);
    578 				}
    579 				_last = SpeakQueue;
    580 			} else {
    581 				Play_Sample(SpeechBuffer, 254, Options.Volume);
    582 			}
    583 			SpeakQueue = VOX_NONE;
    584 		}
    585 	}
    586 #endif
    587 }
    588 
    589 
    590 /***********************************************************************************************
    591  * Stop_Speaking -- Forces the EVA voice to stop talking.                                      *
    592  *                                                                                             *
    593  *    Use this routine to immediately stop the EVA voice from speaking. It also clears out     *
    594  *    the pending voice queue.                                                                 *
    595  *                                                                                             *
    596  * INPUT:   none                                                                               *
    597  *                                                                                             *
    598  * OUTPUT:  none                                                                               *
    599  *                                                                                             *
    600  * WARNINGS:   none                                                                            *
    601  *                                                                                             *
    602  * HISTORY:                                                                                    *
    603  *   12/27/1994 JLB : Created.                                                                 *
    604  *=============================================================================================*/
    605 void Stop_Speaking(void)
    606 {
    607 	SpeakQueue = VOX_NONE;
    608 	if (SampleType != 0) {
    609 		Stop_Sample_Playing(SpeechBuffer);
    610 	}
    611 }
    612 
    613 
    614 /***********************************************************************************************
    615  * Is_Speaking -- Checks to see if the eva voice is still playing.                             *
    616  *                                                                                             *
    617  *    Call this routine when the EVA voice being played needs to be checked. A typical use     *
    618  *    of this would be when some action needs to be delayed until the voice has finished --    *
    619  *    say the end of the game.                                                                 *
    620  *                                                                                             *
    621  * INPUT:   none                                                                               *
    622  *                                                                                             *
    623  * OUTPUT:  bool; Is the EVA voice still playing?                                              *
    624  *                                                                                             *
    625  * WARNINGS:   none                                                                            *
    626  *                                                                                             *
    627  * HISTORY:                                                                                    *
    628  *   03/12/1995 JLB : Created.                                                                 *
    629  *=============================================================================================*/
    630 bool Is_Speaking(void)
    631 {
    632 	Speak_AI();
    633 	if (SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {
    634 		return(true);
    635 	}
    636 	return(false);
    637 }