Skip to content

Commit

Permalink
Merge pull request #988 from Csantucci/conditional-sound-official
Browse files Browse the repository at this point in the history
  • Loading branch information
Csantucci authored Nov 4, 2024
2 parents 3419240 + f1d4d18 commit 2d03c3f
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
49 changes: 48 additions & 1 deletion Source/Documentation/Manual/sound.rst
Original file line number Diff line number Diff line change
Expand Up @@ -651,4 +651,51 @@ where the number in parenthesis may be anyone from 0 (nothing heard )
to 100 (internal track sound reproduced at volume as defined in .sms file).

If the parameter is not present, the internal track sound is
reproduced at the volume as defined in .sms file.
reproduced at the volume as defined in .sms file.

Conditional sound
=================

In the real world some sounds are present only at a specific time (season and/or
time of day) and/or with a specific weather.

OR provides the parameters to actuate that for any set of sound streams. Consider the
sound stream here below::

Stream (
Priority ( 6 )
ORTSSeason ( Spring () winter () )
ORTSWeather ( rain () )
ORTSTimeOfDay ( 7 12 )
ORTSTimeOfDay ( 13 20 )
Triggers ( 2
Variable_Trigger ( Distance_Dec_Past 400.0
StartLoop ( 1
File ( "Somma_annunci_loud.wav" -1 )
SelectionMethod ( SequentialSelection )
)
)
Variable_Trigger ( Distance_Inc_Past 400.0 ReleaseLoopRelease ())
)

VolumeCurve(
DistanceControlled
CurvePoints ( 4
0.0 1.0
230.0 1.0
260.0 0.0
2000.0 0.0
)
Granularity (0.01)
)
)


As can be seen, there are three keywords, that are ORTSSeason, ORTSWeather and
ORTSTimeOfDay. If one or more of the three keywords is not present in the stream,
the sound does not depend from that keyword.

In the example shown, the sound is played if all conditions are met, that is season
is spring or winter and weather is rain and time of day is within one of the two
intervals 7-12 or 13-20. There may be as many TimeOfDay lines as wanted,
but the granularity is one hour.
42 changes: 42 additions & 0 deletions Source/Orts.Formats.Msts/SoundManagmentFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ public class SMSStream
public float Volume = 1.0f;
public List<VolumeCurve> VolumeCurves = new List<VolumeCurve>();
public FrequencyCurve FrequencyCurve;
public bool[] Season;
public bool[] Weather;
public int[] TimeInterval;
public List<int[]> TimeIntervals;



public SMSStream(STFReader stf)
{
Expand All @@ -186,6 +192,42 @@ public SMSStream(STFReader stf)
new STFReader.TokenProcessor("volumecurve", ()=>{ VolumeCurves.Add(new VolumeCurve(stf)); }),
new STFReader.TokenProcessor("frequencycurve", ()=>{ FrequencyCurve = new FrequencyCurve(stf); }),
new STFReader.TokenProcessor("volume", ()=>{ Volume = stf.ReadFloatBlock(STFReader.UNITS.None, Volume); }),
new STFReader.TokenProcessor("ortstimeofday", ()=>{
if (TimeIntervals == null)
TimeIntervals = new List<int[]>();
var timeInterval = new int[2];
stf.MustMatch("(");
timeInterval[0] = stf.ReadInt(null);
timeInterval[1] = stf.ReadInt(null);
TimeIntervals.Add(timeInterval);
stf.SkipRestOfBlock();
}),
new STFReader.TokenProcessor("ortsseason", ()=>{
Season = new bool[4];
stf.MustMatch("(");
stf.ParseBlock(new STFReader.TokenProcessor[] {
new STFReader.TokenProcessor("spring", ()=>{ if(stf.ReadBoolBlock(true))
Season[(int)SeasonType.Spring] = true; }),
new STFReader.TokenProcessor("summer", ()=>{ if(stf.ReadBoolBlock(true))
Season[(int)SeasonType.Summer] = true; }),
new STFReader.TokenProcessor("autumn", ()=>{ if(stf.ReadBoolBlock(true))
Season[(int)SeasonType.Autumn] = true; }),
new STFReader.TokenProcessor("winter", ()=>{ if(stf.ReadBoolBlock(true))
Season[(int)SeasonType.Winter] = true; }),
});
}),
new STFReader.TokenProcessor("ortsweather", ()=>{
Weather = new bool[3];
stf.MustMatch("(");
stf.ParseBlock(new STFReader.TokenProcessor[] {
new STFReader.TokenProcessor("clear", ()=>{ if(stf.ReadBoolBlock(true))
Weather[(int)WeatherType.Clear] = true; }),
new STFReader.TokenProcessor("snow", ()=>{ if(stf.ReadBoolBlock(true))
Weather[(int)WeatherType.Snow] = true; }),
new STFReader.TokenProcessor("rain", ()=>{ if(stf.ReadBoolBlock(true))
Weather[(int)WeatherType.Rain] = true; }),
});
}),
});
//if (Volume > 1) Volume /= 100f;
}
Expand Down
26 changes: 26 additions & 0 deletions Source/RunActivity/Viewer3D/Sound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,32 @@ private void SetFreqAndVolume()
volume *= ((MSTSWagon)SoundSource.Viewer.Camera.AttachedCar).TrackSoundPassThruPercent * 0.01f;
}

// check if time of day, season and weather enable the sound; if not, set volume to zero
if (MSTSStream?.TimeIntervals != null)
{
var outOfInterval = true;
foreach (var timeInterval in MSTSStream.TimeIntervals)
{
int hourOfDay = (int)SoundSource.Viewer.Simulator.ClockTime / 3600;
if (hourOfDay >= timeInterval[0] && hourOfDay < timeInterval[1])
{
outOfInterval = false;
break;
}
}
if (outOfInterval)
volume = 0;
}
if (MSTSStream?.Season != null )
{
if (!MSTSStream.Season[(int)(SoundSource.Viewer.Simulator.Season)])
volume = 0;
}
if (MSTSStream?.Weather != null )
{
if (!MSTSStream.Weather[(int)(SoundSource.Viewer.Simulator.WeatherType)])
volume = 0;
}
ALSoundSource.Volume = volume;
}

Expand Down

0 comments on commit 2d03c3f

Please sign in to comment.