From 9c9958ca6c51676cab549d19311df59a1b4ccf1a Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Mon, 1 Jun 2015 14:03:39 -0700 Subject: Remove variable-speed library. Bug: 21444991 Change-Id: I3e1fc7f0773ddfa227cde6b5161102a087f47702 --- variablespeed/jni/sola_time_scaler.cc | 366 ---------------------------------- 1 file changed, 366 deletions(-) delete mode 100644 variablespeed/jni/sola_time_scaler.cc (limited to 'variablespeed/jni/sola_time_scaler.cc') diff --git a/variablespeed/jni/sola_time_scaler.cc b/variablespeed/jni/sola_time_scaler.cc deleted file mode 100644 index 1ff1236..0000000 --- a/variablespeed/jni/sola_time_scaler.cc +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sola_time_scaler.h" - -#include -#include -#include - -#include "ring_buffer.h" - -#define FLAGS_sola_ring_buffer 2.0 -#define FLAGS_sola_enable_correlation true - - -namespace video_editing { - -// Returns a cross-correlation score for the specified buffers. -int SolaAnalyzer::Correlate(const float* buffer1, const float* buffer2, - int num_frames) { - CHECK(initialized_); - - int score = 0; - num_frames *= num_channels_; - while (num_frames-- > 0) { - // Increment the score if the sign bits match. - score += ((bit_cast(*buffer1++) ^ bit_cast(*buffer2++)) >= 0) - ? 1 : 0; - } - return score; -} - -// Trivial SolaAnalyzer class to bypass correlation. -class SolaBypassAnalyzer : public SolaAnalyzer { - public: - SolaBypassAnalyzer() { } - virtual int Correlate(const float*, const float*, int num_frames) { - return num_frames * num_channels_; - } -}; - - -// Default constructor. -SolaTimeScaler::SolaTimeScaler() - : input_buffer_(NULL), output_buffer_(NULL), analyzer_(NULL) { - sample_rate_ = 0; - num_channels_ = 0; - - draining_ = false; - initialized_ = false; -} - -SolaTimeScaler::~SolaTimeScaler() { - delete input_buffer_; - delete output_buffer_; - delete analyzer_; -} - -// Injects a SolaAnalyzer instance for analyzing signal frames. -void SolaTimeScaler::set_analyzer(SolaAnalyzer* analyzer) { - MutexLock lock(&mutex_); // lock out processing while updating - delete analyzer_; - analyzer_ = analyzer; -} - -// Initializes a SOLA timescaler. -void SolaTimeScaler::Init(double sample_rate, - int num_channels, - double initial_speed, - double window_duration, - double overlap_duration) { - MutexLock lock(&mutex_); // lock out processing while updating - - sample_rate_ = sample_rate; - num_channels_ = num_channels; - speed_ = initial_speed; - window_duration_ = window_duration; - overlap_duration_ = overlap_duration; - - initialized_ = true; - GenerateParameters(); - Reset(); -} - -// Adjusts the rate scaling factor. -void SolaTimeScaler::set_speed(double speed) { - MutexLock lock(&mutex_); // lock out processing while updating - - speed_ = speed; - GenerateParameters(); -} - -// Generates processing parameters from the current settings. -void SolaTimeScaler::GenerateParameters() { - if (speed_ < 0.1) { - LOGE("Requested speed %fx limited to 0.1x", speed_); - speed_ = 0.1; - } else if (speed_ > 8.0) { - LOGE("Requested speed %fx limited to 8.0x", speed_); - speed_ = 8.0; - } - - ratio_ = 1.0 / speed_; - - num_window_frames_ = nearbyint(sample_rate_ * window_duration_); - - // Limit the overlap to half the window size, and round up to an odd number. - // Half of overlap window (rounded down) is also a useful number. - overlap_duration_ = min(overlap_duration_, window_duration_ / 2.0); - num_overlap_frames_ = nearbyint(sample_rate_ * overlap_duration_); - num_overlap_frames_ |= 1; - half_overlap_frames_ = num_overlap_frames_ >> 1; - - if (speed_ >= 1.) { - // For compression (speed up), adjacent input windows overlap in the output. - input_window_offset_ = num_window_frames_; - target_merge_offset_ = nearbyint(num_window_frames_ * ratio_); - } else { - // For expansion (slow down), each input window start point overlaps the - // previous, and they are placed adjacently in the output - // (+/- half the overlap size). - input_window_offset_ = nearbyint(num_window_frames_ * speed_); - target_merge_offset_ = num_window_frames_; - } - - // Make sure we copy enough extra data to be able to perform a - // frame correlation over the range of target merge point +/- half overlap, - // even when the previous merge point was adjusted backwards a half overlap. - max_frames_to_merge_ = max(num_window_frames_, - target_merge_offset_ + (2 * num_overlap_frames_)); - min_output_to_hold_= - max_frames_to_merge_ + num_overlap_frames_ - target_merge_offset_; -} - -// The input buffer has one writer and reader. -// The output buffer has one reader/updater, and one reader/consumer. -static const int kInputReader = 0; -static const int kOutputAnalysis = 0; -static const int kOutputConsumer = 1; - -void SolaTimeScaler::Reset() { - CHECK(initialized_); - double duration = max(FLAGS_sola_ring_buffer, 20. * window_duration_); - draining_ = false; - - delete input_buffer_; - input_buffer_ = new RingBuffer(); - input_buffer_->Init(static_cast - (sample_rate_ * duration), num_channels_, 1); - - delete output_buffer_; - output_buffer_ = new RingBuffer(); - output_buffer_->Init(static_cast - (sample_rate_ * ratio_ * duration), num_channels_, 2); - - if (analyzer_ == NULL) { - if (FLAGS_sola_enable_correlation) { - analyzer_ = new SolaAnalyzer(); - } else { - analyzer_ = new SolaBypassAnalyzer(); - } - } - analyzer_->Init(sample_rate_, num_channels_); -} - -// Returns the number of frames that the input buffer can accept. -int SolaTimeScaler::input_limit() const { - CHECK(initialized_); - return input_buffer_->overhead(); -} - -// Returns the number of available output frames. -int SolaTimeScaler::available() { - CHECK(initialized_); - - int available = output_buffer_->available(kOutputConsumer); - if (available > min_output_to_hold_) { - available -= min_output_to_hold_; - } else if (draining_) { - Process(); - available = output_buffer_->available(kOutputConsumer); - if (available > min_output_to_hold_) { - available -= min_output_to_hold_; - } - } else { - available = 0; - } - return available; -} - -void SolaTimeScaler::Drain() { - CHECK(initialized_); - - draining_ = true; -} - - -// Feeds audio to the timescaler, and processes as much data as possible. -int SolaTimeScaler::InjectSamples(float* buffer, int num_frames) { - CHECK(initialized_); - - // Do not write more frames than the buffer can accept. - num_frames = min(input_limit(), num_frames); - if (!num_frames) { - return 0; - } - - // Copy samples to the input buffer and then process whatever can be consumed. - input_buffer_->Write(buffer, num_frames); - Process(); - return num_frames; -} - -// Retrieves audio data from the timescaler. -int SolaTimeScaler::RetrieveSamples(float* buffer, int num_frames) { - CHECK(initialized_); - - // Do not read more frames than available. - num_frames = min(available(), num_frames); - if (!num_frames) { - return 0; - } - - output_buffer_->Copy(kOutputConsumer, buffer, num_frames); - output_buffer_->Seek(kOutputConsumer, - output_buffer_->Tell(kOutputConsumer) + num_frames); - - return num_frames; -} - -// Munges input samples to produce output. -bool SolaTimeScaler::Process() { - CHECK(initialized_); - bool generated_data = false; - - // We can only process data if there is sufficient input available - // (or we are draining the latency), and there is sufficient room - // for output to be merged. - while (((input_buffer_->available(kInputReader) > max_frames_to_merge_) || - draining_) && (output_buffer_->overhead() >= max_frames_to_merge_)) { - MutexLock lock(&mutex_); // lock out updates while processing each window - - // Determine the number of samples to merge into the output. - int input_count = - min(input_buffer_->available(kInputReader), max_frames_to_merge_); - if (input_count == 0) { - break; - } - // The input reader always points to the next window to process. - float* input_pointer = input_buffer_->GetPointer(kInputReader, input_count); - - // The analysis reader always points to the ideal target merge point, - // minus half an overlap window (ie, the starting point for correlation). - // That means the available data from that point equals the number - // of samples that must be cross-faded. - int output_merge_cnt = output_buffer_->available(kOutputAnalysis); - float* output_pointer = - output_buffer_->GetPointer(kOutputAnalysis, output_merge_cnt); - - // If there is not enough data to do a proper correlation, - // just merge at the ideal target point. Otherwise, - // find the best correlation score, working from the center out. - int merge_offset = min(output_merge_cnt, half_overlap_frames_); - - if ((output_merge_cnt >= (2 * num_overlap_frames_)) && - (input_count >= num_overlap_frames_)) { - int best_offset = merge_offset; - int best_score = 0; - int score; - for (int i = 0; i <= half_overlap_frames_; ++i) { - score = analyzer_->Correlate(input_pointer, - output_pointer + ((merge_offset + i) * num_channels_), - num_overlap_frames_); - if (score > best_score) { - best_score = score; - best_offset = merge_offset + i; - if (score == (num_overlap_frames_ * num_channels_)) { - break; // It doesn't get better than perfect. - } - } - if (i > 0) { - score = analyzer_->Correlate(input_pointer, - output_pointer + ((merge_offset - i) * num_channels_), - num_overlap_frames_); - if (score > best_score) { - best_score = score; - best_offset = merge_offset - i; - if (score == (num_overlap_frames_ * num_channels_)) { - break; // It doesn't get better than perfect. - } - } - } - } - merge_offset = best_offset; - } else if ((output_merge_cnt > 0) && !draining_) { - LOGE("no correlation performed"); - } - - // Crossfade the overlap between input and output, and then - // copy in the remaining input. - int crossfade_count = max(0, (output_merge_cnt - merge_offset)); - crossfade_count = min(crossfade_count, input_count); - int remaining_count = input_count - crossfade_count; - - float* merge_pointer = output_pointer + (merge_offset * num_channels_); - float flt_count = static_cast(crossfade_count); - for (int i = 0; i < crossfade_count; ++i) { - // Linear cross-fade, for now. - float input_scale = static_cast(i) / flt_count; - float output_scale = 1. - input_scale; - for (int j = 0; j < num_channels_; ++j) { - *merge_pointer = (*merge_pointer * output_scale) + - (*input_pointer++ * input_scale); - ++merge_pointer; - } - } - // Copy the merged buffer back into the output, if necessary, and - // append the rest of the window. - output_buffer_->MergeBack(kOutputAnalysis, - output_pointer, output_merge_cnt); - output_buffer_->Write(input_pointer, remaining_count); - - // Advance the output analysis pointer to the next target merge point, - // minus half an overlap window. The target merge point is always - // calculated as a delta from the previous ideal target, not the actual - // target, to avoid drift. - int output_advance = target_merge_offset_; - if (output_merge_cnt < half_overlap_frames_) { - // On the first window, back up the pointer for the next correlation. - // Thereafter, that compensation is preserved. - output_advance -= half_overlap_frames_; - } - - // Don't advance beyond the available data, when finishing up. - if (draining_) { - output_advance = - min(output_advance, output_buffer_->available(kOutputAnalysis)); - } - output_buffer_->Seek(kOutputAnalysis, - output_buffer_->Tell(kOutputAnalysis) + output_advance); - - // Advance the input pointer beyond the frames that are no longer needed. - input_buffer_->Seek(kInputReader, input_buffer_->Tell(kInputReader) + - min(input_count, input_window_offset_)); - - if ((crossfade_count + remaining_count) > 0) { - generated_data = true; - } - } // while (more to process) - return generated_data; -} - -} // namespace video_editing -- cgit v1.2.3