public void OpenFiles()
{
long previousMilliseconds;
long milliseconds;
int count;
int sampleRate;
int distributionIndex;
m_parser.OpenFiles();
sampleRate = m_parser.ControlFile.SystemParameters.samples_per_second;
m_subsecondDistribution = Ticks.SubsecondDistribution(sampleRate);
using (Parser parser = new Parser())
{
parser.ControlFile = m_parser.ControlFile;
parser.FileName = m_parser.FileName;
// Open EMAX data file
parser.OpenFiles();
m_currentSecond = DateTime.MinValue;
previousMilliseconds = -1;
milliseconds = 0;
count = 0;
while (parser.ReadNext())
{
if (parser.TimeError)
continue;
// Set currentSecond to this frame's timestamp
m_currentSecond = parser.Timestamp;
// Get total milliseconds since epoch
milliseconds = m_currentSecond.Ticks / Ticks.PerMillisecond;
// If the milliseconds are exactly one millisecond greater than the previous
// timestamp's milliseconds, we can accurately find the timestamp of this frame
if (previousMilliseconds > 0 && milliseconds - previousMilliseconds == 1)
break;
// Update previousMilliseconds and count
previousMilliseconds = milliseconds;
count++;
}
if (m_currentSecond == DateTime.MinValue)
{
// If there was an error reading the timestamps in the parser,
// calculate the timestamp from the data in the control file
TimeZoneInfo tzInfo = parser.ControlFile.SystemParameters.GetTimeZoneInfo();
DateTime faultTime = parser.ControlFile.SystemParameters.FaultTime;
string daylightName = parser.ControlFile.SystemParameters.time_zone_information.DaylightName;
short faultMilliseconds = parser.ControlFile.SystemParameters.mS_time;
short prefaultSamples = parser.ControlFile.SystemParameters.prefault_samples;
short startOffsetSamples = parser.ControlFile.SystemParameters.start_offset_samples;
// Set currentSecond to the timestamp of the first frame
m_currentSecond = faultTime.AddMilliseconds(faultMilliseconds).AddSeconds(-(prefaultSamples + startOffsetSamples) / (double)sampleRate);
// Get total milliseconds since epoch
milliseconds = m_currentSecond.Ticks / Ticks.PerMillisecond;
// Timestamps in the control file are stored in UTC (or close to it),
// but it seems that sometimes EMAX adjusts timestamps without applying DST
// rules so we use the DaylightName of the time zone info as a sanity check
// and fall back on the BaseUtcOffset property in these weird cases
if (daylightName == tzInfo.DaylightName || daylightName != tzInfo.Id)
m_currentSecond = TimeZoneInfo.ConvertTimeFromUtc(m_currentSecond, tzInfo);
else
m_currentSecond += tzInfo.BaseUtcOffset;
m_currentSecond = DateTime.SpecifyKind(m_currentSecond, DateTimeKind.Unspecified);
}
// Remove subseconds from currentSecond
m_currentSecond = m_currentSecond.AddTicks(-(m_currentSecond.Ticks % Ticks.PerSecond));
// Get the milliseconds since the top of the second
milliseconds %= 1000;
// This should get very near to the index of the
// desired value in the subsecond distribution
distributionIndex = ((int)milliseconds * sampleRate) / 1000;
// Scan forward in the subsecond distribution until we are sure we've found the correct index
while ((long)m_subsecondDistribution[distributionIndex].ToMilliseconds() != milliseconds)
distributionIndex++;
// Set currentIndex to the index in the distribution of the first timestamp in this file
m_currentIndex = distributionIndex - count;
// Subtract seconds from currentSecond and add the equivalent number of indexes
// to currentIndex until currentIndex is greater than or equal to zero
while (m_currentIndex < 0)
{
m_currentSecond = m_currentSecond.AddSeconds(-1.0D);
m_currentIndex += sampleRate;
}
}
}