repeat play, in/out <> shortcuts, append to proj wording, cleanup
[goodguy/history.git] / cinelerra-5.1 / cinelerra / edits.C
index 7d152bc5ef0e59c50155e2a2a34bedbb78dd0863..9024af904728c9d1653c275796a7841d7ed6cb7c 100644 (file)
@@ -1,7 +1,7 @@
 
 /*
  * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
  *
  * 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
@@ -295,25 +295,20 @@ void Edits::resample(double old_rate, double new_rate)
        }
 }
 
-
-
-
-
-
-
-
-
-
-
-
-
+int Edits::is_glitch(Edit *edit)
+{
+       if( track->data_type != TRACK_AUDIO ) return 0;
+       int64_t threshold = edl->session->frame_rate > 0 ?
+               0.5 * edl->session->sample_rate / edl->session->frame_rate : 0;
+// audio edit shorter than .5 frames is a glitch
+       return edit->length < threshold ? 1 : 0;
+}
 
 int Edits::optimize()
 {
        int result = 1;
        Edit *current;
 
-
 //printf("Edits::optimize %d\n", __LINE__);
 // Sort edits by starting point
        while(result)
@@ -379,42 +374,55 @@ int Edits::optimize()
                        current = next;
                }
 
-//printf("Edits::optimize %d result=%d\n", __LINE__, result);
-// merge same files or transitions
-               if(track->data_type == TRACK_SUBTITLE ) continue;
-
-               for(current = first; !result && current && current->next; ) {
-                       Edit *next_edit = current->next;
-
-// printf("Edits::optimize %d %lld=%lld %d=%d %p=%p %p=%p\n",
-// __LINE__, current->startsource + current->length, next_edit->startsource,
-// current->channel, next_edit->channel, current->asset, next_edit->asset,
-// current->nested_edl, next_edit->nested_edl);
-
+// merge same files or transitions, and deglitch
+               if( !result && track->data_type != TRACK_SUBTITLE ) {
+                       current = first;
+                       if( current && !current->hard_right &&
+                           current->next && !current->next->hard_left &&
+                           is_glitch(current) ) {
+// if the first edit is a glitch, change it to silence
+                               current->asset = 0;
+                               current->nested_edl = 0;
+                       }
+                       Edit *next_edit = 0;
+                       for( ; current && (next_edit=current->next); current=NEXT ) {
+// both edges are not hard edges
+                               if( current->hard_right || next_edit->hard_left ) continue;
+// next edit is a glitch
+                               if( is_glitch(next_edit) )
+                                       break;
 // both edits are silence & not a plugin
-// source channels are identical, assets are identical
-                       if( (current->silence() && next_edit->silence() && !current->is_plugin) ||
-                           (current->startsource + current->length == next_edit->startsource &&
-                            current->channel == next_edit->channel &&
-                            current->asset == next_edit->asset &&
-                            current->nested_edl == next_edit->nested_edl)) {
-//printf("Edits::optimize %d\n", __LINE__);
-                               current->length += next_edit->length;
-                               remove(next_edit);
-                               result = 1;
-                               break;
-                       }
-
-                       current = current->next;
+                               if( !current->is_plugin && current->silence() &&
+                                   !next_edit->is_plugin && next_edit->silence() )
+                                       break;
+// source channels are identical & assets are identical
+                               if( !result && current->channel == next_edit->channel &&
+                                   current->asset == next_edit->asset &&
+                                   current->nested_edl == next_edit->nested_edl ) {
+//  and stop and start in the same frame
+                                       int64_t current_end = current->startsource + current->length;
+                                       int64_t next_start = next_edit->startsource;
+                                       if( current_end == next_start ||
+                                           EQUIV(edl->frame_align(track->from_units(current_end), 1),
+                                                 edl->frame_align(track->from_units(next_start), 1)) )
+                                               break;
+                               }
+                       }
+                       if( next_edit ) {
+                               int64_t current_start = current->startproject;
+                               int64_t next_end = next_edit->startproject + next_edit->length;
+                               current->length = next_end - current_start;
+                               remove(next_edit);
+                               result = 1;
+                       }
                }
 
-               if(last && last->silence()) {
+               if( last && last->silence() && !last->transition ) {
                        delete last;
                        result = 1;
                }
        }
 
-//track->dump();
        return 0;
 }
 
@@ -592,7 +600,7 @@ void Edits::clear(int64_t start, int64_t end)
                end = this->length();
        }
 
-       if(edit1 != edit2)
+       if( edit1 && edit2 && edit1 != edit2)
        {
 // in different edits
 
@@ -657,8 +665,7 @@ int Edits::clear_handle(double start, double end,
 
                if(current_edit->asset && current_edit->next->asset) {
 
-                       if(current_edit->asset->equivalent(*current_edit->next->asset,
-                               0, 0)) {
+                       if(current_edit->asset->equivalent(*current_edit->next->asset, 0, 0, edl)) {
 
 // Got two consecutive edits in same source
                                if(edl->equivalent(track->from_units(current_edit->next->startproject),
@@ -769,7 +776,7 @@ int Edits::modify_handles(double oldposition, double newposition, int currentend
                                else
                                {
 // move end of edit out
-//printf("Edits::modify_handle 6\n");
+//printf("Edits::modify_handle %d edit_mode=%d\n", __LINE__, edit_mode);
                                        current_edit->shift_end_out(edit_mode,
                                                track->to_units(newposition, 0),
                                                track->to_units(oldposition, 0),
@@ -820,7 +827,7 @@ Edit *Edits::create_silence(int64_t start, int64_t end)
        }
        return new_edit;
 }
-                                    
+
 Edit* Edits::shift(int64_t position, int64_t difference)
 {
        Edit *new_edit = split_edit(position);