rework speed timeline picons/waves
[goodguy/history.git] / cinelerra-5.1 / cinelerra / indexfile.C
index b62379b2c71108630c1d5f23fb33464da23c7462..3d21d2af73b399e03967c8f7a91b66c02048dfe9 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "arender.h"
 #include "asset.h"
+#include "automation.h"
+#include "autos.h"
 #include "bcsignals.h"
 #include "bctimer.h"
 #include "cache.h"
@@ -33,6 +35,8 @@
 #include "file.h"
 #include "filesystem.h"
 #include "filexml.h"
+#include "floatauto.h"
+#include "floatautos.h"
 #include "indexable.h"
 #include "indexfile.h"
 #include "indexstate.h"
@@ -103,12 +107,12 @@ static int udf_volume_id(const char *path, char *fname)
                if( strncmp(ISO_STANDARD_ID,id.id,sizeof(id.id)) ) continue;
                // look for volume_id
                if( !isalnum(id.volume_id[0]) ) continue;
-               char *bp = &id.volume_id[0], *cp = fname;
+               char *bp = (char*)&id.volume_id[0], *cp = fname;
                for( int i=0; i<(int)sizeof(id.volume_id); ++i ) *cp++ = *bp++;
                while( --cp>=fname && *cp==' ' ) *cp = 0;
                if( !*fname ) continue;
                // fname = volume_id _ creation_date
