From: Good Guy Date: Thu, 28 Nov 2019 20:19:55 +0000 (-0700) Subject: rework audio import_samples + resample + playback speed sampling, fix clear_boarder... X-Git-Tag: 2019-11~2 X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=commitdiff_plain;h=83c58d6d78f6bf0d1d1fd4cfba8654906fe6ec29 rework audio import_samples + resample + playback speed sampling, fix clear_boarder segv, index rebuild fixes, fix libzmpeg3 large audio buffer segv --- diff --git a/cinelerra-5.1/cinelerra/amodule.C b/cinelerra-5.1/cinelerra/amodule.C index 50b58884..9e2c59b6 100644 --- a/cinelerra-5.1/cinelerra/amodule.C +++ b/cinelerra-5.1/cinelerra/amodule.C @@ -72,75 +72,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 +85,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 +109,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 +190,179 @@ 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; - } - - 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); + source_position += dir*speed; + if( source_position > max_source ) max_source = source_position; + if( source_position < min_source ) min_source = source_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; + } -// 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); - } + result = read_samples(speed_buffer, + start_source, speed_fragment_len, direction); } } - 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; - } - } - 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; } @@ -704,10 +609,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) { diff --git a/cinelerra-5.1/cinelerra/amodule.h b/cinelerra-5.1/cinelerra/amodule.h index 1d17bf0f..128b2808 100644 --- a/cinelerra-5.1/cinelerra/amodule.h +++ b/cinelerra-5.1/cinelerra/amodule.h @@ -55,7 +55,8 @@ public: ~AModuleResample(); // All positions are in source sample rate - int read_samples(Samples *buffer, int64_t start, int64_t len); + int read_samples(Samples *buffer, + int64_t start, int64_t len, int direction); AModule *module; // output for nested EDL if resampled @@ -77,21 +78,13 @@ public: CICache* get_cache(); int import_samples(AEdit *playable_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); int render(Samples *buffer, - int64_t input_len, - int64_t input_position, - int direction, - int sample_rate, - int use_nudge); + int64_t input_len, int64_t input_position, int direction, + int sample_rate, int use_nudge); + int read_samples(Samples *buffer, + int64_t start, int64_t len, int direction); int get_buffer_size(); AttachmentPoint* new_attachment(Plugin *plugin); diff --git a/cinelerra-5.1/cinelerra/canvas.C b/cinelerra-5.1/cinelerra/canvas.C index 93507c3e..410145f0 100644 --- a/cinelerra-5.1/cinelerra/canvas.C +++ b/cinelerra-5.1/cinelerra/canvas.C @@ -767,16 +767,22 @@ void Canvas::clear_borders(EDL *edl) { BC_WindowBase *window = get_canvas(); if( !window ) return; - int window_w = window->get_w(); int window_h = window->get_h(); + int color = get_clear_color(); + window->set_color(color); + + if( !edl ) { + window->draw_box(0, 0, window_w, window_h); + window->flash(0); + return; + } + float output_x1,output_y1, output_x2,output_y2; float canvas_x1,canvas_y1, canvas_x2,canvas_y2; get_transfers(edl, output_x1, output_y1, output_x2, output_y2, canvas_x1, canvas_y1, canvas_x2, canvas_y2); - int color = get_clear_color(); - window->set_color(color); if( canvas_y1 > 0 ) { window->draw_box(0, 0, window_w, canvas_y1); diff --git a/cinelerra-5.1/cinelerra/indexfile.C b/cinelerra-5.1/cinelerra/indexfile.C index 3e1ce389..3c6fd97f 100644 --- a/cinelerra-5.1/cinelerra/indexfile.C +++ b/cinelerra-5.1/cinelerra/indexfile.C @@ -232,6 +232,15 @@ void IndexFile::delete_index(Preferences *preferences, remove_file(index_filename); } +void IndexFile::delete_index_files(Preferences *preferences, + Indexable *indexable) +{ + delete_index(preferences, indexable, ".toc"); + delete_index(preferences, indexable, ".idx"); + delete_index(preferences, indexable, ".mkr"); +} + + int IndexFile::open_file() { int result = 0; diff --git a/cinelerra-5.1/cinelerra/indexfile.h b/cinelerra-5.1/cinelerra/indexfile.h index dd38e9b8..63204631 100644 --- a/cinelerra-5.1/cinelerra/indexfile.h +++ b/cinelerra-5.1/cinelerra/indexfile.h @@ -60,6 +60,8 @@ public: int interrupt_index(); static void delete_index(Preferences *preferences, Indexable *indexable, const char *suffix=0); + static void delete_index_files(Preferences *preferences, + Indexable *indexable); static int get_index_filename(char *source_filename, char *index_directory, char *index_filename, diff --git a/cinelerra-5.1/cinelerra/main.C b/cinelerra-5.1/cinelerra/main.C index 6e0b6d5e..4b04a11b 100644 --- a/cinelerra-5.1/cinelerra/main.C +++ b/cinelerra-5.1/cinelerra/main.C @@ -145,6 +145,7 @@ int main(int argc, char *argv[]) // handle command line arguments first srand(time(0)); ArrayList filenames; + filenames.set_array_delete(); FileSystem fs; time_t st; time(&st); diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 89d188de..03e265e6 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -3688,6 +3688,26 @@ void MWindow::update_project(int load_mode) if(debug) PRINT_TRACE } +void MWindow::update_preferences(Preferences *prefs) +{ + if( prefs != preferences ) + preferences->copy_from(prefs); + if( cwindow->playback_engine ) + cwindow->playback_engine->preferences->copy_from(prefs); + for(int i = 0; i < vwindows.size(); i++) { + VWindow *vwindow = vwindows[i]; + if( !vwindow->is_running() ) continue; + if( vwindow->playback_engine ) + vwindow->playback_engine->preferences->copy_from(prefs); + } + for(int i = 0; i < zwindows.size(); i++) { + ZWindow *zwindow = zwindows[i]; + if( !zwindow->is_running() ) continue; + if( zwindow->zgui->playback_engine ) + zwindow->zgui->playback_engine->preferences->copy_from(prefs); + } +} + void MWindow::update_vwindow() { for( int i=0; ipath); remove_indexfile(indexable); // Schedule index build - IndexState *index_state = indexable->index_state; - index_state->index_status = INDEX_NOTTESTED; + indexable->index_state->remove_user(); + indexable->index_state = new IndexState; + IndexFile::delete_index_files(preferences, indexable); if( indexable->is_asset ) { Asset *asset = (Asset *)indexable; if( asset->format != FILE_PCM ) { @@ -3733,6 +3754,9 @@ void MWindow::rebuild_indices() } mainindexes->add_next_asset(0, indexable); } +// still in render engine + sync_parameters(CHANGE_ALL); + awindow->gui->async_update_assets(); mainindexes->start_build(); } @@ -4078,9 +4102,16 @@ void MWindow::remove_asset_from_caches(Asset *asset) if( vwindow->playback_engine->video_cache ) vwindow->playback_engine->video_cache->delete_entry(asset); } + for(int i = 0; i < zwindows.size(); i++) { + ZWindow *zwindow = zwindows[i]; + if( !zwindow->is_running() ) continue; + if( zwindow->zgui->playback_engine->audio_cache ) + zwindow->zgui->playback_engine->audio_cache->delete_entry(asset); + if( zwindow->zgui->playback_engine->video_cache ) + zwindow->zgui->playback_engine->video_cache->delete_entry(asset); + } } - void MWindow::remove_assets_from_project(int push_undo, int redraw, int delete_indexes, ArrayList *drag_assets, ArrayList *drag_clips) { diff --git a/cinelerra-5.1/cinelerra/mwindow.h b/cinelerra-5.1/cinelerra/mwindow.h index 0e6db95e..513e1bfe 100644 --- a/cinelerra-5.1/cinelerra/mwindow.h +++ b/cinelerra-5.1/cinelerra/mwindow.h @@ -181,6 +181,7 @@ public: int overwrite); // Reset everything for a load void update_project(int load_mode); + void update_preferences(Preferences *prefs); void update_vwindow(); // Fit selected time to horizontal display range void fit_selection(); @@ -231,7 +232,6 @@ public: // Not wanted for loading backups. int update_filename = 1); - // Print out plugins which are referenced in the EDL but not loaded. void test_plugins(EDL *new_edl, char *path); diff --git a/cinelerra-5.1/cinelerra/mwindowgui.C b/cinelerra-5.1/cinelerra/mwindowgui.C index 2350f92e..248a5600 100644 --- a/cinelerra-5.1/cinelerra/mwindowgui.C +++ b/cinelerra-5.1/cinelerra/mwindowgui.C @@ -2291,7 +2291,7 @@ int FFMpegToggle::handle_event() set_tooltip(ffmpeg_early_probe ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP); mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe); mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe); - + mwindow->update_preferences(mwindow->preferences); mwindow->show_warning(&mwindow->preferences->warn_indexes, _("Changing the base codecs may require rebuilding indexes.")); return 1; diff --git a/cinelerra-5.1/cinelerra/preferencesthread.C b/cinelerra-5.1/cinelerra/preferencesthread.C index b085e13b..e4f050be 100644 --- a/cinelerra-5.1/cinelerra/preferencesthread.C +++ b/cinelerra-5.1/cinelerra/preferencesthread.C @@ -252,7 +252,7 @@ int PreferencesThread::apply_settings() } mwindow->edl->copy_session(edl, 1); - mwindow->preferences->copy_from(preferences); + mwindow->update_preferences(preferences); BC_Signals::set_catch_segv(mwindow->preferences->trap_sigsegv); BC_Signals::set_catch_intr(mwindow->preferences->trap_sigintr); diff --git a/cinelerra-5.1/cinelerra/record.C b/cinelerra-5.1/cinelerra/record.C index 4b8accd3..2dd9e2c5 100644 --- a/cinelerra-5.1/cinelerra/record.C +++ b/cinelerra-5.1/cinelerra/record.C @@ -474,9 +474,7 @@ void Record::activate_batch(int number) void Record::delete_index_file(Asset *asset) { - IndexFile::delete_index(mwindow->preferences, asset, ".toc"); - IndexFile::delete_index(mwindow->preferences, asset, ".idx"); - IndexFile::delete_index(mwindow->preferences, asset, ".mkr"); + IndexFile::delete_index_files(mwindow->preferences, asset); } void Record::delete_batch() diff --git a/cinelerra-5.1/cinelerra/resample.C b/cinelerra-5.1/cinelerra/resample.C index 9e51a994..8ebd90dc 100644 --- a/cinelerra-5.1/cinelerra/resample.C +++ b/cinelerra-5.1/cinelerra/resample.C @@ -34,7 +34,9 @@ Resample::Resample() { - old = new double[BLACKSIZE]; + old.allocate(BLACKSIZE, 0); + double *old_data = old.get_data(); + memset(old_data, 0, BLACKSIZE*sizeof(*old_data)); resample_init = 0; last_ratio = 0; output_temp = 0; @@ -51,22 +53,15 @@ Resample::Resample() Resample::~Resample() { - delete [] old; delete [] output_temp; delete input; } -int Resample::read_samples(Samples *buffer, int64_t start, int64_t len) +int Resample::read_samples(Samples *buffer, int64_t start, int64_t len, int direction) { return 0; } -int Resample::get_direction() -{ - return direction; -} - - void Resample::reset() { resample_init = 0; @@ -75,26 +70,28 @@ void Resample::reset() input_position = 0; } -double Resample::blackman(int i, double offset, double fcn, int l) +void Resample::blackman(double fcn, int filter_l) { - /* This algorithm from: -SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C -S.D. Stearns and R.A. David, Prentice-Hall, 1992 - */ - - double bkwn; - double wcn = (M_PI * fcn); - double dly = l / 2.0; - double x = i-offset; - if(x < 0) x = 0; - else - if(x > l) x = l; - - bkwn = 0.42 - 0.5 * cos((x * 2) * M_PI /l) + 0.08 * cos((x * 4) * M_PI /l); - if(fabs(x - dly) < 1e-9) - return wcn / M_PI; - else - return (sin((wcn * (x - dly))) / (M_PI * (x - dly)) * bkwn); + double wcn = M_PI * fcn; + double ctr = filter_l / 2.0; + double cir = 2*M_PI/filter_l; + for( int j=0; j<=2*BPC; ++j ) { + double offset = (j-BPC) / (2.*BPC); // -0.5 ... 0.5 + for( int i=0; i<=filter_l; ++i ) { + double x = i - offset; + bclamp(x, 0,filter_l); + double v, dx = x - ctr; + if( fabs(dx) >= 1e-9 ) { + double curve = sin(wcn * dx) / (M_PI * dx); + double th = x * cir; + double blkmn = 0.42 - 0.5 * cos(th) + 0.08 * cos(2*th); + v = blkmn * curve; + } + else + v = fcn; + blackfilt[j][i] = v; + } + } } @@ -107,148 +104,83 @@ int Resample::get_output_size() // { // memcpy(output, output_temp, size * sizeof(double)); // // Shift leftover forward -// for(int i = size; i < output_size; i++) +// for( int i = size; i < output_size; i++ ) // output_temp[i - size] = output_temp[i]; // output_size -= size; // } +// starts odd = (even-1) +#define FILTER_N (BLACKSIZE-6) +#define FILTER_L (FILTER_N - (~FILTER_N & 1)); -void Resample::resample_chunk(Samples *input_buffer, - int64_t in_len, - int in_rate, - int out_rate) +void Resample::resample_chunk(Samples *input_buffer, int64_t in_len, + int in_rate, int out_rate) { - double resample_ratio = (double)in_rate / out_rate; - int filter_l; - double fcn, intratio; - double offset, xvalue; - int num_used; - int i, j, k; - double *input = input_buffer->get_data(); //printf("Resample::resample_chunk %d in_len=%jd input_size=%d\n", // __LINE__, in_len, input_size); - - intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < .0001); - fcn = .90 / resample_ratio; - if(fcn > .90) fcn = .90; - filter_l = BLACKSIZE - 6; -/* must be odd */ - if(0 == filter_l % 2 ) --filter_l; - -/* if resample_ratio = int, filter_l should be even */ - filter_l += (int)intratio; - + double *input = input_buffer->get_data(); + double resample_ratio = (double)in_rate / out_rate; + double fcn = .90 / resample_ratio; + if( fcn > .90 ) fcn = .90; + int filter_l = FILTER_L; +// if resample_ratio = int, filter_l should include right edge + if( fabs(resample_ratio - floor(.5 + resample_ratio)) < .0001 ) + ++filter_l; // Blackman filter initialization must be called whenever there is a // sampling ratio change - if(!resample_init || last_ratio != resample_ratio) - { + if( !resample_init || last_ratio != resample_ratio ) { resample_init = 1; + last_ratio = resample_ratio; + blackman(fcn, filter_l); itime = 0; - bzero(old, sizeof(double) * BLACKSIZE); + } -// precompute blackman filter coefficients - for (j = 0; j <= 2 * BPC; ++j) - { - for(j = 0; j <= 2 * BPC; j++) - { - offset = (double)(j - BPC) / (2 * BPC); - for(i = 0; i <= filter_l; i++) - { - blackfilt[j][i] = blackman(i, offset, fcn, filter_l); - } - } + double filter_l2 = filter_l/2.; + int l2 = filter_l2; + int64_t end_time = itime + in_len + l2; + int64_t out_time = end_time / resample_ratio + 1; + int64_t demand = out_time - output_position; + if( demand >= output_allocation ) { +// demand 2**n buffer + int64_t new_allocation = output_allocation ? output_allocation : 16384; + while( new_allocation < demand ) new_allocation <<= 1; + double *new_output = new double[new_allocation]; + if( output_temp ) { + memmove(new_output, output_temp, output_allocation*sizeof(double)); + delete [] output_temp; } + output_temp = new_output; + output_allocation = new_allocation; } // Main loop - double *inbuf_old = old; - for(k = 0; 1; k++) - { - double time0; - int joff; - - time0 = k * resample_ratio; - j = (int)floor(time0 - itime); - -// if(j + filter_l / 2 >= input_size) break; - if(j + filter_l / 2 >= in_len) break; - -/* blackman filter. by default, window centered at j+.5(filter_l%2) */ -/* but we want a window centered at time0. */ - offset = (time0 - itime - (j + .5 * (filter_l % 2))); - joff = (int)floor((offset * 2 * BPC) + BPC + .5); - xvalue = 0; - - - for(i = 0; i <= filter_l; i++) - { - int j2 = i + j - filter_l / 2; -//printf("j2=%d\n", j2); - double y = ((j2 < 0) ? inbuf_old[BLACKSIZE + j2] : input[j2]); - - xvalue += y * blackfilt[joff][i]; - } - - - if(output_allocation <= output_size) - { - double *new_output = 0; - int64_t new_allocation = output_allocation ? (output_allocation * 2) : 16384; - new_output = new double[new_allocation]; - if(output_temp) - { - bcopy(output_temp, new_output, output_allocation * sizeof(double)); - delete [] output_temp; - } - - output_temp = new_output; - output_allocation = new_allocation; - } - + double *old_data = old.get_data(); + double ctr_pos = 0; + int otime = 0, last_used = 0; + while( output_size < output_allocation ) { + double in_pos = otime * resample_ratio; +// window centered at ctr_pos + ctr_pos = in_pos + itime; + double pos = ctr_pos - filter_l2; + int ipos = floor(pos); + last_used = ipos + filter_l; + if( last_used >= in_len ) break; + double fraction = pos - ipos; + int phase = floor(fraction * 2*BPC + .5); + int i = ipos, j = filter_l; // fir filter + double xvalue = 0, *filt = blackfilt[phase]; + for( ; j>=0 && i<0; ++i,--j ) xvalue += *filt++ * old_data[BLACKSIZE + i]; + for( ; j>=0; ++i,--j ) xvalue += *filt++ * input[i]; output_temp[output_size++] = xvalue; + ++otime; } - - num_used = MIN(in_len, j + filter_l / 2); - itime += num_used - k * resample_ratio; - for(i = 0; i < BLACKSIZE; i++) - inbuf_old[i] = input[num_used + i - BLACKSIZE]; - - last_ratio = resample_ratio; - -} - -int Resample::read_chunk(Samples *input, - int64_t len) -{ - int fragment = len; - if(direction == PLAY_REVERSE && - input_position - len < 0) - { - fragment = input_position; - } - - int result = read_samples(input, input_position, fragment); - - if(direction == PLAY_FORWARD) - { - input_position += fragment; - } - else - { - input_position -= fragment; -// Mute unused part of buffer - if(fragment < len) - { - bzero(input->get_data() + fragment, - (len - fragment) * sizeof(double)); - } - } - - return result; +// move ctr_pos backward by in_len as new itime offset +// the next read will be in the history, itime is negative + itime = ctr_pos - in_len; + memmove(old_data, input+in_len-BLACKSIZE, BLACKSIZE*sizeof(double)); } - void Resample::reverse_buffer(double *buffer, int64_t len) { double *ap = buffer; @@ -260,76 +192,50 @@ void Resample::reverse_buffer(double *buffer, int64_t len) } } +int Resample::set_input_position(int64_t in_pos, int in_dir) +{ + reset(); + input_position = in_pos; + direction = in_dir; +// update old, just before/after input going fwd/rev; + int dir = direction == PLAY_FORWARD ? -1 : 1; + in_pos += dir * BLACKSIZE; + return read_samples(&old, in_pos, BLACKSIZE, in_dir); +} -int Resample::resample(Samples *output, - int64_t out_len, - int in_rate, - int out_rate, - int64_t out_position, - int direction) +int Resample::resample(Samples *output, int64_t out_len, + int in_rate, int out_rate, int64_t out_position, int direction) { int result = 0; - - -//printf("Resample::resample 1 output_position=%jd out_position=%jd out_len=%jd\n", -// output_position, out_position, out_len); -// Changed position - if(labs(this->output_position - out_position) > 0 || - direction != this->direction) - { - reset(); - -// Compute starting point in input rate. - this->input_position = out_position * in_rate / out_rate; - this->direction = direction; + if( this->output_position != out_position || + this->direction != direction ) { +//printf("missed %jd!=%jd\n", output_position, out_position); +// starting point in input rate. + int64_t in_pos = out_position * in_rate / out_rate; + set_input_position(in_pos, direction); } +//else +//printf("matched %jd==%jd\n", output_position, out_position); - + int dir = direction == PLAY_REVERSE ? -1 : 1; int remaining_len = out_len; double *output_ptr = output->get_data(); - while(remaining_len > 0 && !result) - { -// Drain output buffer - if(output_size) - { - int fragment_len = output_size; - if(fragment_len > remaining_len) fragment_len = remaining_len; - -//printf("Resample::resample 1 %d %d\n", remaining_len, output_size); - bcopy(output_temp, output_ptr, fragment_len * sizeof(double)); - -// Shift leftover forward - for(int i = fragment_len; i < output_size; i++) - output_temp[i - fragment_len] = output_temp[i]; - - output_size -= fragment_len; - remaining_len -= fragment_len; - output_ptr += fragment_len; + while( remaining_len > 0 && !result ) { + if( output_size ) { + int len = bmin(output_size, remaining_len); + memmove(output_ptr, output_temp, len*sizeof(double)); + memmove(output_temp, output_temp+len, (output_size-=len)*sizeof(double)); + output_ptr += len; remaining_len -= len; } - -// Import new samples -//printf("Resample::resample 2 %d\n", remaining_len); - if(remaining_len > 0) - { -//printf("Resample::resample 3 input_size=%d out_position=%d\n", input_size, out_position); - result = read_chunk(input, input_size); - resample_chunk(input, - input_size, - in_rate, - out_rate); + if( remaining_len > 0 ) { + result = read_samples(input, input_position, input_size, direction); + if( result ) break; + resample_chunk(input, input_size, in_rate, out_rate); + input_position += dir * input_size; } } - - - if(direction == PLAY_FORWARD) - this->output_position = out_position + out_len; - else - this->output_position = out_position - out_len; - -//printf("Resample::resample 2 %d %d\n", this->output_position, out_position); -//printf("Resample::resample 2 %d %d\n", out_len, output_size); - -//printf("Resample::resample 2 %d\n", output_size); + if( !result ) + this->output_position = out_position + dir * out_len; return result; } diff --git a/cinelerra-5.1/cinelerra/resample.h b/cinelerra-5.1/cinelerra/resample.h index b80bb6bd..d58e1e52 100644 --- a/cinelerra-5.1/cinelerra/resample.h +++ b/cinelerra-5.1/cinelerra/resample.h @@ -29,7 +29,7 @@ #define BLACKSIZE 25 #include "resample.inc" -#include "samples.inc" +#include "samples.h" #include class Resample @@ -41,57 +41,43 @@ public: // All positions are in file sample rate // This must reverse the buffer during reverse playback // so the filter always renders forward. - virtual int read_samples(Samples *buffer, int64_t start, int64_t len); + virtual int read_samples(Samples *buffer, + int64_t start, int64_t len, int direction); // Resample from the file handler and store in *output. // Returns 1 if the input reader failed. - int resample(Samples *samples, - int64_t out_len, - int in_rate, - int out_rate, // Starting sample in output samplerate // If reverse, the end of the buffer. - int64_t out_position, - int direction); - - int get_direction(); - + int resample(Samples *samples, + int64_t out_len, int in_rate, int out_rate, + int64_t out_position, int direction); static void reverse_buffer(double *buffer, int64_t len); // Reset after seeking void reset(); private: - double blackman(int i, double offset, double fcn, int l); + void blackman(double fcn, int l); + int set_input_position(int64_t in_pos, int in_dir); // Query output temp int get_output_size(); // void read_output(Samples *output, int size); // Resamples input and dumps it to output_temp - void resample_chunk(Samples *input, - int64_t in_len, - int in_rate, - int out_rate); - int read_chunk(Samples *input, - int64_t len); - -// History buffer for resampling. - double *old; - double itime; - - + void resample_chunk(Samples *input, int64_t in_len, + int in_rate, int out_rate); + int direction; // Unaligned resampled output double *output_temp; - - // Total samples in unaligned output int64_t output_size; - - int direction; // Allocation of unaligned output int64_t output_allocation; +// History buffer for resampling. + Samples old; // input chunk Samples *input; + double itime; // Position of source in source sample rate. int64_t input_position; int64_t input_size; diff --git a/cinelerra-5.1/cinelerra/virtualaconsole.C b/cinelerra-5.1/cinelerra/virtualaconsole.C index 4afc12f7..fab1b6a7 100644 --- a/cinelerra-5.1/cinelerra/virtualaconsole.C +++ b/cinelerra-5.1/cinelerra/virtualaconsole.C @@ -205,31 +205,30 @@ if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__); for( int i=0; iaudio_out[i]->get_data(); +// Time stretch the fragment to the real_output size for( int i=0; i 1 ) { - int out = 0; - for( int in=0; in len ) end = len; - int k = end - in; - double sample = 0; - while( in < end ) sample += current_buffer[in++]; - if( k > 0 ) sample /= k; + if( speed > 1 ) { // buffer gets shorter + int in = 0, out = 0; + while( in < len ) { + int next = (out+1) * speed; + if( next > len) next = len; + double sample = current_buffer[in]; + for( int i=in; ++i 1 ) sample /= l; current_buffer[out++] = sample; + in = next; } real_output_len = out; } - else if( speed < 1 ) { - int end = len / speed; - real_output_len = end; - for( int in=len, out=end; --in>=0; ) { -// samples rendered in real output buffer sample. - int start = in / speed; - double v = current_buffer[in]; - while( --out >= start ) current_buffer[out] = v; + else if( speed < 1 ) { // buffer gets longer + real_output_len = len / speed; + int in = len, out = real_output_len; + while( in > 0 && out > 0 ) { + double sample = current_buffer[--in]; + int next = in / speed; + while( out > next ) current_buffer[--out] = sample; } } else diff --git a/cinelerra-5.1/cinelerra/zwindow.h b/cinelerra-5.1/cinelerra/zwindow.h index 3019d438..fcd05699 100644 --- a/cinelerra-5.1/cinelerra/zwindow.h +++ b/cinelerra-5.1/cinelerra/zwindow.h @@ -28,7 +28,6 @@ #include "edl.inc" #include "filexml.inc" #include "mwindow.inc" -#include "playbackengine.inc" #include "renderengine.inc" #include "zwindowgui.inc" diff --git a/cinelerra-5.1/ffmpeg/video/pro.dfl b/cinelerra-5.1/ffmpeg/video/pro.dfl index b317d6b6..f1137e2f 100644 --- a/cinelerra-5.1/ffmpeg/video/pro.dfl +++ b/cinelerra-5.1/ffmpeg/video/pro.dfl @@ -1 +1 @@ -med422p10.pro +prores.pro diff --git a/cinelerra-5.1/libzmpeg3/audio/audio.C b/cinelerra-5.1/libzmpeg3/audio/audio.C index 4a98bbf4..5d88c169 100644 --- a/cinelerra-5.1/libzmpeg3/audio/audio.C +++ b/cinelerra-5.1/libzmpeg3/audio/audio.C @@ -720,9 +720,10 @@ decode_audio(void *output_v, int atyp, int channel, int len) // tell/eof %jd/%d\n", output_position, output_size, aud_pos, end_pos, // demand, demux->tell_byte(), demux->eof()); if( demux->eof() ) break; + int needed_history = len > AUDIO_HISTORY ? len : AUDIO_HISTORY; /* if overflowing, shift audio back */ - if( src->seekable && output_size > AUDIO_HISTORY ) { - int diff = demand + output_size - AUDIO_HISTORY; + if( src->seekable && output_size > needed_history ) { + int diff = demand + output_size - needed_history; shift_audio(diff); } int samples = read_frame(1); @@ -742,7 +743,7 @@ decode_audio(void *output_v, int atyp, int channel, int len) j = track->track_position() - output_position; k = output_size - j; if( k > len ) k = len; - float *out = channel < output_channels ? + float *out = j >= 0 && channel < output_channels ? output[channel] + j : 0; /* transmit data in specified format */