/* * 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. */ #ifndef FRAMEWORKS_EX_VARIABLESPEED_JNI_SOLA_TIME_SCALER_H_ #define FRAMEWORKS_EX_VARIABLESPEED_JNI_SOLA_TIME_SCALER_H_ #include <android/log.h> #include <no_synchronization.h> #include <list> #include <vector> #include "macros.h" // Time-domain audio playback rate scaler using phase-aligned Synchronized // OverLap Add (SOLA). namespace video_editing { class RingBuffer; // The default SolaAnalyzer implements a sign-bit cross-correlation // function for determining the best fit between two signals. class SolaAnalyzer { public: SolaAnalyzer() : initialized_(false) { } virtual ~SolaAnalyzer() { } // Initializes a SolaAnalyzer. // @param sample_rate sample rate of the audio signal. // @param num_channels number of interleaved channels in the signal. void Init(int sample_rate, int num_channels) { sample_rate_ = sample_rate; num_channels_ = num_channels; initialized_ = true; } // Returns a cross-correlation score for the specified buffers. // The correlation is performed over all channels of a multi-channel signal. // @param buffer1 pointer to interleaved input samples // @param buffer2 pointer to interleaved input samples // @param num_frames number of input frames (that is to say, number of // samples / number of channels) // @param returns a correlation score in the range zero to num_frames virtual int Correlate(const float* buffer1, const float* buffer2, int num_frames); protected: bool initialized_; int sample_rate_; int num_channels_; DISALLOW_COPY_AND_ASSIGN(SolaAnalyzer); }; class SolaTimeScaler { public: // Default constructor. SolaTimeScaler(); virtual ~SolaTimeScaler(); // Injects a SolaAnalyzer instance for analyzing signal frames. // The scaler takes ownership of this instance. // This is normally called once, before Init(). // @param analyzer SolaAnalyzer instance void set_analyzer(SolaAnalyzer* analyzer); // Initializes a SOLA timescaler. // @param sample_rate sample rate of the signal to process // @param num_channels number of channels of the signal to process // @param initial_speed starting rate scaling factor // @param window_duration processing window size, in seconds // @param overlap_duration correlation overlap size, in seconds void Init(double sample_rate, int num_channels, double initial_speed, double window_duration, double overlap_duration); // Adjusts the rate scaling factor. // This may be called concurrently with processing, and will // take effect on the next processing window. // @param speed rate scaling factor void set_speed(double speed); // Indicates that we are done with the input and won't call Process anymore // This processes all the data reamining in the analysis buffer. void Drain(); // Flushes the buffers associated with the scaler. void Reset(); // Feeds audio to the timescaler, and processes as much data as possible. // @param buffer pointer to interleaved float input samples // @param num_frames number of frames (num_samples / num_channels) // @returns number of frames actually accepted int InjectSamples(float* buffer, int num_frames); // Retrieves audio data from the timescaler. // @param buffer pointer to buffer to receive interleaved float output // @param num_frames maximum desired number of frames // @returns number of frames actually returned int RetrieveSamples(float* buffer, int num_frames); // Returns the number of frames that the input buffer can accept. // @returns number of frames for the next Process() call int input_limit() const; // Returns the number of available output frames. // @returns number of frames that can be retrieved int available(); int num_channels() const { return num_channels_; } private: mutable Mutex mutex_; // allows concurrent produce/consume/param change bool initialized_; // set true when input parameters have been set bool draining_; // set true to drain latency // Input parameters. int num_channels_; // channel valence of audio stream double sample_rate_; // sample rate of audio stream double window_duration_; // the nominal time quantum for processing double overlap_duration_; // the maximum slip for correlating windows double speed_; // varispeed rate // Derived parameters. double ratio_; // inverse of speed int num_window_frames_; // window_duration_ expressed as frame count int num_overlap_frames_; // overlap_duration_ expressed as frame count int half_overlap_frames_; // half of the overlap int input_window_offset_; // frame delta between input windows int target_merge_offset_; // ideal frame delta between output windows int max_frames_to_merge_; // ideal frame count to merge to output int min_output_to_hold_; // number of output frames needed for next merge RingBuffer* input_buffer_; RingBuffer* output_buffer_; SolaAnalyzer* analyzer_; // Generates processing parameters from the current settings. void GenerateParameters(); // Munges input samples to produce output. // @returns true if any output samples were generated bool Process(); DISALLOW_COPY_AND_ASSIGN(SolaTimeScaler); }; } // namespace video_editing #endif // FRAMEWORKS_EX_VARIABLESPEED_JNI_SOLA_TIME_SCALER_H_