-               ++cp;  *cp++ = '_';  bp = &id.creation_date[0];
+               ++cp;  *cp++ = '_';  bp = (char*)&id.creation_date[0];
                for( int i=0; i<(int)sizeof(id.creation_date)-1; ++i ) {
                        if( !isdigit(*bp) ) break;
                        *cp++ = *bp++;
@@ -141,7 +145,6 @@ IndexFile::IndexFile(MWindow *mwindow,
        this->mwindow = mwindow;
        this->indexable = indexable;
        redraw_timer = new Timer;
-
        if(indexable)
        {
                indexable->add_user();
@@ -433,6 +436,9 @@ SET_TRACE
 
 // open the source file
        if(open_source()) return 1;
+       source_channels = indexable->get_audio_channels();
+       source_samplerate = indexable->get_sample_rate();
+       source_length = indexable->get_audio_samples();
 
 SET_TRACE
 
@@ -650,160 +656,134 @@ SET_TRACE
                mwindow->edl->local_session->view_start[pane_number];
 
 // samples in segment to draw relative to asset
-       double asset_over_session = (double)source_samplerate /
-               mwindow->edl->session->sample_rate;
-       int64_t startsource = (int64_t)(((pixmap->pixmap_x - virtual_edit_x + x) *
-               mwindow->edl->local_session->zoom_sample +
-               edit->startsource) *
-               asset_over_session);
-// just in case we get a numerical error
-       if (startsource < 0) startsource = 0;
-       int64_t length = (int64_t)(w *
-               mwindow->edl->local_session->zoom_sample *
-               asset_over_session);
-       int64_t lengthindex = length / index_state->index_zoom * 2;
-       int64_t startindex = startsource / index_state->index_zoom * 2;
-// length of index to read in floats
+       FloatAutos *speed_autos = !edit->track->has_speed() ? 0 :
+               (FloatAutos *)edit->track->automation->autos[AUTOMATION_SPEED];
+       double project_zoom = mwindow->edl->local_session->zoom_sample;
+       int64_t edit_position = (x + pixmap->pixmap_x - virtual_edit_x) * project_zoom;
+       int64_t start_position = edit->startsource;
+       start_position += !speed_autos ? edit_position :
+               speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
+       int64_t end_position = edit->startsource;
+       edit_position = (x + w + pixmap->pixmap_x - virtual_edit_x) * project_zoom;
+       end_position += !speed_autos ? edit_position :
+               speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
+       double session_sample_rate = mwindow->edl->session->sample_rate;
+       double asset_over_session = (double)indexable->get_sample_rate() / session_sample_rate;
+       int64_t start_source = start_position * asset_over_session;
+       if( start_source < 0 ) start_source = 0;
+       int64_t start_index = start_source / index_state->index_zoom;
+       int64_t end_source = end_position * asset_over_session;
+       if( end_source < 0 ) end_source = 0;
+       int64_t end_index = end_source / index_state->index_zoom;
+// start/length of index to read in floats
+       start_index *= 2;  end_index *= 2;
 // length of index available in floats
-       int64_t endindex = index_state->index_status == INDEX_BUILDING ?
+       int64_t size_index = index_state->index_status == INDEX_BUILDING ?
                index_state->get_channel_used(edit->channel) * 2 :
                index_state->get_index_size(edit->channel);
 // Clamp length of index to read by available data
-       if(startindex + lengthindex >= endindex )
-               lengthindex = endindex - startindex;
-       if( lengthindex <= 0 ) return 0;
+       if( end_index >= size_index ) end_index = size_index;
+       int64_t length_index = end_index - start_index;
+       if( length_index <= 0 ) return 0;
 
-// Actual length read from file in bytes
-       int64_t length_read;
 // Start and length of fragment to read from file in bytes.
-       int64_t startfile, lengthfile;
        float *buffer = 0;
        int buffer_shared = 0;
        int center_pixel = mwindow->edl->local_session->zoom_track / 2;
        if( mwindow->edl->session->show_titles )
                center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
-       //int miny = center_pixel - mwindow->edl->local_session->zoom_track / 2;
-       //int maxy = center_pixel + mwindow->edl->local_session->zoom_track / 2;
-       int x1 = 0, y1, y2;
-// get zoom_sample relative to index zoomx
-       double index_frames_per_pixel = mwindow->edl->local_session->zoom_sample /
-               index_state->index_zoom *
-               asset_over_session;
-
-
 
-       if(index_state->index_status == INDEX_BUILDING)
-       {
+       if( index_state->index_status == INDEX_BUILDING ) {
 // index is in RAM, being built
                buffer = index_state->get_channel_buffer(edit->channel);
                if( !buffer ) return 0;
-               buffer += startindex;
+               buffer += start_index;
                buffer_shared = 1;
        }
-       else
-       {
-// add channel offset
-               startindex += index_state->get_index_offset(edit->channel);
-// index is stored in a file
-               buffer = new float[lengthindex + 1];
-               buffer_shared = 0;
-               startfile = index_state->index_start + startindex * sizeof(float);
-               lengthfile = lengthindex * sizeof(float);
-               length_read = 0;
-
-               if(startfile < file_length)
-               {
-                       fseek(fd, startfile, SEEK_SET);
-
-                       length_read = lengthfile;
-                       if(startfile + length_read > file_length)
-                               length_read = file_length - startfile;
-
-                       (void)fread(buffer, length_read + sizeof(float), 1, fd);
-               }
-
-               if(length_read < lengthfile) {
-                       int pos = length_read / sizeof(float);
-                       int file_length = lengthfile / sizeof(float);
-                       while( pos < file_length ) buffer[pos++] = 0;
+       else {
+               buffer = new float[length_index + 1];
+               int64_t length_buffer = length_index * sizeof(float);
+// add file/channel offset
+               int64_t index_offset = index_state->get_index_offset(edit->channel);
+               int64_t file_offset = (index_offset + start_index) * sizeof(float);
+               int64_t file_pos = index_state->index_start + file_offset;
+               int64_t read_length = file_length - file_pos;
+               if( read_length > length_buffer )
+                       read_length = length_buffer;
+               int64_t length_read = 0;
+               if( read_length > 0 ) {
+                       fseek(fd, file_pos, SEEK_SET);
+                       length_read = fread(buffer, 1, read_length + sizeof(float), fd);
+                       length_read &= ~(sizeof(float)-1);
                }
+               if( (read_length-=length_read) > 0 )
+                       memset((char*)buffer + length_read, 0, read_length);
+               buffer_shared = 0;
        }
 
        canvas->set_color(mwindow->theme->audio_color);
 
-       double current_frame = 0;
-       float highsample = buffer[0];
-       float lowsample = buffer[1];
        int prev_y1 = center_pixel;
        int prev_y2 = center_pixel;
        int first_frame = 1;
        int zoom_y = mwindow->edl->local_session->zoom_y, zoom_y2 = zoom_y / 2;
        int max_y = center_pixel + zoom_y2 - 1;
+       edit_position = (x + pixmap->pixmap_x - virtual_edit_x) * project_zoom;
+       int64_t speed_position = edit->startsource;
+       speed_position += !speed_autos ? edit_position :
+               speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
+       int64_t source_position  = speed_position * asset_over_session;
+       int64_t index_position = source_position / index_state->index_zoom;
+       int64_t i = 2 * index_position - start_index;
+       CLAMP(i, 0, length_index);
 SET_TRACE
 
-       for(int bufferposition = 0;
-               bufferposition < lengthindex;
-               bufferposition += 2)
-       {
-               if(current_frame >= index_frames_per_pixel)
-               {
+       for( int64_t x1=0; x1<w && i < length_index; ++x1 ) {
+               float highsample = buffer[i];  ++i;
+               float lowsample = buffer[i];   ++i;
+               int x2 = x1 + x + 1;
+               edit_position = (x2 + pixmap->pixmap_x - virtual_edit_x) * project_zoom;
+               int64_t speed_position = edit->startsource;
+               speed_position += !speed_autos ? edit_position :
+                       speed_autos->automation_integral(edit->startproject, edit_position, PLAY_FORWARD);
+               source_position  = speed_position * asset_over_session;
+               index_position = source_position / index_state->index_zoom;
+               int64_t k = 2 * index_position - start_index;
+               CLAMP(k, 0, length_index);
+               while( i < k ) {
+                       highsample = MAX(highsample, buffer[i]); ++i;
+                       lowsample = MIN(lowsample, buffer[i]);   ++i;
+               }
 
-                       int y1 = (int)(center_pixel - highsample * zoom_y2);
-                       int y2 = (int)(center_pixel - lowsample * zoom_y2);
-                       CLAMP(y1, 0, max_y);  int next_y1 = y1;
-                       CLAMP(y2, 0, max_y);  int next_y2 = y2;
-//printf("draw_line (%f,%f) = %d,%d,  %d,%d\n", lowsample, highsample, x1 + x, y1, x1 + x, y2);
+               int y1 = (int)(center_pixel - highsample * zoom_y2);
+               int y2 = (int)(center_pixel - lowsample * zoom_y2);
+               CLAMP(y1, 0, max_y);  int next_y1 = y1;
+               CLAMP(y2, 0, max_y);  int next_y2 = y2;
+//printf("draw_line (%f,%f) = %d,%d,  %d,%d\n", lowsample, highsample, x2, y1, x2, y2);
 
 //SET_TRACE
 // A different algorithm has to be used if it's 1 sample per pixel and the
 // index is used.  Now the min and max values are equal so we join the max samples.
-                       if(mwindow->edl->local_session->zoom_sample == 1)
-                       {
-                               canvas->draw_line(x1 + x - 1, prev_y1, x1 + x, y1, pixmap);
-                       }
-                       else
-                       {
+               if(mwindow->edl->local_session->zoom_sample == 1) {
+                       canvas->draw_line(x2 - 1, prev_y1, x2, y1, pixmap);
+               }
+               else {
 // Extend line height if it doesn't connect to previous line
-                               if(!first_frame)
-                               {
-                                       if(y1 > prev_y2) y1 = prev_y2 + 1;
-                                       if(y2 < prev_y1) y2 = prev_y1 - 1;
-                               }
-                               else
-                               {
-                                       first_frame = 0;
-                               }
-
-
-
-                               canvas->draw_line(x1 + x, y1, x1 + x, y2, pixmap);
+                       if(!first_frame) {
+                               if(y1 > prev_y2) y1 = prev_y2 + 1;
+                               if(y2 < prev_y1) y2 = prev_y1 - 1;
                        }
-                       current_frame -= index_frames_per_pixel;
-                       x1++;
-                       prev_y1 = next_y1;
-                       prev_y2 = next_y2;
-                       highsample = buffer[bufferposition];
-                       lowsample = buffer[bufferposition + 1];
+                       else {
+                               first_frame = 0;
+                       }
+                       canvas->draw_line(x2, y1, x2, y2, pixmap);
                }
-
-               current_frame++;
-               highsample = MAX(highsample, buffer[bufferposition]);
-               lowsample = MIN(lowsample, buffer[bufferposition + 1]);
-       }
-SET_TRACE
-
-// Get last column
-       if(current_frame)
-       {
-               y1 = (int)(center_pixel - highsample * zoom_y2);
-               y2 = (int)(center_pixel - lowsample * zoom_y2);
-               canvas->draw_line(x1 + x, y1, x1 + x, y2, pixmap);
+               prev_y1 = next_y1;
+               prev_y2 = next_y2;
        }
 
 SET_TRACE
 
-
-
        if(!buffer_shared) delete [] buffer;
 SET_TRACE
        if(debug) printf("IndexFile::draw_index %d\n", __LINE__);
@@ -866,16 +846,19 @@ int IndexFile::read_info(Indexable *test_indexable)
 // Read the file format & index state.
                if(test_indexable->is_asset)
                {
-                       Asset *asset = (Asset*)test_indexable;
+                       Asset *test_asset = (Asset *)test_indexable;
+                       Asset *asset = new Asset;
                        asset->read(&xml);
-
+                       int ret = 0;
 //printf("IndexFile::read_info %d %f\n", __LINE__, asset->get_frame_rate());
 
-                       if(asset->format == FILE_UNKNOWN)
-                       {
+                       if( asset->format == FILE_UNKNOWN ||
+                           test_asset->format != asset->format ) {
 if(debug) printf("IndexFile::read_info %d\n", __LINE__);
-                               return 1;
+                               ret = 1;
                        }
+                       asset->remove_user();
+                       if( ret ) return ret;
                }
                else
                {