From 120f82197b4bdfdad9a5a666d773b45a8064d049 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Fri, 22 Nov 2019 11:52:30 -0700 Subject: [PATCH] rework playback speed and speed auto sampling, change conver to transcode, change x264opts to x254-params --- cinelerra-5.1/cinelerra/amodule.C | 421 ++++-------------- cinelerra-5.1/cinelerra/amodule.h | 4 - cinelerra-5.1/cinelerra/audioalsa.C | 2 +- cinelerra-5.1/cinelerra/convert.C | 22 +- cinelerra-5.1/cinelerra/ffmpeg.C | 2 +- cinelerra-5.1/cinelerra/virtualaconsole.C | 102 ++--- cinelerra-5.1/doc/shortcuts.html | 28 +- cinelerra-5.1/ffmpeg/video/16mmto264.mp4 | 2 +- cinelerra-5.1/ffmpeg/video/avc422.m2ts | 2 +- cinelerra-5.1/ffmpeg/video/faststart_h264.mp4 | 2 +- cinelerra-5.1/ffmpeg/video/faststart_h264.qt | 2 +- cinelerra-5.1/ffmpeg/video/h264-10bit.mp4 | 2 +- cinelerra-5.1/ffmpeg/video/h264.f4v | 2 +- cinelerra-5.1/ffmpeg/video/h264.mp4 | 2 +- cinelerra-5.1/ffmpeg/video/hd_h264.youtube | 2 +- cinelerra-5.1/ffmpeg/video/pass1of2_h264.mp4 | 2 +- cinelerra-5.1/ffmpeg/video/pass2of2_h264.mp4 | 2 +- cinelerra-5.1/ffmpeg/video/sd_h264.youtube | 2 +- cinelerra-5.1/ffmpeg/video/uhd_h264.youtube | 2 +- .../ffmpeg/video/visually_lossless.m2ts | 3 +- 20 files changed, 161 insertions(+), 447 deletions(-) diff --git a/cinelerra-5.1/cinelerra/amodule.C b/cinelerra-5.1/cinelerra/amodule.C index aee3f5f0..50b58884 100644 --- a/cinelerra-5.1/cinelerra/amodule.C +++ b/cinelerra-5.1/cinelerra/amodule.C @@ -151,8 +151,6 @@ AModule::AModule(RenderEngine *renderengine, transition_temp = 0; speed_temp = 0; bzero(nested_output, sizeof(Samples*) * MAX_CHANNELS); - bzero(prev_head, SPEED_OVERLAP * sizeof(double)); - bzero(prev_tail, SPEED_OVERLAP * sizeof(double)); meter_history = new MeterHistory(); nested_allocation = 0; resample = 0; @@ -216,11 +214,10 @@ int AModule::import_samples(AEdit *edit, 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; + 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 @@ -232,51 +229,32 @@ int AModule::import_samples(AEdit *edit, 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) + 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=%jd\n", -__LINE__, -speed_fragment_len); - - - + int dir = direction == PLAY_FORWARD ? 1 : -1; // apply speed curve to source position so the timeline agrees with the playback - if(track->has_speed()) - { + if( track->has_speed() ) { // get speed adjusted position from start of edit. - FloatAuto *previous = 0; - FloatAuto *next = 0; + FloatAuto *previous = 0, *next = 0; FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; speed_position += speed_autos->automation_integral(edit_startproject, start_project-edit_startproject, PLAY_FORWARD); 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; + int64_t pos = start_project; + for( int64_t i=0; iget_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; } @@ -301,59 +279,32 @@ speed_fragment_len); 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->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) + if( speed_fragment_len == 0 ) return 1; - - // Source is a nested EDL - if(edit->nested_edl) - { - int command; + if( edit->nested_edl ) { + int command = direction == PLAY_REVERSE ? + NORMAL_REWIND : NORMAL_FWD; 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) - { + 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_renderengine ) { + delete nested_renderengine; nested_renderengine = 0; } - - if(!nested_command) - { + if( !nested_command ) nested_command = new TransportCommand; - } - - - if(!nested_renderengine) - { + if( !nested_renderengine ) { nested_command->command = command; nested_command->get_edl()->copy_all(nested_edl); nested_command->change_type = CHANGE_ALL; @@ -373,350 +324,144 @@ if(debug) printf("AModule::import_samples %d\n", __LINE__); 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; + 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); - } } -if(debug) printf("AModule::import_samples %d\n", __LINE__); - if(nested_allocation < speed_fragment_len) + 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) - { + 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) - { + else if(sample_rate != nested_edl->session->sample_rate) { + 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); + 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 - { + 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__); + nested_output, speed_fragment_len, start_source); 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) - { + if( direction == PLAY_REVERSE ) { Resample::reverse_buffer(speed_buffer->get_data(), speed_fragment_len); } } - -if(debug) printf("AModule::import_samples %d\n", __LINE__); } - else + else if( edit->asset ) { // 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( 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()))) - { + 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 - { + else { result = 0; - - if(sample_rate != asset->sample_rate) - { + if( sample_rate != asset->sample_rate ) { // Read through sample rate converter. - if(!resample) - { + 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); + 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=%jd len=%d\n", __LINE__, edit->channel, start_source, (int)speed_fragment_len); + 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(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 - { + 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( speed_fragment_len > 0 ) + bzero(speed_buffer->get_data(), speed_fragment_len * sizeof(double)); } -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]; + if( have_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; + 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; + int64_t speed_pos = speed_position; + + int64_t pos = start_project; + for( int64_t i=0; iget_value(pos, + direction, previous, next); + double next_position = speed_position + dir*speed; + int64_t next_pos = next_position; + 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)]; } - 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]; - } + sample /= total; + } #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; + else if( total < 1 ) { + k += d; + double next_sample = speed_samples[bclip(k, 0,len1)]; + double v = speed_position - speed_pos; + sample = (1.-v) * sample + v * next_sample; } - } - - 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]; +#endif + buffer_samples[out_offset] = sample; + out_offset += dir; + speed_position = next_position; + speed_pos = next_pos; } } } - - - - return result; } - int AModule::render(Samples *buffer, int64_t input_len, int64_t start_position, diff --git a/cinelerra-5.1/cinelerra/amodule.h b/cinelerra-5.1/cinelerra/amodule.h index 6781d38c..1d17bf0f 100644 --- a/cinelerra-5.1/cinelerra/amodule.h +++ b/cinelerra-5.1/cinelerra/amodule.h @@ -109,10 +109,6 @@ public: Samples *transition_temp; // Temporary buffer for rendering speed curve Samples *speed_temp; -// Previous buffers for rendering speed curve -#define SPEED_OVERLAP 4 - double prev_head[SPEED_OVERLAP]; - double prev_tail[SPEED_OVERLAP]; // Pointer to an asset for the resampler Asset *asset; diff --git a/cinelerra-5.1/cinelerra/audioalsa.C b/cinelerra-5.1/cinelerra/audioalsa.C index f256a506..e5c9fdfb 100644 --- a/cinelerra-5.1/cinelerra/audioalsa.C +++ b/cinelerra-5.1/cinelerra/audioalsa.C @@ -579,7 +579,7 @@ int AudioALSA::write_buffer(char *buffer, int size) done = 1; } else { - printf("AudioALSA::write_buffer err %d(%s) at sample %jd\n", + printf(_("AudioALSA::write_buffer err %d(%s) at sample %jd\n"), ret, snd_strerror(ret), device->current_position()); Timer::delay(50); // snd_pcm_resume(get_output()); diff --git a/cinelerra-5.1/cinelerra/convert.C b/cinelerra-5.1/cinelerra/convert.C index 9f4bfbd0..d42bac49 100644 --- a/cinelerra-5.1/cinelerra/convert.C +++ b/cinelerra-5.1/cinelerra/convert.C @@ -166,7 +166,7 @@ EDL *ConvertRender::convert_edl(EDL *edl, Indexable *idxbl) char path[BCTEXTLEN]; FileSystem fs; fs.extract_name(path, copy_asset->path); strcpy(copy_edl->local_session->clip_title, path); - strcpy(copy_edl->local_session->clip_notes, _("Convert clip")); + strcpy(copy_edl->local_session->clip_notes, _("Transcode clip")); int64_t video_frames = idxbl->get_video_frames(); double frame_rate = idxbl->get_frame_rate(); double video_length = video_frames / frame_rate; @@ -318,18 +318,18 @@ void ConvertRender::run() create_copy(i); canceled = progress->is_cancelled(); -printf("convert: failed=%d canceled=%d\n", failed, canceled); +printf(_("convert: failed=%d canceled=%d\n"), failed, canceled); double elapsed_time = progress_timer->get_scaled_difference(1); char elapsed[BCSTRLEN], text[BCSTRLEN]; Units::totext(elapsed, elapsed_time, TIME_HMS2); - printf("ConvertRender::run: done in %s\n", elapsed); + printf(_("TranscodeRender::run: done in %s\n"), elapsed); if( canceled ) - strcpy(text, _("convert cancelled")); + strcpy(text, _("transcode cancelled")); else if( failed ) - strcpy(text, _("convert failed")); + strcpy(text, _("transcode failed")); else - sprintf(text, _("convert %d files, render time %s"), + sprintf(text, _("transcode %d files, render time %s"), needed_copies.size(), elapsed); // stop progress bar stop_progress(text); @@ -338,7 +338,7 @@ printf("convert: failed=%d canceled=%d\n", failed, canceled); mwindow->finish_convert(remove_originals); } else if( !canceled ) { - eprintf(_("Error making convert.")); + eprintf(_("Error making transcode.")); } if( !canceled && beep > 0 ) { @@ -372,7 +372,7 @@ void ConvertRender::start_progress() int64_t total_samples = total_len * format_asset->sample_rate; mwindow->gui->lock_window("Render::start_progress"); progress = mwindow->mainprogress-> - start_progress(_("Convert files..."), total_samples); + start_progress(_("Transcode files..."), total_samples); mwindow->gui->unlock_window(); convert_progress = new ConvertProgress(mwindow, this); convert_progress->start(); @@ -489,7 +489,7 @@ void ConvertRender::create_copy(int i) } ConvertWindow::ConvertWindow(MWindow *mwindow, ConvertDialog *dialog, int x, int y) - : BC_Window(_(PROGRAM_NAME ": Convert settings"), x, y, WIDTH, HEIGHT, + : BC_Window(_(PROGRAM_NAME ": Transcode settings"), x, y, WIDTH, HEIGHT, -1, -1, 0, 0, 1) { this->mwindow = mwindow; @@ -580,7 +580,7 @@ void ConvertFormatTools::update_format() ConvertMenuItem::ConvertMenuItem(MWindow *mwindow) - : BC_MenuItem(_("Convert..."), _("Alt-e"), 'e') + : BC_MenuItem(_("Transcode..."), _("Alt-e"), 'e') { this->mwindow = mwindow; set_alt(); @@ -610,7 +610,7 @@ ConvertDialog::ConvertDialog(MWindow *mwindow) this->mwindow = mwindow; gui = 0; asset = new Asset; - strcpy(suffix, ".convert"); + strcpy(suffix, ".transcode"); // quicker than some, not as good as others asset->format = FILE_FFMPEG; strcpy(asset->fformat, "mp4"); diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index e72ea7af..794added 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -2372,7 +2372,7 @@ int FFMPEG::open_decoder() } if( bad_time && !(fflags & FF_BAD_TIMES) ) { fflags |= FF_BAD_TIMES; - printf("FFMPEG::open_decoder: some stream have bad times: %s\n", + printf(_("FFMPEG::open_decoder: some stream have bad times: %s\n"), fmt_ctx->url); } ff_unlock(); diff --git a/cinelerra-5.1/cinelerra/virtualaconsole.C b/cinelerra-5.1/cinelerra/virtualaconsole.C index 02a86dcf..4afc12f7 100644 --- a/cinelerra-5.1/cinelerra/virtualaconsole.C +++ b/cinelerra-5.1/cinelerra/virtualaconsole.C @@ -196,60 +196,40 @@ if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__); !interrupt) { // speed parameters + float speed = renderengine->command->get_speed(); // length compensated for speed int real_output_len = 0; -// output sample - double sample; - int k; double *audio_out_packed[MAX_CHANNELS]; int audio_channels = renderengine->get_edl()->session->audio_channels; - for(int i = 0, j = 0; - i < audio_channels; - i++) - { - audio_out_packed[j++] = arender->audio_out[i]->get_data(); - } - for(int i = 0; - i < audio_channels; - i++) - { - int in, out; + for( int i=0; iaudio_out[i]->get_data(); + for( int i=0; icommand->get_speed() > 1) - { -// Number of samples in real output buffer for each to sample rendered. - int interpolate_len = (int)renderengine->command->get_speed(); - for(in = 0, out = 0; in < len; ) - { - sample = 0; - for(k = 0; k < interpolate_len; k++) - { - sample += current_buffer[in++]; - } - - sample /= renderengine->command->get_speed(); + if( speed > 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; current_buffer[out++] = sample; } real_output_len = out; } - else - if(renderengine->command->get_speed() < 1) - { -// number of samples to skip - int interpolate_len = (int)(1.0 / renderengine->command->get_speed()); - real_output_len = len * interpolate_len; - - for(in = len - 1, out = real_output_len - 1; in >= 0; ) - { - for(k = 0; k < interpolate_len; k++) - { - current_buffer[out--] = current_buffer[in]; - } - in--; + 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 @@ -257,53 +237,23 @@ if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__); } // Wait until video is ready - if(arender->first_buffer) - { + if( arender->first_buffer ) { renderengine->first_frame_lock->lock("VirtualAConsole::process_buffer"); arender->first_buffer = 0; } - if(!renderengine->audio->get_interrupted()) - { + if( !renderengine->audio->get_interrupted() ) { renderengine->audio->write_buffer(audio_out_packed, audio_channels, real_output_len); } - if(renderengine->audio->get_interrupted()) interrupt = 1; + if( renderengine->audio->get_interrupted() ) + interrupt = 1; } -if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__); - - - - - return result; } - - - - - - - - - - - - - - - - - - - - - - - int VirtualAConsole::init_rendering(int duplicate) { return 0; diff --git a/cinelerra-5.1/doc/shortcuts.html b/cinelerra-5.1/doc/shortcuts.html index dce291fd..29c8c53b 100644 --- a/cinelerra-5.1/doc/shortcuts.html +++ b/cinelerra-5.1/doc/shortcuts.html @@ -7,7 +7,7 @@ - +