/// @brief Actually process subtitles /// void DialogTimingProcessor::Process() { SortDialogues(); int rows = Sorted.size(); // Options long inVal = 0; long outVal = 0; leadIn->GetValue().ToLong(&inVal); leadOut->GetValue().ToLong(&outVal); bool addIn = hasLeadIn->IsChecked() && inVal; bool addOut = hasLeadOut->IsChecked() && outVal; // Add lead-in/out if (addIn || addOut) { for (int i=0; i<rows; i++) { AssDialogue *cur = Sorted[i]; // Compare to every previous line (yay for O(n^2)!) to see if it's OK to add lead-in if (inVal) { int startLead = cur->Start.GetMS() - inVal; for (int j=0; j<i; j++) { AssDialogue *comp = Sorted[j]; // Check if they don't already collide (ignore it in that case) if (cur->CollidesWith(comp)) continue; // Get comparison times startLead = std::max(startLead, comp->End.GetMS()); } cur->Start.SetMS(startLead); } // Compare to every line to see how far can lead-out be extended if (outVal) { int endLead = cur->End.GetMS() + outVal; for (int j=i+1; j<rows; j++) { AssDialogue *comp = Sorted[j]; // Check if they don't already collide (ignore it in that case) if (cur->CollidesWith(comp)) continue; // Get comparison times endLead = std::min(endLead, comp->Start.GetMS()); } cur->End.SetMS(endLead); } } } // Make adjacent if (adjsEnable->IsChecked()) { AssDialogue *prev = Sorted.front(); long adjsThres = 0; adjacentThres->GetValue().ToLong(&adjsThres); float bias = adjacentBias->GetValue() / 100.0; for (int i=1; i < rows; i++) { AssDialogue *cur = Sorted[i]; // Check if they don't collide if (cur->CollidesWith(prev)) continue; // Compare distance int curStart = cur->Start.GetMS(); int prevEnd = prev->End.GetMS(); int dist = curStart-prevEnd; if (dist > 0 && dist < adjsThres) { int setPos = prevEnd+int(dist*bias); cur->Start.SetMS(setPos); prev->End.SetMS(setPos); } prev = cur; } } // Keyframe snapping if (keysEnable->IsChecked()) { KeyFrames = c->videoController->GetKeyFrames(); KeyFrames.push_back(c->videoController->GetLength() - 1); long beforeStart = 0; long afterStart = 0; long beforeEnd = 0; long afterEnd = 0; keysStartBefore->GetValue().ToLong(&beforeStart); keysStartAfter->GetValue().ToLong(&afterStart); keysEndBefore->GetValue().ToLong(&beforeEnd); keysEndAfter->GetValue().ToLong(&afterEnd); for (int i=0; i<rows; i++) { AssDialogue *cur = Sorted[i]; // Get start/end frames int startF = c->videoController->FrameAtTime(cur->Start.GetMS(),agi::vfr::START); int endF = c->videoController->FrameAtTime(cur->End.GetMS(),agi::vfr::END); // Get closest for start int closest = GetClosestKeyFrame(startF); if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) { cur->Start.SetMS(c->videoController->TimeAtFrame(closest,agi::vfr::START)); } // Get closest for end closest = GetClosestKeyFrame(endF)-1; if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) { cur->End.SetMS(c->videoController->TimeAtFrame(closest,agi::vfr::END)); } } } // Update grid c->ass->Commit(_("timing processor"), AssFile::COMMIT_TIMES); }
////////////////////////////// // Actually process subtitles void DialogTimingProcessor::Process() { // Sort rows SortDialogues(); int rows = Sorted.size(); // Options long inVal = 0; long outVal = 0; leadIn->GetValue().ToLong(&inVal); leadOut->GetValue().ToLong(&outVal); bool addIn = hasLeadIn->IsChecked() && inVal; bool addOut = hasLeadOut->IsChecked() && outVal; // Add lead-in/out if (addIn || addOut) { // Variables AssDialogue *cur; AssDialogue *comp; int start,end; int startLead,endLead; int compStart,compEnd; // For each row for (int i=0;i<rows;i++) { // Get line and check if it's OK cur = GetSortedDialogue(i); // Set variables start = cur->Start.GetMS(); end = cur->End.GetMS(); if (addIn) startLead = start - inVal; else startLead = start; if (addOut) endLead = end + outVal; else endLead = end; // Compare to every previous line (yay for O(n^2)!) to see if it's OK to add lead-in if (addIn) { for (int j=0;j<i;j++) { comp = GetSortedDialogue(j); // Check if they don't already collide (ignore it in that case) if (cur->CollidesWith(comp)) continue; // Get comparison times compEnd = comp->End.GetMS(); // Limit lead-in if needed if (compEnd > startLead) startLead = compEnd; } } // Compare to every line to see how far can lead-out be extended if (addOut) { for (int j=i+1;j<rows;j++) { comp = GetSortedDialogue(j); // Check if they don't already collide (ignore it in that case) if (cur->CollidesWith(comp)) continue; // Get comparison times compStart = comp->Start.GetMS(); // Limit lead-in if needed if (compStart < endLead) endLead = compStart; } } // Set times cur->Start.SetMS(startLead); cur->End.SetMS(endLead); cur->UpdateData(); } } // Make adjascent if (adjsEnable->IsChecked()) { // Variables AssDialogue *cur; AssDialogue *prev = NULL; int curStart,prevEnd; long adjsThres = 0; int dist; // Get threshold adjascentThres->GetValue().ToLong(&adjsThres); // Get bias float bias = adjascentBias->GetValue() / 100.0; // For each row for (int i=0;i<rows;i++) { // Get line and check if it's OK cur = GetSortedDialogue(i); // Check if previous is OK if (!prev) { prev = cur; continue; } // Check if they don't collide if (cur->CollidesWith(prev)) continue; // Compare distance curStart = cur->Start.GetMS(); prevEnd = prev->End.GetMS(); dist = curStart-prevEnd; if (dist > 0 && dist < adjsThres) { int setPos = prevEnd+int(dist*bias); cur->Start.SetMS(setPos); cur->UpdateData(); prev->End.SetMS(setPos); prev->UpdateData(); } // Set previous prev = cur; } } // Keyframe snapping if (keysEnable->IsChecked()) { // Get keyframes KeyFrames = grid->video->KeyFrames; KeyFrames.Add(grid->video->length-1); // Variables int startF,endF; int closest; bool changed; AssDialogue *cur; // Get variables long beforeStart = 0; long afterStart = 0; long beforeEnd = 0; long afterEnd = 0; keysStartBefore->GetValue().ToLong(&beforeStart); keysStartAfter->GetValue().ToLong(&afterStart); keysEndBefore->GetValue().ToLong(&beforeEnd); keysEndAfter->GetValue().ToLong(&afterEnd); // For each row for (int i=0;i<rows;i++) { // Get line and check if it's OK cur = GetSortedDialogue(i); // Get start/end frames startF = VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true); endF = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false); changed = false; // Get closest for start closest = GetClosestKeyFrame(startF); if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) { cur->Start.SetMS(VFR_Output.GetTimeAtFrame(closest,true)); changed = true; } // Get closest for end closest = GetClosestKeyFrame(endF)-1; if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) { cur->End.SetMS(VFR_Output.GetTimeAtFrame(closest,false)); changed = true; } // Apply changes if (changed) { cur->UpdateData(); } } } // Update grid grid->ass->FlagAsModified(); grid->CommitChanges(); }