double TimeBar::get_edl_length() { edl_length = 0; if(get_edl()) { //printf("TimeBar::get_edl_length 1 %f\n", get_edl()->tracks->total_playable_length()); edl_length = get_edl()->tracks->total_playable_length(); } //printf("TimeBar::get_edl_length 2\n"); if(!EQUIV(edl_length, 0)) { //printf("TimeBar::get_edl_length 3\n"); time_per_pixel = edl_length / get_w(); //printf("TimeBar::get_edl_length 4\n"); } else { time_per_pixel = 0; } //printf("TimeBar::get_edl_length 5\n"); return edl_length; }
void PlayTransport::change_position(double position) { EDL *edl = get_edl(); if( !edl ) return; int prev_command = engine->command->command; // stop transport if( prev_command != STOP && prev_command != COMMAND_NONE && prev_command != SINGLE_FRAME_FWD && prev_command != SINGLE_FRAME_REWIND ) { engine->que->send_command(STOP, CHANGE_NONE, 0, 0, 0, 0); engine->interrupt_playback(0); } mwindow->gui->lock_window("PlayTransport::change_position"); mwindow->goto_position(position); mwindow->gui->unlock_window(); // restart command switch(prev_command) { case FAST_REWIND: case NORMAL_REWIND: case SLOW_REWIND: case SLOW_FWD: case NORMAL_FWD: case FAST_FWD: engine->que->send_command(prev_command, CHANGE_NONE, get_edl(), 1, 1, using_inout); } }
void TimeBar::update(int flush) { draw_time(); // Need to redo these when range is drawn to get the background updated. update_labels(); update_points(); EDL *edl = get_edl(); int64_t pixel = -1; // Draw highlight position if(edl && (highlighted || current_operation == TIMEBAR_DRAG) && get_cursor_x() >= 0 && get_cursor_y() < get_w()) { //printf("TimeBar::update %d %d\n", __LINE__, get_cursor_x()); double position = pixel_to_position(get_cursor_x()); position = get_edl()->align_to_frame(position, 0); pixel = position_to_pixel(position); update_clock(position); } if(pixel < 0) { double position = test_highlight(); if(position >= 0) pixel = position_to_pixel(position); } if(pixel >= 0 && pixel < get_w()) { set_color(mwindow->theme->timebar_cursor_color); set_line_dashes(1); //printf("TimeBar::update %d pane=%d pixel=%jd\n", __LINE__, pane->number, pixel); draw_line(pixel, 0, pixel, get_h()); set_line_dashes(0); } if(edl) { int64_t pixel = position_to_pixel( edl->local_session->get_selectionstart(1)); // Draw insertion point position. set_color(mwindow->theme->timebar_cursor_color); draw_line(pixel, 0, pixel, get_h()); } update_highlights(); // Get the labels to show show_window(0); flash(flush); //printf("TimeBar::update %d this=%p %d\n", __LINE__, this, current_operation); }
void VWindow::goto_start() { if(get_edl()) { get_edl()->local_session->set_selectionstart(0); get_edl()->local_session->set_selectionend(0); update_position(CHANGE_NONE, 0, 1); } }
void VWindow::goto_end() { if(get_edl()) { double position = get_edl()->tracks->total_length(); get_edl()->local_session->set_selectionstart(position); get_edl()->local_session->set_selectionend(position); update_position(CHANGE_NONE, 0, 1); } }
void VWindow::change_source() { //printf("VWindow::change_source() 1 %p\n", mwindow->edl->vwindow_edl); if(mwindow->edl->vwindow_edl) { gui->change_source(get_edl(), get_edl()->local_session->clip_title); update_position(CHANGE_ALL, 1, 1); } else { if(asset) Garbage::delete_object(asset); asset = 0; mwindow->edl->vwindow_edl_shared = 0; } }
void TimeBar::draw_range() { int x1 = 0, x2 = get_w(); //printf("TimeBar::draw_range %d %p\n", __LINE__, get_edl()); if(get_edl()) { // get_preview_pixels(x1, x2); // // //printf("TimeBar::draw_range %f %d %d\n", edl_length, x1, x2); // draw_3segmenth(0, 0, x1, mwindow->theme->timebar_view_data); draw_top_background(get_parent(), x1, 0, x2 - x1, get_h()); // draw_3segmenth(x2, 0, get_w() - x2, mwindow->theme->timebar_view_data); // // set_color(BLACK); // draw_line(x1, 0, x1, get_h()); // draw_line(x2, 0, x2, get_h()); // // EDL *edl = get_edl(); // if(edl) // { // int64_t pixel = position_to_pixel( // edl->local_session->get_selectionstart(1)); // // Draw insertion point position if this timebar belongs to a window which // // has something other than the master EDL. // set_color(mwindow->theme->timebar_cursor_color); // draw_line(pixel, 0, pixel, get_h()); // } } else draw_top_background(get_parent(), 0, 0, get_w(), get_h()); }
void VWindow::update_position(int change_type, int use_slider, int update_slider) { EDL *edl = get_edl(); if(edl) { Asset *asset = edl->assets->first; if(use_slider) { edl->local_session->set_selectionstart(gui->slider->get_value()); edl->local_session->set_selectionend(gui->slider->get_value()); } if(update_slider) { gui->slider->set_position(); } playback_engine->que->send_command(CURRENT_FRAME, change_type, edl, 1); gui->clock->update(edl->local_session->get_selectionstart(1) + asset->tcstart / (asset->video_data ? asset->frame_rate : asset->sample_rate)); } }
void VWindow::set_outpoint() { EDL *edl = get_edl(); if(edl) { edl->set_outpoint(edl->local_session->get_selectionstart(1)); gui->timebar->update(); } }
void VWindow::clear_outpoint() { EDL *edl = get_edl(); if(edl) { edl->local_session->unset_outpoint(); gui->timebar->update(); } }
double VTimeBar::pixel_to_position(int pixel) { double start = 0, length = 0; EDL *edl = get_edl(); if(edl) { start = edl->local_session->preview_start; if(start >= 0) length = edl->local_session->preview_end - start; } if(length <= 0) length = get_edl_length(); return start + (double)pixel * length / get_w(); }
void VTimeBar::select_label(double position) { EDL *edl = get_edl(); if(edl) { unlock_window(); gui->transport->handle_transport(STOP, 1, 0, 0); lock_window(); position = mwindow->edl->align_to_frame(position, 1); if(shift_down()) { if(position > edl->local_session->get_selectionend(1) / 2 + edl->local_session->get_selectionstart(1) / 2) { edl->local_session->set_selectionend(position); } else { edl->local_session->set_selectionstart(position); } } else { edl->local_session->set_selectionstart(position); edl->local_session->set_selectionend(position); } // Que the CWindow gui->vwindow->update_position(CHANGE_NONE, 0, 1, 0); update(1); } }
void VWindow::copy() { EDL *edl = get_edl(); if(edl) { double start = edl->local_session->get_selectionstart(); double end = edl->local_session->get_selectionend(); FileXML file; edl->copy(start, end, 0, 0, 0, &file, mwindow->plugindb, "", 1); mwindow->gui->lock_window(); mwindow->gui->get_clipboard()->to_clipboard(file.string, strlen(file.string), SECONDARY_SELECTION); mwindow->gui->unlock_window(); } }
void PlayTransport::handle_transport(int command, int wait_tracking, int use_inout, int update_refresh) { if(!get_edl()) return; // Stop requires transferring the output buffer to a refresh buffer. int do_stop = 0; //printf("PlayTransport::handle_transport 1 %d\n", command); int prev_command = engine->command->command; int prev_direction = engine->command->get_direction(); int prev_single_frame = engine->command->single_frame(); // Dispatch command switch(command) { // Commands that play back case FAST_REWIND: case NORMAL_REWIND: case SLOW_REWIND: case SINGLE_FRAME_REWIND: case SINGLE_FRAME_FWD: case SLOW_FWD: case NORMAL_FWD: case FAST_FWD: // Same direction pressed twice. Stop if(prev_command == command && !prev_single_frame) { do_stop = 1; } else // Resume or change direction if(prev_command != STOP && prev_command != COMMAND_NONE && prev_command != SINGLE_FRAME_FWD && prev_command != SINGLE_FRAME_REWIND) { engine->que->send_command(STOP, CHANGE_NONE, 0, 0, 0, 0); engine->interrupt_playback(wait_tracking); engine->que->send_command(command, CHANGE_NONE, get_edl(), 1, 1, use_inout); } else // Start from scratch { engine->que->send_command(command, CHANGE_NONE, get_edl(), 1, 0, use_inout); } break; // Commands that stop case STOP: do_stop = 1; break; case REWIND: case GOTO_END: engine->que->send_command(STOP, CHANGE_NONE, 0, 0, 0, 0); engine->interrupt_playback(wait_tracking); break; } if(do_stop) { engine->que->send_command(STOP, CHANGE_NONE, 0, 0, 0, 0); engine->interrupt_playback(wait_tracking); // This is necessary to get an OpenGL output buffer // printf("PlayTransport::handle_transport 2 update_refresh=%d prev_command=%d prev_direction=%d\n", // update_refresh, prev_command, prev_direction); if(!prev_single_frame && update_refresh && prev_command != STOP && prev_command != COMMAND_NONE) { engine->que->send_command( (prev_direction == PLAY_FORWARD) ? SINGLE_FRAME_REWIND : SINGLE_FRAME_FWD, CHANGE_NONE, get_edl(), 1, 0, 0); } } }
int AModule::render(Samples *buffer, int64_t input_len, int64_t start_position, int direction, int sample_rate, int use_nudge) { int64_t edl_rate = get_edl()->session->sample_rate; const int debug = 0; if(debug) printf("AModule::render %d\n", __LINE__); if(use_nudge) start_position += track->nudge * sample_rate / edl_rate; AEdit *playable_edit; int64_t end_position; if(direction == PLAY_FORWARD) end_position = start_position + input_len; else end_position = start_position - input_len; int buffer_offset = 0; int result = 0; // // Flip range around so the source is always read forward. // if(direction == PLAY_REVERSE) // { // start_project -= input_len; // end_position -= input_len; // } // Clear buffer bzero(buffer->get_data(), input_len * sizeof(double)); // The EDL is normalized to the requested sample rate because // the requested rate may be the project sample rate and a sample rate // might as well be directly from the source rate to the requested rate. // Get first edit containing the range if(direction == PLAY_FORWARD) playable_edit = (AEdit*)track->edits->first; else playable_edit = (AEdit*)track->edits->last; if(debug) printf("AModule::render %d\n", __LINE__); while(playable_edit) { int64_t edit_start = playable_edit->startproject; int64_t edit_end = playable_edit->startproject + playable_edit->length; // Normalize to requested rate edit_start = edit_start * sample_rate / edl_rate; edit_end = edit_end * sample_rate / edl_rate; if(direction == PLAY_FORWARD) { if(start_position < edit_end && end_position > edit_start) { break; } playable_edit = (AEdit*)playable_edit->next; } else { if(end_position < edit_end && start_position > edit_start) { break; } playable_edit = (AEdit*)playable_edit->previous; } } if(debug) printf("AModule::render %d\n", __LINE__); // Fill output one fragment at a time while(start_position != end_position) { int64_t fragment_len = input_len; if(debug) printf("AModule::render %d " _LD " " _LD "\n", __LINE__, start_position, end_position); // Clamp fragment to end of input if(direction == PLAY_FORWARD && start_position + fragment_len > end_position) fragment_len = end_position - start_position; else if(direction == PLAY_REVERSE && start_position - fragment_len < end_position) fragment_len = start_position - end_position; if(debug) printf("AModule::render %d " _LD "\n", __LINE__, fragment_len); // Normalize position here since update_transition is a boolean operation. update_transition(start_position * edl_rate / sample_rate, PLAY_FORWARD); if(playable_edit) { AEdit *previous_edit = (AEdit*)playable_edit->previous; // Normalize EDL positions to requested rate int64_t edit_startproject = playable_edit->startproject; int64_t edit_endproject = playable_edit->startproject + playable_edit->length; int64_t edit_startsource = playable_edit->startsource; if(debug) printf("AModule::render %d " _LD "\n", __LINE__, fragment_len); edit_startproject = edit_startproject * sample_rate / edl_rate; edit_endproject = edit_endproject * sample_rate / edl_rate; edit_startsource = edit_startsource * sample_rate / edl_rate; if(debug) printf("AModule::render %d " _LD "\n", __LINE__, fragment_len); // Clamp fragment to end of edit if(direction == PLAY_FORWARD && start_position + fragment_len > edit_endproject) fragment_len = edit_endproject - start_position; else if(direction == PLAY_REVERSE && start_position - fragment_len < edit_startproject) fragment_len = start_position - edit_startproject; if(debug) printf("AModule::render %d " _LD "\n", __LINE__, fragment_len); // Clamp to end of transition int64_t transition_len = 0; if(transition && previous_edit) { transition_len = transition->length * sample_rate / edl_rate; if(direction == PLAY_FORWARD && start_position < edit_startproject + transition_len && start_position + fragment_len > edit_startproject + transition_len) fragment_len = edit_startproject + transition_len - start_position; else if(direction == PLAY_REVERSE && start_position > edit_startproject + transition_len && start_position - fragment_len < edit_startproject + transition_len) fragment_len = start_position - edit_startproject - transition_len; } if(debug) printf("AModule::render %d buffer_offset=%d fragment_len=" _LD "\n", __LINE__, buffer_offset, fragment_len); Samples output(buffer); output.set_offset(output.get_offset() + buffer_offset); if(import_samples(playable_edit, start_position, edit_startproject, edit_startsource, direction, sample_rate, &output, fragment_len)) result = 1; if(debug) printf("AModule::render %d\n", __LINE__); // Read transition into temp and render if(transition && previous_edit) { int64_t previous_startproject = previous_edit->startproject * sample_rate / edl_rate; int64_t previous_startsource = previous_edit->startsource * sample_rate / edl_rate; // Allocate transition temp size int transition_fragment_len = fragment_len; if(direction == PLAY_FORWARD && fragment_len + start_position > edit_startproject + transition_len) fragment_len = edit_startproject + transition_len - start_position; // Read into temp buffers // Temp + master or temp + temp ? temp + master if(transition_temp && transition_temp->get_allocated() < fragment_len) { delete transition_temp; transition_temp = 0; } if(!transition_temp) { transition_temp = new Samples(fragment_len); } if(debug) printf("AModule::render %d " _LD "\n", __LINE__, fragment_len); if(transition_fragment_len > 0) { // Previous_edit is always the outgoing segment, regardless of direction import_samples(previous_edit, start_position, previous_startproject, previous_startsource, direction, sample_rate, transition_temp, transition_fragment_len); int64_t current_position; // Reverse buffers here so transitions always render forward. if(direction == PLAY_REVERSE) { Resample::reverse_buffer(output.get_data(), transition_fragment_len); Resample::reverse_buffer(transition_temp->get_data(), transition_fragment_len); current_position = start_position - transition_fragment_len - edit_startproject; } else { current_position = start_position - edit_startproject; } transition_server->process_transition( transition_temp, &output, current_position, transition_fragment_len, transition->length); // Reverse output buffer here so transitions always render forward. if(direction == PLAY_REVERSE) Resample::reverse_buffer(output.get_data(), transition_fragment_len); } } if(debug) printf("AModule::render %d start_position=" _LD " end_position=" _LD " fragment_len=" _LD "\n", __LINE__, start_position, end_position, fragment_len); if(direction == PLAY_REVERSE) { if(playable_edit && start_position - fragment_len <= edit_startproject) playable_edit = (AEdit*)playable_edit->previous; } else { if(playable_edit && start_position + fragment_len >= edit_endproject) playable_edit = (AEdit*)playable_edit->next; } } if(fragment_len > 0) { buffer_offset += fragment_len; if(direction == PLAY_FORWARD) start_position += fragment_len; else start_position -= fragment_len; } } if(debug) printf("AModule::render %d\n", __LINE__); return result; }
int AModule::import_samples(AEdit *edit, int64_t start_project, int64_t edit_startproject, int64_t edit_startsource, int direction, int sample_rate, Samples *buffer, int64_t fragment_len) { int result = 0; // start in EDL samplerate int64_t start_source = start_project - edit_startproject + edit_startsource; // fragment size adjusted for speed curve int64_t speed_fragment_len = fragment_len; // boundaries of input fragment required for speed curve double max_position = 0; double min_position = 0; double speed_position = edit_startsource; // position in source where speed curve starts reading double speed_position1 = speed_position; // position in source where speed curve finishes double speed_position2 = speed_position; // Need speed curve processing int have_speed = 0; // Temporary buffer for rendering speed curve Samples *speed_buffer = buffer; const int debug = 0; if(debug) printf("AModule::import_samples %d edit=%p nested_edl=%p\n", __LINE__, edit, nested_edl); if(nested_edl && edit->channel >= nested_edl->session->audio_channels) return 1; if(debug) printf("AModule::import_samples %d\n", __LINE__); this->channel = edit->channel; if(debug) printf("AModule::import_samples %d speed_fragment_len=%ld\n", __LINE__, speed_fragment_len); // apply speed curve to source position so the timeline agrees with the playback if(track->has_speed()) { // get speed adjusted position from start of edit. FloatAuto *previous = 0; FloatAuto *next = 0; FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; for(int64_t i = edit_startproject; i < start_project; i++) { double speed = speed_autos->get_value(i, PLAY_FORWARD, previous, next); speed_position += speed; } speed_position1 = speed_position; // calculate boundaries of input fragment required for speed curve max_position = speed_position; min_position = speed_position; for(int64_t i = start_project; i < start_project + fragment_len; i++) { double speed = speed_autos->get_value(i, PLAY_FORWARD, previous, next); speed_position += speed; if(speed_position > max_position) max_position = speed_position; if(speed_position < min_position) min_position = speed_position; } speed_position2 = speed_position; if(speed_position2 < speed_position1) { max_position += 1.0; // min_position -= 1.0; speed_fragment_len = (int64_t)(max_position - min_position); } else { max_position += 1.0; speed_fragment_len = (int64_t)(max_position - min_position); } printf("AModule::import_samples %d %f %f %f %f\n", __LINE__, min_position, max_position, speed_position1, speed_position2); // new start of source to read from file start_source = (int64_t)min_position; have_speed = 1; // swap in the temp buffer if(speed_temp && speed_temp->get_allocated() < speed_fragment_len) { delete speed_temp; speed_temp = 0; } if(!speed_temp) { speed_temp = new Samples(speed_fragment_len); } speed_buffer = speed_temp; } if(speed_fragment_len == 0) return 1; // Source is a nested EDL if(edit->nested_edl) { int command; asset = 0; if(direction == PLAY_REVERSE) command = NORMAL_REWIND; else command = NORMAL_FWD; if(debug) printf("AModule::import_samples %d\n", __LINE__); if(!nested_edl || nested_edl->id != edit->nested_edl->id) { nested_edl = edit->nested_edl; if(nested_renderengine) { delete nested_renderengine; nested_renderengine = 0; } if(!nested_command) { nested_command = new TransportCommand; } if(!nested_renderengine) { nested_command->command = command; nested_command->get_edl()->copy_all(nested_edl); nested_command->change_type = CHANGE_ALL; nested_command->realtime = renderengine->command->realtime; nested_renderengine = new RenderEngine(0, get_preferences(), 0, renderengine ? renderengine->channeldb : 0, 1); nested_renderengine->set_acache(get_cache()); // Must use a private cache for the audio // if(!cache) // { // cache = new CICache(get_preferences()); // private_cache = 1; // } // nested_renderengine->set_acache(cache); nested_renderengine->arm_command(nested_command); } } if(debug) printf("AModule::import_samples %d speed_fragment_len=%d\n", __LINE__, (int)speed_fragment_len); // Allocate output buffers for all channels for(int i = 0; i < nested_edl->session->audio_channels; i++) { if(nested_allocation < speed_fragment_len) { delete nested_output[i]; nested_output[i] = 0; } if(!nested_output[i]) { nested_output[i] = new Samples(speed_fragment_len); } } if(debug) printf("AModule::import_samples %d\n", __LINE__); if(nested_allocation < speed_fragment_len) nested_allocation = speed_fragment_len; // Update direction command nested_renderengine->command->command = command; // Render the segment if(!nested_renderengine->arender) { bzero(speed_buffer->get_data(), speed_fragment_len * sizeof(double)); } else if(sample_rate != nested_edl->session->sample_rate) { // Read through sample rate converter. if(!resample) { resample = new AModuleResample(this); } if(debug) printf("AModule::import_samples %d %d %d\n", __LINE__, (int)sample_rate, (int)nested_edl->session->sample_rate); result = resample->resample(speed_buffer, speed_fragment_len, nested_edl->session->sample_rate, sample_rate, start_source, direction); // Resample reverses to keep it running forward. if(debug) printf("AModule::import_samples %d\n", __LINE__); } else { // Render without resampling if(debug) printf("AModule::import_samples %d\n", __LINE__); result = nested_renderengine->arender->process_buffer( nested_output, speed_fragment_len, start_source); if(debug) printf("AModule::import_samples %d\n", __LINE__); memcpy(speed_buffer->get_data(), nested_output[edit->channel]->get_data(), speed_fragment_len * sizeof(double)); if(debug) printf("AModule::import_samples %d\n", __LINE__); // Reverse fragment so ::render can apply transitions going forward. if(direction == PLAY_REVERSE) { Resample::reverse_buffer(speed_buffer->get_data(), speed_fragment_len); } } if(debug) printf("AModule::import_samples %d\n", __LINE__); } else // Source is an asset if(edit->asset) { nested_edl = 0; if(debug) printf("AModule::import_samples %d\n", __LINE__); asset = edit->asset; if(debug) printf("AModule::import_samples %d\n", __LINE__); get_cache()->age(); if(debug) printf("AModule::import_samples %d\n", __LINE__); if(nested_renderengine) { delete nested_renderengine; nested_renderengine = 0; } if(debug) printf("AModule::import_samples %d\n", __LINE__); if(!(file = get_cache()->check_out( asset, get_edl()))) { // couldn't open source file / skip the edit printf(_("AModule::import_samples Couldn't open %s.\n"), asset->path); result = 1; } else { result = 0; if(sample_rate != asset->sample_rate) { // Read through sample rate converter. if(!resample) { resample = new AModuleResample(this); } if(debug) printf("AModule::import_samples %d %d %d\n", __LINE__, sample_rate, asset->sample_rate); result = resample->resample(speed_buffer, speed_fragment_len, asset->sample_rate, sample_rate, start_source, direction); // Resample reverses to keep it running forward. } else { if(debug) printf("AModule::import_samples %d channel=%d start_source=%ld len=%d\n", __LINE__, edit->channel, start_source, (int)speed_fragment_len); file->set_audio_position(start_source); file->set_channel(edit->channel); result = file->read_samples(speed_buffer, speed_fragment_len); // Reverse fragment so ::render can apply transitions going forward. if(debug) printf("AModule::import_samples %d speed_buffer=%p data=%p speed_fragment_len=%d\n", __LINE__, (void*)speed_buffer, (void*)speed_buffer->get_data(), (int)speed_fragment_len); if(direction == PLAY_REVERSE) { Resample::reverse_buffer(speed_buffer->get_data(), speed_fragment_len); } if(debug) printf("AModule::import_samples %d\n", __LINE__); } if(debug) printf("AModule::import_samples %d\n", __LINE__); get_cache()->check_in(asset); if(debug) printf("AModule::import_samples %d\n", __LINE__); file = 0; } } else { nested_edl = 0; asset = 0; if(debug) printf("AModule::import_samples %d %p %d\n", __LINE__, speed_buffer->get_data(), (int)speed_fragment_len); if(speed_fragment_len > 0) bzero(speed_buffer->get_data(), speed_fragment_len * sizeof(double)); if(debug) printf("AModule::import_samples %d\n", __LINE__); } if(debug) printf("AModule::import_samples %d\n", __LINE__); // Stretch it to fit the speed curve // Need overlapping buffers to get the interpolation to work, but this // screws up sequential effects. if(have_speed) { FloatAuto *previous = 0; FloatAuto *next = 0; FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; double *buffer_samples = buffer->get_data(); double *speed_samples = speed_buffer->get_data(); //printf("AModule::import_samples %d %lld\n", __LINE__, speed_fragment_len); if(speed_fragment_len == 0) { bzero(buffer_samples, fragment_len * sizeof(double)); bzero(prev_tail, SPEED_OVERLAP * sizeof(double)); bzero(prev_head, SPEED_OVERLAP * sizeof(double)); } else { // buffer is now reversed if(direction == PLAY_REVERSE) { int out_offset = 0; speed_position = speed_position2; //printf("AModule::import_samples %d %lld %lld\n", __LINE__, start_project, speed_fragment_len); for(int64_t i = start_project + fragment_len; i != start_project; i--) { // funky sample reordering, because the source is a reversed buffer int in_offset = (int64_t)(speed_fragment_len - 1 - speed_position); CLAMP(in_offset, 0, speed_fragment_len - 1); buffer_samples[out_offset++] = speed_samples[in_offset]; double speed = speed_autos->get_value(i, PLAY_REVERSE, previous, next); speed_position -= speed; } //printf("AModule::import_samples %d %f\n", __LINE__, speed_position); } else { int out_offset = 0; // position in buffer to read speed_position = speed_position1 - start_source; //printf("AModule::import_samples %d %f\n", __LINE__, speed_position); for(int64_t i = start_project; i < start_project + fragment_len; i++) { double speed = speed_autos->get_value(i, PLAY_FORWARD, previous, next); double next_speed_position = speed_position + speed; int in_offset = (int)(speed_position); if(fabs(speed) >= 1.0) { int total = abs(speed); double accum = 0; for(int j = 0; j < total; j++) { int in_offset2 = in_offset + (speed > 0 ? j : -j); CLAMP(in_offset2, 0, speed_fragment_len - 1); accum += speed_samples[in_offset2]; } buffer_samples[out_offset++] = accum / total; } else { // if(in_offset < 0 || in_offset >= speed_fragment_len) // printf("AModule::import_samples %d %d %d\n", // __LINE__, // in_offset, // speed_fragment_len); int in_offset1 = in_offset; int in_offset2 = in_offset; if(speed < 0) { in_offset1 += SPEED_OVERLAP; in_offset2 = in_offset1 - 1; } else { in_offset1 -= SPEED_OVERLAP; in_offset2 = in_offset1 + 1; } CLAMP(in_offset1, -SPEED_OVERLAP, speed_fragment_len - 1 + SPEED_OVERLAP); CLAMP(in_offset2, -SPEED_OVERLAP, speed_fragment_len - 1 + SPEED_OVERLAP); double value1 = 0; if(in_offset1 >= speed_fragment_len) { value1 = prev_head[in_offset1 - speed_fragment_len]; } else if(in_offset1 >= 0) { value1 = speed_samples[in_offset1]; } else { //printf("AModule::import_samples %d %d\n", __LINE__, in_offset1); value1 = prev_tail[SPEED_OVERLAP + in_offset1]; } #if 0 double value2 = 0; if(in_offset2 >= speed_fragment_len) { value2 = prev_head[in_offset2 - speed_fragment_len]; } else if(in_offset2 >= 0) { value2 = speed_samples()[in_offset2]; } else { value2 = prev_tail[SPEED_OVERLAP + in_offset2]; } double fraction = speed_position - floor(speed_position); buffer_samples[out_offset++] = value1 * (1.0 - fraction) + value2 * fraction; #endif buffer_samples[out_offset++] = value1; } speed_position = next_speed_position; } } for(int i = 0; i < SPEED_OVERLAP; i++) { int offset = speed_fragment_len - SPEED_OVERLAP + i; CLAMP(offset, 0, speed_fragment_len - 1); //printf("AModule::import_samples %d %d\n", __LINE__, offset, ); prev_tail[i] = speed_samples[offset]; offset = i; CLAMP(offset, 0, speed_fragment_len - 1); prev_head[i] = speed_samples[offset]; } } } return result; }
void TimeBar::update_points() { EDL *edl = get_edl(); int64_t pixel; if(edl) pixel = position_to_pixel(edl->local_session->get_inpoint()); if(in_point) { if(edl && edl->local_session->inpoint_valid() && pixel >= 0 && pixel < get_w()) { if(!EQUIV(edl->local_session->get_inpoint(), in_point->position) || in_point->pixel != pixel) { in_point->pixel = pixel; in_point->position = edl->local_session->get_inpoint(); in_point->reposition(0); } else { in_point->draw_face(1, 0); } } else { delete in_point; in_point = 0; } } else if(edl && edl->local_session->inpoint_valid() && pixel >= 0 && pixel < get_w()) { add_subwindow(in_point = new InPointGUI(mwindow, this, pixel, edl->local_session->get_inpoint())); in_point->set_cursor(ARROW_CURSOR, 0, 0); } if(edl) pixel = position_to_pixel(edl->local_session->get_outpoint()); if(out_point) { if(edl && edl->local_session->outpoint_valid() && pixel >= 0 && pixel < get_w()) { if(!EQUIV(edl->local_session->get_outpoint(), out_point->position) || out_point->pixel != pixel) { out_point->pixel = pixel; out_point->position = edl->local_session->get_outpoint(); out_point->reposition(0); } else { out_point->draw_face(1, 0); } } else { delete out_point; out_point = 0; } } else if(edl && edl->local_session->outpoint_valid() && pixel >= 0 && pixel < get_w()) { add_subwindow(out_point = new OutPointGUI(mwindow, this, pixel, edl->local_session->get_outpoint())); out_point->set_cursor(ARROW_CURSOR, 0, 0); } // flush(); }
void TimeBar::update_labels() { int output = 0; EDL *edl = get_edl(); if(edl) { for(Label *current = edl->labels->first; current; current = NEXT) { int64_t pixel = position_to_pixel(current->position); if(pixel >= 0 && pixel < get_w()) { // Create new label if(output >= labels.total) { LabelGUI *new_label; add_subwindow(new_label = new LabelGUI(mwindow, this, pixel, LabelGUI::get_y(mwindow, this), current->position)); new_label->set_cursor(ARROW_CURSOR, 0, 0); labels.append(new_label); } else // Reposition old label { LabelGUI *gui = labels.values[output]; if(gui->pixel != pixel) { gui->pixel = pixel; gui->reposition(0); } else { gui->draw_face(1,0); } labels.values[output]->position = current->position; } if(edl->local_session->get_selectionstart(1) <= current->position && edl->local_session->get_selectionend(1) >= current->position) labels.values[output]->update(1); else if(labels.values[output]->get_value()) labels.values[output]->update(0); output++; } } } // Delete excess labels while(labels.total > output) { labels.remove_object(); } // Get the labels to show show_window(0); }