static void S_AddSNDINFO()

in doom_py/src/vizdoom/src/s_advsound.cpp [973:1415]


static void S_AddSNDINFO (int lump)
{
	bool skipToEndIf;
	TArray<WORD> list;

	FScanner sc(lump);
	skipToEndIf = false;

	while (sc.GetString ())
	{
		if (skipToEndIf)
		{
			if (sc.Compare ("$endif"))
			{
				skipToEndIf = false;
			}
			continue;
		}

		if (sc.String[0] == '$')
		{ // Got a command
			switch (sc.MatchString (SICommandStrings))
			{
			case SI_Ambient: {
				// $ambient <num> <logical name> [point [atten] | surround | [world]]
				//			<continuous | random <minsecs> <maxsecs> | periodic <secs>>
				//			<volume>
				FAmbientSound *ambient;

				sc.MustGetNumber ();
				ambient = &Ambients[sc.Number];
				ambient->type = 0;
				ambient->periodmin = 0;
				ambient->periodmax = 0;
				ambient->volume = 0;
				ambient->attenuation = 0;
				ambient->sound = 0;

				sc.MustGetString ();
				ambient->sound = FSoundID(S_FindSoundTentative(sc.String));
				ambient->attenuation = 0;

				sc.MustGetString ();
				if (sc.Compare ("point"))
				{
					float attenuation;

					ambient->type = POSITIONAL;
					sc.MustGetString ();

					if (IsFloat (sc.String))
					{
						attenuation = (float)atof (sc.String);
						sc.MustGetString ();
						if (attenuation > 0)
						{
							ambient->attenuation = attenuation;
						}
						else
						{
							ambient->attenuation = 1;
						}
					}
					else
					{
						ambient->attenuation = 1;
					}
				}
				else if (sc.Compare ("surround"))
				{
					ambient->type = SURROUND;
					sc.MustGetString ();
					ambient->attenuation = -1;
				}
				else
				{ // World is an optional keyword
					if (sc.Compare ("world"))
					{
						sc.MustGetString ();
					}
				}

				if (sc.Compare ("continuous"))
				{
					ambient->type |= CONTINUOUS;
				}
				else if (sc.Compare ("random"))
				{
					ambient->type |= RANDOM;
					sc.MustGetFloat ();
					ambient->periodmin = (int)(sc.Float * TICRATE);
					sc.MustGetFloat ();
					ambient->periodmax = (int)(sc.Float * TICRATE);
				}
				else if (sc.Compare ("periodic"))
				{
					ambient->type |= PERIODIC;
					sc.MustGetFloat ();
					ambient->periodmin = (int)(sc.Float * TICRATE);
				}
				else
				{
					Printf ("Unknown ambient type (%s)\n", sc.String);
				}

				sc.MustGetFloat ();
				ambient->volume = (float)sc.Float;
				if (ambient->volume > 1)
					ambient->volume = 1;
				else if (ambient->volume < 0)
					ambient->volume = 0;
				}
				break;

			case SI_Map: {
				// Hexen-style $MAP command
				int mapnum;

				sc.MustGetNumber();
				mapnum = sc.Number;
				sc.MustGetString();
				if (mapnum != 0)
				{
					HexenMusic[mapnum] = sc.String;
				}
				}
				break;

			case SI_Registered:
				// I don't think Hexen even pays attention to the $registered command.
			case SI_EDFOverride:
				break;

			case SI_ArchivePath:
				sc.MustGetString ();	// Unused for now
				break;

			case SI_PlayerSound: {
				// $playersound <player class> <gender> <logical name> <lump name>
				FString pclass;
				int gender, refid, sfxnum;

				S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
				sfxnum = S_AddPlayerSound (pclass, gender, refid, sc.String);
				if (0 == stricmp(sc.String, "dsempty"))
				{
					S_sfx[sfxnum].bPlayerSilent = true;
				}
				}
				break;

			case SI_PlayerSoundDup: {
				// $playersounddup <player class> <gender> <logical name> <target sound name>
				FString pclass;
				int gender, refid, targid;

				S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
				targid = S_FindSoundNoHash (sc.String);
				if (!S_sfx[targid].bPlayerReserve)
				{
					sc.ScriptError ("%s is not a player sound", sc.String);
				}
				S_DupPlayerSound (pclass, gender, refid, targid);
				}
				break;

			case SI_PlayerCompat: {
				// $playercompat <player class> <gender> <logical name> <compat sound name>
				FString pclass;
				int gender, refid;
				int sfxfrom, aliasto;

				S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
				sfxfrom = S_AddSound (sc.String, -1, &sc);
				aliasto = S_LookupPlayerSound (pclass, gender, refid);
				S_sfx[sfxfrom].link = aliasto;
				S_sfx[sfxfrom].bPlayerCompat = true;
				}
				break;

			case SI_PlayerAlias: {
				// $playeralias <player class> <gender> <logical name> <logical name of existing sound>
				FString pclass;
				int gender, refid;
				int soundnum;

				S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
				soundnum = S_FindSoundTentative (sc.String);
				S_AddPlayerSoundExisting (pclass, gender, refid, soundnum);
				}
				break;

			case SI_Alias: {
				// $alias <name of alias> <name of real sound>
				int sfxfrom;

				sc.MustGetString ();
				sfxfrom = S_AddSound (sc.String, -1, &sc);
				sc.MustGetString ();
				if (S_sfx[sfxfrom].bPlayerCompat)
				{
					sfxfrom = S_sfx[sfxfrom].link;
				}
				S_sfx[sfxfrom].link = S_FindSoundTentative (sc.String);
				S_sfx[sfxfrom].NearLimit = -1;	// Aliases must use the original sound's limit.
				}
				break;

			case SI_Limit: {
				// $limit <logical name> <max channels> [<distance>]
				int sfx;

				sc.MustGetString ();
				sfx = S_FindSoundTentative (sc.String);
				sc.MustGetNumber ();
				S_sfx[sfx].NearLimit = MIN(MAX(sc.Number, 0), 255);
				if (sc.CheckFloat())
				{
					S_sfx[sfx].LimitRange = float(sc.Float * sc.Float);
				}
				}
				break;

			case SI_Singular: {
				// $singular <logical name>
				int sfx;

				sc.MustGetString ();
				sfx = S_FindSoundTentative (sc.String);
				S_sfx[sfx].bSingular = true;
				}
				break;

			case SI_PitchShift: {
				// $pitchshift <logical name> <pitch shift amount>
				int sfx;

				sc.MustGetString ();
				sfx = S_FindSoundTentative (sc.String);
				sc.MustGetNumber ();
				S_sfx[sfx].PitchMask = (1 << clamp (sc.Number, 0, 7)) - 1;
				}
				break;

			case SI_PitchShiftRange:
				// $pitchshiftrange <pitch shift amount>
				sc.MustGetNumber ();
				CurrentPitchMask = (1 << clamp (sc.Number, 0, 7)) - 1;
				break;

			case SI_Volume: {
				// $volume <logical name> <volume>
				int sfx;

				sc.MustGetString();
				sfx = S_FindSoundTentative(sc.String);
				sc.MustGetFloat();
				S_sfx[sfx].Volume = (float)sc.Float;
				}
				break;

			case SI_Attenuation: {
				// $attenuation <logical name> <attenuation>
				int sfx;

				sc.MustGetString();
				sfx = S_FindSoundTentative(sc.String);
				sc.MustGetFloat();
				S_sfx[sfx].Attenuation = (float)sc.Float;
				}
				break;

			case SI_Rolloff: {
				// $rolloff *|<logical name> [linear|log|custom] <min dist> <max dist/rolloff factor>
				// Using * for the name makes it the default for sounds that don't specify otherwise.
				FRolloffInfo *rolloff;
				int type;
				int sfx;

				sc.MustGetString();
				if (sc.Compare("*"))
				{
					sfx = -1;
					rolloff = &S_Rolloff;
				}
				else
				{
					sfx = S_FindSoundTentative(sc.String);
					rolloff = &S_sfx[sfx].Rolloff;
				}
				type = ROLLOFF_Doom;
				if (!sc.CheckFloat())
				{
					sc.MustGetString();
					if (sc.Compare("linear"))
					{
						rolloff->RolloffType = ROLLOFF_Linear;
					}
					else if (sc.Compare("log"))
					{
						rolloff->RolloffType = ROLLOFF_Log;
					}
					else if (sc.Compare("custom"))
					{
						rolloff->RolloffType = ROLLOFF_Custom;
					}
					else
					{
						sc.ScriptError("Unknown rolloff type '%s'", sc.String);
					}
					sc.MustGetFloat();
				}
				rolloff->MinDistance = (float)sc.Float;
				sc.MustGetFloat();
				rolloff->MaxDistance = (float)sc.Float;
				break;
			  }

			case SI_Random: {
				// $random <logical name> { <logical name> ... }
				FRandomSoundList random;

				list.Clear ();
				sc.MustGetString ();
				random.SfxHead = S_AddSound (sc.String, -1, &sc);
				sc.MustGetStringName ("{");
				while (sc.GetString () && !sc.Compare ("}"))
				{
					WORD sfxto = S_FindSoundTentative (sc.String);
					if (sfxto == random.SfxHead)
					{
						Printf("Definition of random sound '%s' refers to itself recursively.", sc.String);
						continue;
					}
					list.Push (sfxto);
				}
				if (list.Size() == 1)
				{ // Only one sound: treat as $alias
					S_sfx[random.SfxHead].link = list[0];
					S_sfx[random.SfxHead].NearLimit = -1;
				}
				else if (list.Size() > 1)
				{ // Only add non-empty random lists
					random.NumSounds = (WORD)list.Size();
					S_sfx[random.SfxHead].link = (WORD)S_rnd.Push (random);
					S_sfx[random.SfxHead].bRandomHeader = true;
					S_rnd[S_sfx[random.SfxHead].link].Sounds = new WORD[random.NumSounds];
					memcpy (S_rnd[S_sfx[random.SfxHead].link].Sounds, &list[0], sizeof(WORD)*random.NumSounds);
					S_sfx[random.SfxHead].NearLimit = -1;
				}
				}
				break;

			case SI_MusicVolume: {
				sc.MustGetString();
				FString musname (sc.String);
				sc.MustGetFloat();
				FMusicVolume *mv = (FMusicVolume *)M_Malloc (sizeof(*mv) + musname.Len());
				mv->Volume = (float)sc.Float;
				strcpy (mv->MusicName, musname);
				mv->Next = MusicVolumes;
				MusicVolumes = mv;
				}
				break;

			case SI_MusicAlias: {
				sc.MustGetString();
				int lump = Wads.CheckNumForName(sc.String, ns_music);
				if (lump >= 0)
				{
					// do not set the alias if a later WAD defines its own music of this name
					int file = Wads.GetLumpFile(lump);
					int sndifile = Wads.GetLumpFile(sc.LumpNum);
					if (file > sndifile)
					{
						sc.MustGetString();
						continue;
					}
				}
				FName alias = sc.String;
				sc.MustGetString();
				FName mapped = sc.String;

				// only set the alias if the lump it maps to exists.
				if (mapped == NAME_None || Wads.CheckNumForName(sc.String, ns_music) >= 0)
				{
					MusicAliases[alias] = mapped;
				}
				}
				break;

			case SI_MidiDevice: {
				sc.MustGetString();
				FName nm = sc.String;
				FScanner::SavedPos save = sc.SavePos();
				
				sc.SetCMode(true);
				sc.MustGetString();
				MidiDeviceSetting devset;
				if (sc.Compare("timidity")) devset.device = MDEV_TIMIDITY;
				else if (sc.Compare("fmod") || sc.Compare("sndsys")) devset.device = MDEV_SNDSYS;
				else if (sc.Compare("standard")) devset.device = MDEV_MMAPI;
				else if (sc.Compare("opl")) devset.device = MDEV_OPL;
				else if (sc.Compare("default")) devset.device = MDEV_DEFAULT;
				else if (sc.Compare("fluidsynth")) devset.device = MDEV_FLUIDSYNTH;
				else if (sc.Compare("gus")) devset.device = MDEV_GUS;
				else if (sc.Compare("wildmidi")) devset.device = MDEV_WILDMIDI;
				else sc.ScriptError("Unknown MIDI device %s\n", sc.String);

				if (sc.CheckString(","))
				{
					sc.SetCMode(false);
					sc.MustGetString();
					devset.args = sc.String;
				}
				else
				{
					// This does not really do what one might expect, because the next token has already been parsed and can be a '$'.
					// So in order to continue parsing without C-Mode, we need to reset and parse the last token again.
					sc.SetCMode(false);
					sc.RestorePos(save);
					sc.MustGetString();
				}
				MidiDevices[nm] = devset;
				}
				break;

			case SI_IfDoom: //also Chex
			case SI_IfStrife:
			case SI_IfHeretic:
			case SI_IfHexen:
				skipToEndIf = !CheckGame(sc.String+3, true);
				break;
			}
		}
		else
		{ // Got a logical sound mapping
			FString name (sc.String);
			sc.MustGetString ();
			S_AddSound (name, sc.String, &sc);
		}
	}
}