MCPcopy Create free account
hub / github.com/OpenShot/libopenshot / apply_timemapping

Method apply_timemapping

src/Clip.cpp:573–723  ·  view source on GitHub ↗

Adjust the audio and image of a time mapped frame

Source from the content-addressed store, hash-verified

571
572// Adjust the audio and image of a time mapped frame
573void Clip::apply_timemapping(std::shared_ptr<Frame> frame)
574{
575 // Check for valid reader
576 if (!reader)
577 // Throw error if reader not initialized
578 throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.");
579
580 // Check for a valid time map curve
581 if (time.GetLength() > 1)
582 {
583 const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
584
585 int64_t clip_frame_number = frame->number;
586 int64_t new_frame_number = adjust_frame_number_minimum(time.GetLong(clip_frame_number));
587
588 // create buffer
589 juce::AudioBuffer<float> *source_samples = nullptr;
590
591 // Get delta (difference from this frame to the next time mapped frame: Y value)
592 double delta = time.GetDelta(clip_frame_number + 1);
593 const bool prev_is_increasing = time.IsIncreasing(clip_frame_number);
594 const bool is_increasing = time.IsIncreasing(clip_frame_number + 1);
595
596 // Determine length of source audio (in samples)
597 // A delta of 1.0 == normal expected samples
598 // A delta of 0.5 == 50% of normal expected samples
599 // A delta of 2.0 == 200% of normal expected samples
600 int target_sample_count = Frame::GetSamplesPerFrame(adjust_timeline_framenumber(clip_frame_number), Reader()->info.fps,
601 Reader()->info.sample_rate,
602 Reader()->info.channels);
603 int source_sample_count = round(target_sample_count * fabs(delta));
604
605 // Determine starting audio location
606 AudioLocation location;
607 if (previous_location.frame == 0 || abs(new_frame_number - previous_location.frame) > 2 || prev_is_increasing != is_increasing) {
608 // No previous location OR gap detected
609 location.frame = new_frame_number;
610 location.sample_start = 0;
611
612 // Create / Reset resampler
613 // We don't want to interpolate between unrelated audio data
614 if (resampler) {
615 delete resampler;
616 resampler = nullptr;
617 }
618 // Init resampler with # channels from Reader (should match the timeline)
619 resampler = new AudioResampler(Reader()->info.channels);
620
621 // Allocate buffer of silence to initialize some data inside the resampler
622 // To prevent it from becoming input limited
623 juce::AudioBuffer<float> init_samples(Reader()->info.channels, 64);
624 init_samples.clear();
625 resampler->SetBuffer(&init_samples, 1.0);
626 resampler->GetResampledBuffer();
627
628 } else {
629 // Use previous location
630 location = previous_location;

Callers

nothing calls this directly

Calls 15

ReaderClosedClass · 0.85
GetLongMethod · 0.80
GetDeltaMethod · 0.80
IsIncreasingMethod · 0.80
SetBufferMethod · 0.80
GetResampledBufferMethod · 0.80
AddAudioSilenceMethod · 0.80
GetAudioSamplesCountMethod · 0.80
SetDirectionHintMethod · 0.80
SetAudioDirectionMethod · 0.80
GetAudioChannelsCountMethod · 0.80
GetAudioSamplesMethod · 0.80

Tested by

no test coverage detected