X-Git-Url: https://git.cinelerra-gg.org/git/?a=blobdiff_plain;ds=sidebyside;f=cinelerra-5.1%2Fcinelerra%2Famodule.C;h=d8fb4396437ecea793686c20b5d55539880bdfd6;hb=54b918a8b84f666bf32548ebd12b93908061d2a6;hp=50b58884784a42b882c425ae913f846745195eae;hpb=120f82197b4bdfdad9a5a666d773b45a8064d049;p=goodguy%2Fcinelerra.git diff --git a/cinelerra-5.1/cinelerra/amodule.C b/cinelerra-5.1/cinelerra/amodule.C index 50b58884..d8fb4396 100644 --- a/cinelerra-5.1/cinelerra/amodule.C +++ b/cinelerra-5.1/cinelerra/amodule.C @@ -37,6 +37,7 @@ #include "filexml.h" #include "floatautos.h" #include "language.h" +#include "mainerror.h" #include "module.h" #include "patch.h" #include "plugin.h" @@ -49,6 +50,7 @@ #include "theme.h" #include "transition.h" #include "transportque.h" +#include "tracks.h" #include @@ -72,75 +74,12 @@ AModuleResample::~AModuleResample() delete nested_output[i]; } -int AModuleResample::read_samples(Samples *buffer, int64_t start, int64_t len) +int AModuleResample::read_samples(Samples *buffer, + int64_t start, int64_t len, int direction) { - int result = 0; - - - if(module->asset) - { -// Files only read going forward. - if(get_direction() == PLAY_REVERSE) - { - start -= len; - } - -//printf("AModuleResample::read_samples start=%jd len=%jd\n", start, len); - module->file->set_audio_position(start); - module->file->set_channel(module->channel); - result = module->file->read_samples(buffer, len); - -// Reverse buffer so resampling filter renders forward. - if(get_direction() == PLAY_REVERSE) - Resample::reverse_buffer(buffer->get_data(), len); - } - else - if(module->nested_edl) - { - - -// Nested EDL generates reversed buffer. - for(int i = 0; i < module->nested_edl->session->audio_channels; i++) - { - if(nested_allocation < len) - { - delete nested_output[i]; - nested_output[i] = 0; - } - - if(!nested_output[i]) - { - nested_output[i] = new Samples(len); - } - } - - - result = module->nested_renderengine->arender->process_buffer( - nested_output, - len, - start); -// printf("AModuleResample::read_samples buffer=%p module=%p len=%d\n", -// buffer, -// module, -// len); - memcpy(buffer->get_data(), - nested_output[module->channel]->get_data(), - len * sizeof(double)); - - } - return result; + return module->read_samples(buffer, start, len, direction); } - - - - - - - - - - AModule::AModule(RenderEngine *renderengine, CommonRender *commonrender, PluginArray *plugin_array, @@ -148,6 +87,7 @@ AModule::AModule(RenderEngine *renderengine, : Module(renderengine, commonrender, plugin_array, track) { data_type = TRACK_AUDIO; + channel = 0; transition_temp = 0; speed_temp = 0; bzero(nested_output, sizeof(Samples*) * MAX_CHANNELS); @@ -171,6 +111,52 @@ AModule::~AModule() delete resample; } +int AModule::read_samples(Samples *buffer, int64_t start, int64_t len, int direction) +{ + if( len < 0 ) return 1; + double *buffer_data = buffer->get_data(); +// if start < 0, zero fill prefix. if error, zero fill buffer + int64_t zeros = len; + int result = 0; + if( asset ) { +// Files only read going forward. + if( direction == PLAY_REVERSE ) start -= len; + int64_t sz = start >= 0 ? len : len + start; + if( start < 0 ) start = 0; + if( sz > 0 ) { + file->set_audio_position(start); + file->set_channel(channel); + result = file->read_samples(buffer, sz); + if( !result && (zeros-=sz) > 0 ) { + double *top_data = buffer_data + zeros; + memmove(top_data, buffer_data, sz*sizeof(*buffer_data)); + } + } + if( !result && direction == PLAY_REVERSE ) + Resample::reverse_buffer(buffer_data, len); + } + else if( nested_edl ) { + if( nested_allocation < len ) { + nested_allocation = len; + for( int i=0; isession->audio_channels; ++i ) { + delete nested_output[i]; + nested_output[i] = new Samples(nested_allocation); + } + } + result = nested_renderengine->arender-> + process_buffer(nested_output, len, start); + if( !result ) { + double *sample_data = nested_output[channel]->get_data(); + int buffer_size = len * sizeof(*buffer_data); + memcpy(buffer_data, sample_data, buffer_size); + zeros = 0; + } + } + if( zeros > 0 ) + memset(buffer_data, 0, zeros*sizeof(*buffer_data)); + return result; +} + AttachmentPoint* AModule::new_attachment(Plugin *plugin) { return new AAttachmentPoint(renderengine, plugin); @@ -206,258 +192,180 @@ CICache* AModule::get_cache() 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) + int64_t start_project, int64_t edit_startproject, int64_t edit_startsource, + int direction, int sample_rate, Samples *buffer, int64_t fragment_len) { - const int debug = 0; 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 + if( fragment_len <= 0 ) + result = 1; + if( nested_edl && edit->channel >= nested_edl->session->audio_channels ) + result = 1; + double *buffer_data = buffer->get_data(); +// buffer fragment adjusted for speed curve Samples *speed_buffer = buffer; + double *speed_data = speed_buffer->get_data(); + int64_t speed_fragment_len = fragment_len; + int dir = direction == PLAY_FORWARD ? 1 : -1; +// normal speed source boundaries in EDL samplerate + int64_t start_source = start_project - edit_startproject + edit_startsource; + double end_source = start_source + dir*speed_fragment_len; + double start_position = start_source; +// double end_position = end_source; +// normal speed playback boundaries + double min_source = bmin(start_source, end_source); + double max_source = bmax(start_source, end_source); - if( nested_edl && edit->channel >= nested_edl->session->audio_channels ) - return 1; this->channel = edit->channel; - int dir = direction == PLAY_FORWARD ? 1 : -1; + int have_speed = track->has_speed(); // 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. + if( !result && have_speed ) { +// get speed adjusted start position from start of edit. FloatAuto *previous = 0, *next = 0; FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; - speed_position += speed_autos->automation_integral(edit_startproject, + double source_position = edit_startsource + + speed_autos->automation_integral(edit_startproject, start_project-edit_startproject, PLAY_FORWARD); - speed_position1 = speed_position; - + min_source = source_position; + max_source = source_position; // calculate boundaries of input fragment required for speed curve - max_position = speed_position; - min_position = speed_position; int64_t pos = start_project; - for( int64_t i=0; i=0; pos+=dir ) { double speed = speed_autos->get_value(pos, direction, previous, next); - speed_position += dir*speed; - if(speed_position > max_position) max_position = speed_position; - if(speed_position < min_position) min_position = speed_position; + source_position += dir*speed; + if( source_position > max_source ) max_source = source_position; + if( source_position < min_source ) min_source = source_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; - +// end_position = source_position; + speed_fragment_len = (int64_t)(max_source - min_source); + start_source = direction == PLAY_FORWARD ? min_source : max_source; + if( speed_fragment_len > 0 ) { // 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->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; + speed_data = speed_buffer->get_data(); } - if(!speed_temp) - speed_temp = new Samples(speed_fragment_len); - speed_buffer = speed_temp; } - if( speed_fragment_len == 0 ) - return 1; + int edit_sample_rate = 0; + if( speed_fragment_len <= 0 ) + result = 1; -// Source is a nested EDL - if( edit->nested_edl ) { - int command = direction == PLAY_REVERSE ? - NORMAL_REWIND : NORMAL_FWD; + if( !result && edit->asset ) { + nested_edl = 0; + if( nested_renderengine ) { + delete nested_renderengine; nested_renderengine = 0; + } +// Source is an asset + asset = edit->asset; + edit_sample_rate = asset->sample_rate; + get_cache()->age(); + file = get_cache()->check_out(asset, get_edl()); + if( !file ) { + printf(_("AModule::import_samples Couldn't open %s.\n"), asset->path); + result = 1; + } + } + else if( !result && edit->nested_edl ) { asset = 0; - +// Source is a nested EDL 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, 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); - } + delete nested_renderengine; + nested_renderengine = 0; } -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; isession->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); + edit_sample_rate = nested_edl->session->sample_rate; + int command = direction == PLAY_REVERSE ? + NORMAL_REWIND : NORMAL_FWD; + if( !nested_command ) + nested_command = new TransportCommand; + nested_command->command = command; + nested_command->get_edl()->copy_all(nested_edl); + nested_command->change_type = CHANGE_ALL; + nested_command->realtime = renderengine->command->realtime; + if( !nested_renderengine ) { + nested_renderengine = new RenderEngine(0, get_preferences(), 0, 1); + nested_renderengine->set_acache(get_cache()); + nested_renderengine->arm_command(nested_command); } - - if( nested_allocation < speed_fragment_len ) - nested_allocation = speed_fragment_len; - -// Update direction command nested_renderengine->command->command = command; + result = 0; + } + if( edit_sample_rate <= 0 ) + result = 1; -// 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) { + if( !result ) { +// speed_buffer is (have_speed ? speed_temp : buffer) + if( sample_rate != edit_sample_rate ) { if( !resample ) resample = new AModuleResample(this); result = resample->resample(speed_buffer, - speed_fragment_len, nested_edl->session->sample_rate, + speed_fragment_len, edit_sample_rate, sample_rate, start_source, direction); -// Resample reverses to keep it running forward. - } - else { -// Render without resampling - result = nested_renderengine->arender->process_buffer( - nested_output, speed_fragment_len, start_source); - memcpy(speed_buffer->get_data(), - nested_output[edit->channel]->get_data(), - speed_fragment_len * sizeof(double)); - -// Reverse fragment so ::render can apply transitions going forward. - if( direction == PLAY_REVERSE ) { - Resample::reverse_buffer(speed_buffer->get_data(), speed_fragment_len); - } - } - } - else if( edit->asset ) { -// Source is an asset - nested_edl = 0; - asset = edit->asset; - get_cache()->age(); - - if( nested_renderengine ) { - delete nested_renderengine; nested_renderengine = 0; - } - - 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); - result = resample->resample(speed_buffer, - speed_fragment_len, asset->sample_rate, - sample_rate, start_source, direction); -// Resample reverses to keep it running forward. - } - else { - 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(direction == PLAY_REVERSE) - Resample::reverse_buffer(speed_buffer->get_data(), speed_fragment_len); - } - - get_cache()->check_in(asset); - file = 0; + result = read_samples(speed_buffer, + start_source, speed_fragment_len, direction); } } - else { - nested_edl = 0; - asset = 0; - if( speed_fragment_len > 0 ) - bzero(speed_buffer->get_data(), speed_fragment_len * sizeof(double)); + if( asset && file ) { + file = 0; + get_cache()->check_in(asset); } - // 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 ) { - double *buffer_samples = buffer->get_data(); - if( speed_fragment_len > 0 ) { - FloatAuto *previous = 0; - FloatAuto *next = 0; - FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; - double *speed_samples = speed_buffer->get_data(); - int len1 = speed_fragment_len-1; - int out_offset = dir>0 ? 0 : fragment_len-1; - speed_position = speed_position1; + if( !result && have_speed ) { + FloatAuto *previous = 0, *next = 0; + FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; + int len1 = speed_fragment_len-1; + double speed_position = start_position; + double pos = start_project; +// speed gnuplot> plot "/tmp/x.dat" using($1) with lines +// speed_position gnuplot> plot "/tmp/x.dat" using($2) with lines +//FILE *fp = 0; +//if( !channel ) { fp = fopen("/tmp/x.dat", "a"); fprintf(fp," %f %f\n",0.,0.); } + for( int64_t i=0; iget_value(pos, - direction, previous, next); - double next_position = speed_position + dir*speed; - int64_t next_pos = next_position; + double speed = speed_autos->get_value(pos, + direction, previous, next); +//if(fp) fprintf(fp," %f %f\n", speed, speed_position); + double next_position = speed_position + dir*speed; + int64_t next_pos = next_position; + int total = abs(next_pos - speed_pos); + int k = speed_pos - min_source; + if( dir < 0 ) k = len1 - k; // if buffer reversed + double sample = speed_data[bclip(k, 0,len1)]; + if( total > 1 ) { int d = next_pos >= speed_pos ? 1 : -1; - int k = speed_pos - start_source; - double sample = speed_samples[bclip(k, 0,len1)]; - int total = abs(next_pos - speed_pos); - if( total > 1 ) { - for( int j=total; --j>0; ) { - k += d; - sample += speed_samples[bclip(k, 0,len1)]; - } - sample /= total; - } -#if 0 - else if( total < 1 ) { + for( int j=total; --j>0; ) { k += d; - double next_sample = speed_samples[bclip(k, 0,len1)]; - double v = speed_position - speed_pos; - sample = (1.-v) * sample + v * next_sample; + sample += speed_data[bclip(k, 0,len1)]; } -#endif - buffer_samples[out_offset] = sample; - out_offset += dir; - speed_position = next_position; - speed_pos = next_pos; + sample /= total; } +#if 0 + else if( total < 1 ) { + int d = next_pos >= speed_pos ? 1 : -1; + k += d; + double next_sample = speed_data[bclip(k, 0,len1)]; + double v = speed_position - speed_pos; + sample = (1.-v) * sample + v * next_sample; + } +#endif + buffer_data[i] = sample; + speed_position = next_position; } +//if(fp) fclose(fp); } + if( result ) + bzero(buffer_data, fragment_len*sizeof(*buffer_data)); return result; } @@ -594,13 +502,9 @@ if(debug) printf("AModule::render %d %jd\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; + Plugin *transition = get_edl()->tracks->plugin_exists(transition_id); + if( transition && transition->on && 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) @@ -631,7 +535,7 @@ if(debug) printf("AModule::render %d\n", __LINE__); // Read transition into temp and render - if(transition && previous_edit) + if(transition && transition->on && previous_edit) { int64_t previous_startproject = previous_edit->startproject * sample_rate / @@ -689,13 +593,13 @@ if(debug) printf("AModule::render %d %jd\n", __LINE__, fragment_len); { current_position = start_position - edit_startproject; } - - transition_server->process_transition( - transition_temp, - &output, - current_position, - transition_fragment_len, - transition->length); + if( transition_server ) { + transition_server->process_transition( + transition_temp, &output, current_position, + transition_fragment_len, transition->length); + } + else + eprintf("missing transition plugin: %s\n", transition->title); // Reverse output buffer here so transitions always render forward. if(direction == PLAY_REVERSE) @@ -704,10 +608,7 @@ if(debug) printf("AModule::render %d %jd\n", __LINE__, fragment_len); } } if(debug) printf("AModule::render %d start_position=%jd end_position=%jd fragment_len=%jd\n", -__LINE__, -start_position, -end_position, -fragment_len); + __LINE__, start_position, end_position, fragment_len); if(direction == PLAY_REVERSE) {