mirror of https://github.com/odrling/Aegisub
102 lines
4.0 KiB
C#
102 lines
4.0 KiB
C#
|
/*
|
||
|
SSATool - A collection of utilities for Advanced Substation Alpha
|
||
|
Copyright (C) 2007 Dan Donovan
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; ONLY under version 2
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
using System;
|
||
|
using System.Text;
|
||
|
using System.IO;
|
||
|
|
||
|
namespace SSATool {
|
||
|
public class TimeCodes {
|
||
|
private float[] times;
|
||
|
private double frameRate;
|
||
|
|
||
|
public TimeCodes(string filename, double frameRate) {
|
||
|
this.frameRate = frameRate;
|
||
|
double AssumeFPS = 29.97;
|
||
|
string thisline;
|
||
|
int frames = 0, index;
|
||
|
bool v1;
|
||
|
StreamReader fs = new StreamReader(filename);
|
||
|
|
||
|
thisline = fs.ReadLine(); // Save the first line now
|
||
|
if (string.Compare(thisline, "# timecode format v1", true, Util.cfi) == 0) v1 = true;
|
||
|
else if (string.Compare(thisline, "# timecode format v2", true, Util.cfi) == 0) v1 = false;
|
||
|
else throw new InvalidDataException("File was not detected as an MKV TimeCode v1 or v2 file.");
|
||
|
|
||
|
//count frames
|
||
|
while (!fs.EndOfStream) {
|
||
|
if ((fs.Peek() != '#') && ((thisline = fs.ReadLine()).Length > 3)) {
|
||
|
if (v1 == false) frames+=1;
|
||
|
else frames = Math.Max(frames, int.Parse(thisline.Split(",".ToCharArray())[1]));
|
||
|
}
|
||
|
else if ((fs.Peek() == 'A' || fs.Peek() == 'a') && (string.Compare(thisline.Split(" ".ToCharArray())[0], "assumefps", true, Util.cfi) == 0))
|
||
|
AssumeFPS = double.Parse(thisline.Split(" ".ToCharArray())[1]);
|
||
|
}
|
||
|
fs.Close();
|
||
|
|
||
|
//restart, actually saving info
|
||
|
fs = new StreamReader(filename);
|
||
|
while ((fs.Peek() == '#') || (fs.Peek() == 'a') || (fs.Peek() == 'A'))
|
||
|
fs.ReadLine();
|
||
|
|
||
|
times = new float[frames];
|
||
|
for (index = 0;index < frames;index+=1) {
|
||
|
if (v1) {
|
||
|
string[] splitv1 = fs.ReadLine().Split(",".ToCharArray());
|
||
|
for (;index <= int.Parse(splitv1[1]);index+=1) // frames is the number of frames with v1, so index SHOULD go up for every frame
|
||
|
times[index] = ((index != 0) ? times[index - 1] : 0) + (float)(1.0 / ((splitv1.Length == 3) ? float.Parse(splitv1[2]) : AssumeFPS));
|
||
|
}
|
||
|
else
|
||
|
times[index] = float.Parse(fs.ReadLine());
|
||
|
}
|
||
|
fs.Close();
|
||
|
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Finds the frame number of a given VFR time, so that frame number can be used to convert to a CFR time
|
||
|
/// </summary>
|
||
|
/// <param name="time">The time in MILLISECONDS</param>
|
||
|
/// <returns></returns>
|
||
|
public int FindFrame(float time) {
|
||
|
int k, low = 0, high = times.Length-1;
|
||
|
|
||
|
while (low!=high) {
|
||
|
k=(int)Math.Ceiling((high+low)/2.0f);
|
||
|
if (times[k].CompareTo(time) == -1)
|
||
|
low=k;
|
||
|
else if (k!=0 && times[k-1].CompareTo(time) == -1)
|
||
|
return k;
|
||
|
else high=k;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
public TimeSpan GetTimeInverse(TimeSpan time) {
|
||
|
int frame = System.Convert.ToInt32(time.TotalSeconds * frameRate, Util.cfi);
|
||
|
return TimeSpan.FromMilliseconds((frame<times.Length)?times[frame]:0);
|
||
|
}
|
||
|
|
||
|
public TimeSpan GetTime(TimeSpan time) {
|
||
|
return TimeSpan.FromSeconds(FindFrame((float)time.TotalMilliseconds) / frameRate);
|
||
|
}
|
||
|
}
|
||
|
}
|