forked from mia/Aegisub
Make FractionalTime less weird
Originally committed to SVN as r6086.
This commit is contained in:
parent
7a2c461825
commit
ff32be592f
4 changed files with 35 additions and 86 deletions
|
@ -251,63 +251,32 @@ int AssTime::GetTimeMiliseconds() { return (time % 1000); }
|
||||||
///
|
///
|
||||||
int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; }
|
int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; }
|
||||||
|
|
||||||
|
FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe, char sep)
|
||||||
|
: num(numerator)
|
||||||
|
, den(denominator)
|
||||||
|
, drop(dropframe)
|
||||||
/// @brief Constructor
|
, sep(sep)
|
||||||
/// @param separator
|
{
|
||||||
/// @param numerator
|
|
||||||
/// @param denominator
|
|
||||||
/// @param dropframe
|
|
||||||
///
|
|
||||||
FractionalTime::FractionalTime (wxString separator, int numerator, int denominator, bool dropframe) {
|
|
||||||
drop = dropframe;
|
|
||||||
if (drop) {
|
if (drop) {
|
||||||
// no dropframe for any other framerates
|
// no dropframe for any other framerates
|
||||||
num = 30000;
|
num = 30000;
|
||||||
den = 1001;
|
den = 1001;
|
||||||
} else {
|
|
||||||
num = numerator;
|
|
||||||
den = denominator;
|
|
||||||
}
|
}
|
||||||
sep = separator;
|
|
||||||
|
|
||||||
// fractions < 1 are not welcome here
|
// fractions < 1 are not welcome here
|
||||||
if ((num <= 0 || den <= 0) || (num < den))
|
if ((num <= 0 || den <= 0) || (num < den))
|
||||||
throw "FractionalTime: nonsensical enumerator or denominator";
|
throw "FractionalTime: nonsensical enumerator or denominator";
|
||||||
if (sep.IsEmpty())
|
|
||||||
throw "FractionalTime: no separator specified";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FractionalTime::ToMillisecs(wxString text) {
|
||||||
/// @brief Destructor
|
|
||||||
///
|
|
||||||
FractionalTime::~FractionalTime () {
|
|
||||||
sep.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief SMPTE text string to milliseconds conversion
|
|
||||||
/// @param _text
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
int FractionalTime::ToMillisecs (wxString _text) {
|
|
||||||
wxString text = _text;
|
|
||||||
wxString re_str = "";
|
|
||||||
text.Trim(false);
|
text.Trim(false);
|
||||||
text.Trim(true);
|
text.Trim(true);
|
||||||
long h=0,m=0,s=0,f=0;
|
|
||||||
|
|
||||||
// hour minute second fraction
|
wxRegEx re(wxString::Format("(\\d+)%c(\\d+)%c(\\d+)%c(\\d+)", sep, sep, sep, sep), wxRE_ADVANCED);
|
||||||
re_str << "(\\d+)" << sep << "(\\d+)" << sep << "(\\d+)" << sep << "(\\d+)";
|
|
||||||
|
|
||||||
wxRegEx re(re_str, wxRE_ADVANCED);
|
|
||||||
if (!re.IsValid())
|
|
||||||
throw "FractionalTime: regex failure";
|
|
||||||
if (!re.Matches(text))
|
if (!re.Matches(text))
|
||||||
return 0; // FIXME: throw here too?
|
return 0; // FIXME: throw here too?
|
||||||
|
|
||||||
|
long h=0, m=0, s=0, f=0;
|
||||||
re.GetMatch(text,1).ToLong(&h);
|
re.GetMatch(text,1).ToLong(&h);
|
||||||
re.GetMatch(text,2).ToLong(&m);
|
re.GetMatch(text,2).ToLong(&m);
|
||||||
re.GetMatch(text,3).ToLong(&s);
|
re.GetMatch(text,3).ToLong(&s);
|
||||||
|
@ -327,7 +296,7 @@ int FractionalTime::ToMillisecs (wxString _text) {
|
||||||
fn += m * 1798; // two timestamps dropped per minute after the first
|
fn += m * 1798; // two timestamps dropped per minute after the first
|
||||||
fn += s * 30 + f - 2;
|
fn += s * 30 + f - 2;
|
||||||
}
|
}
|
||||||
else { // minute is evenly divisible by 10, keep first two timestamps
|
else { // minute is evenly divisible by 10, keep first two timestamps
|
||||||
fn += s * 30;
|
fn += s * 30;
|
||||||
fn += f;
|
fn += f;
|
||||||
}
|
}
|
||||||
|
@ -349,40 +318,23 @@ int FractionalTime::ToMillisecs (wxString _text) {
|
||||||
return msecs_f;
|
return msecs_f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssTime FractionalTime::ToAssTime(wxString text) {
|
||||||
/// @brief SMPTE text string to AssTime conversion
|
return AssTime(ToMillisecs(text));
|
||||||
/// @param _text
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
AssTime FractionalTime::ToAssTime (wxString _text) {
|
|
||||||
AssTime time;
|
|
||||||
time.SetMS((int)ToMillisecs(_text));
|
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief AssTime to SMPTE text string conversion
|
|
||||||
/// @param time
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
wxString FractionalTime::FromAssTime(AssTime time) {
|
wxString FractionalTime::FromAssTime(AssTime time) {
|
||||||
return FromMillisecs(time.GetMS());
|
return FromMillisecs(time.GetMS());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Milliseconds to SMPTE text string conversion
|
|
||||||
/// @param msec
|
|
||||||
///
|
|
||||||
wxString FractionalTime::FromMillisecs(int64_t msec) {
|
wxString FractionalTime::FromMillisecs(int64_t msec) {
|
||||||
int h=0, m=0, s=0, f=0; // hours, minutes, seconds, fractions
|
int h=0, m=0, s=0, f=0; // hours, minutes, seconds, fractions
|
||||||
int fn = (msec*(int64_t)num) / (1000*den); // frame number
|
int fn = (msec*(int64_t)num) / (1000*den); // frame number
|
||||||
|
|
||||||
// return 00:00:00:00
|
// return 00:00:00:00
|
||||||
if (msec <= 0)
|
if (msec <= 0) {
|
||||||
goto RETURN;
|
}
|
||||||
|
|
||||||
// dropframe?
|
// dropframe?
|
||||||
if (drop) {
|
else if (drop) {
|
||||||
fn += 2 * (fn / (30 * 60)) - 2 * (fn / (30 * 60 * 10));
|
fn += 2 * (fn / (30 * 60)) - 2 * (fn / (30 * 60 * 10));
|
||||||
h = fn / (30 * 60 * 60);
|
h = fn / (30 * 60 * 60);
|
||||||
m = (fn / (30 * 60)) % 60;
|
m = (fn / (30 * 60)) % 60;
|
||||||
|
@ -409,20 +361,18 @@ wxString FractionalTime::FromMillisecs(int64_t msec) {
|
||||||
int frames_per_h = 3600*fps_approx;
|
int frames_per_h = 3600*fps_approx;
|
||||||
int frames_per_m = 60*fps_approx;
|
int frames_per_m = 60*fps_approx;
|
||||||
int frames_per_s = fps_approx;
|
int frames_per_s = fps_approx;
|
||||||
while (fn >= frames_per_h) {
|
|
||||||
h++; fn -= frames_per_h;
|
h = fn / frames_per_h;
|
||||||
}
|
fn = fn % frames_per_h;
|
||||||
while (fn >= frames_per_m) {
|
|
||||||
m++; fn -= frames_per_m;
|
m = fn / frames_per_m;
|
||||||
}
|
fn = fn % frames_per_m;
|
||||||
while (fn >= frames_per_s) {
|
|
||||||
s++; fn -= frames_per_s;
|
s = fn / frames_per_s;
|
||||||
}
|
fn = fn % frames_per_s;
|
||||||
|
|
||||||
f = fn;
|
f = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN:
|
return wxString::Format("%02i%c%02%c%02i%c%02i", h, sep, m, sep, s, sep, f);
|
||||||
return wxString::Format("%02i" + sep + "%02i" + sep + "%02i" + sep + "%02i",h,m,s,f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,22 +91,21 @@ class FractionalTime {
|
||||||
int num; ///< Numerator
|
int num; ///< Numerator
|
||||||
int den; ///< Denominator
|
int den; ///< Denominator
|
||||||
bool drop; ///< Enable SMPTE dropframe handling
|
bool drop; ///< Enable SMPTE dropframe handling
|
||||||
|
char sep; ///< Timecode component separator
|
||||||
/// separator; someone might have separators of more than one character :V
|
|
||||||
wxString sep;
|
|
||||||
|
|
||||||
/// How often to drop frames when enabled
|
/// How often to drop frames when enabled
|
||||||
static const int frames_per_period = 17982;
|
static const int frames_per_period = 17982;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// dumb assumption? I give no fuck
|
FractionalTime(int numerator=30, int denominator=1, bool dropframe=false, char sep=':');
|
||||||
/// NOTE: separator can be a regex! at least if you only plan on doing SMPTE->somethingelse.
|
|
||||||
FractionalTime(wxString separator, int numerator=30, int denominator=1, bool dropframe=false);
|
|
||||||
~FractionalTime();
|
|
||||||
|
|
||||||
|
/// Parse a SMPTE timecode, returning an AssTime
|
||||||
AssTime ToAssTime(wxString fractime);
|
AssTime ToAssTime(wxString fractime);
|
||||||
|
/// Parse a SMPTE timecode, returning milliseconds
|
||||||
int ToMillisecs(wxString fractime);
|
int ToMillisecs(wxString fractime);
|
||||||
|
|
||||||
|
/// Convert an AssTime to a SMPTE timecode
|
||||||
wxString FromAssTime(AssTime time);
|
wxString FromAssTime(AssTime time);
|
||||||
|
/// Convert milliseconds to a SMPTE timecode
|
||||||
wxString FromMillisecs(int64_t msec);
|
wxString FromMillisecs(int64_t msec);
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,7 +71,7 @@ void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& e
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
// Encore wants ; instead of : if we're dealing with NTSC dropframe stuff
|
// Encore wants ; instead of : if we're dealing with NTSC dropframe stuff
|
||||||
FractionalTime ft(fps_rat.smpte_dropframe ? ";" : ":", fps_rat.num, fps_rat.den, fps_rat.smpte_dropframe);
|
FractionalTime ft(fps_rat.num, fps_rat.den, fps_rat.smpte_dropframe, fps_rat.smpte_dropframe ? ';' : ':');
|
||||||
|
|
||||||
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
||||||
|
|
|
@ -121,7 +121,7 @@ wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRationa
|
||||||
if (nextl_start > 0 && end.GetMS() == nextl_start)
|
if (nextl_start > 0 && end.GetMS() == nextl_start)
|
||||||
end.SetMS(end.GetMS() - ((1000*fps_rat->den)/fps_rat->num));
|
end.SetMS(end.GetMS() - ((1000*fps_rat->den)/fps_rat->num));
|
||||||
|
|
||||||
FractionalTime ft(":", fps_rat->num, fps_rat->den, fps_rat->smpte_dropframe);
|
FractionalTime ft(fps_rat->num, fps_rat->den, fps_rat->smpte_dropframe);
|
||||||
wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft.FromAssTime(start) + ">" + ft.FromAssTime(end) + "]\r\n";
|
wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft.FromAssTime(start) + ">" + ft.FromAssTime(end) + "]\r\n";
|
||||||
|
|
||||||
// Process text
|
// Process text
|
||||||
|
|
Loading…
Reference in a new issue