1b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson/*
2b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Copyright (C) 2011 The Android Open Source Project
3b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *
4b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Licensed under the Apache License, Version 2.0 (the "License");
5b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * you may not use this file except in compliance with the License.
6b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * You may obtain a copy of the License at
7b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *
8b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *      http://www.apache.org/licenses/LICENSE-2.0
9b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *
10b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Unless required by applicable law or agreed to in writing, software
11b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * distributed under the License is distributed on an "AS IS" BASIS,
12b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * See the License for the specific language governing permissions and
14b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * limitations under the License.
15b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson */
16b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
17b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#ifndef FRAMEWORKS_EX_VARIABLESPEED_JNI_SOLA_TIME_SCALER_H_
18b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#define FRAMEWORKS_EX_VARIABLESPEED_JNI_SOLA_TIME_SCALER_H_
19b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
20b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include <android/log.h>
21b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
22b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include <no_synchronization.h>
23b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
24b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include <list>
25b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include <vector>
26b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
27b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include "macros.h"
28b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
29b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson// Time-domain audio playback rate scaler using phase-aligned Synchronized
30b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson// OverLap Add (SOLA).
31b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
32b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonnamespace video_editing {
33b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
34b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonclass RingBuffer;
35b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
36b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson// The default SolaAnalyzer implements a sign-bit cross-correlation
37b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson// function for determining the best fit between two signals.
38b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonclass SolaAnalyzer {
39b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson public:
40b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  SolaAnalyzer() : initialized_(false) { }
41b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  virtual ~SolaAnalyzer() { }
42b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
43b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Initializes a SolaAnalyzer.
44b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param sample_rate sample rate of the audio signal.
45b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param num_channels number of interleaved channels in the signal.
46b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void Init(int sample_rate, int num_channels) {
47b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    sample_rate_ = sample_rate;
48b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    num_channels_ = num_channels;
49b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    initialized_ = true;
50b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  }
51b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
52b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Returns a cross-correlation score for the specified buffers.
53b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // The correlation is performed over all channels of a multi-channel signal.
54b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param buffer1 pointer to interleaved input samples
55b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param buffer2 pointer to interleaved input samples
56b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param num_frames number of input frames (that is to say, number of
57b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  //                   samples / number of channels)
58b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param returns a correlation score in the range zero to num_frames
59b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  virtual int Correlate(const float* buffer1, const float* buffer2,
60b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                        int num_frames);
61b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
62b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson protected:
63b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  bool initialized_;
64b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int sample_rate_;
65b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int num_channels_;
66b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
67b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  DISALLOW_COPY_AND_ASSIGN(SolaAnalyzer);
68b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson};
69b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
70b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
71b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonclass SolaTimeScaler {
72b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson public:
73b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Default constructor.
74b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  SolaTimeScaler();
75b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  virtual ~SolaTimeScaler();
76b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
77b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Injects a SolaAnalyzer instance for analyzing signal frames.
78b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // The scaler takes ownership of this instance.
79b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // This is normally called once, before Init().
80b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param analyzer SolaAnalyzer instance
81b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void set_analyzer(SolaAnalyzer* analyzer);
82b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
83b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Initializes a SOLA timescaler.
84b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param sample_rate sample rate of the signal to process
85b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param num_channels number of channels of the signal to process
86b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param initial_speed starting rate scaling factor
87b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param window_duration processing window size, in seconds
88b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param overlap_duration correlation overlap size, in seconds
89b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void Init(double sample_rate, int num_channels, double initial_speed,
90b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            double window_duration, double overlap_duration);
91b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
92b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Adjusts the rate scaling factor.
93b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // This may be called concurrently with processing, and will
94b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // take effect on the next processing window.
95b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param speed rate scaling factor
96b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void set_speed(double speed);
97b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
98b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Indicates that we are done with the input and won't call Process anymore
99b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // This processes all the data reamining in the analysis buffer.
100b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void Drain();
101b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
102b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Flushes the buffers associated with the scaler.
103b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void Reset();
104b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
105b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Feeds audio to the timescaler, and processes as much data as possible.
106b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param buffer pointer to interleaved float input samples
107b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param num_frames number of frames (num_samples / num_channels)
108b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @returns number of frames actually accepted
109b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int InjectSamples(float* buffer, int num_frames);
110b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
111b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Retrieves audio data from the timescaler.
112b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param buffer pointer to buffer to receive interleaved float output
113b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @param num_frames maximum desired number of frames
114b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @returns number of frames actually returned
115b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int RetrieveSamples(float* buffer, int num_frames);
116b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
117b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Returns the number of frames that the input buffer can accept.
118b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @returns number of frames for the next Process() call
119b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int input_limit() const;
120b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
121b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Returns the number of available output frames.
122b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @returns number of frames that can be retrieved
123b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int available();
124b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
125b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int num_channels() const { return num_channels_; }
126b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
127b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson private:
128b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  mutable Mutex mutex_;       // allows concurrent produce/consume/param change
129b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  bool initialized_;          // set true when input parameters have been set
130b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  bool draining_;             // set true to drain latency
131b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
132b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Input parameters.
133b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int num_channels_;          // channel valence of audio stream
134b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  double sample_rate_;        // sample rate of audio stream
135b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  double window_duration_;    // the nominal time quantum for processing
136b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  double overlap_duration_;   // the maximum slip for correlating windows
137b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  double speed_;              // varispeed rate
138b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
139b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Derived parameters.
140b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  double ratio_;              // inverse of speed
141b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int num_window_frames_;     // window_duration_ expressed as frame count
142b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int num_overlap_frames_;    // overlap_duration_ expressed as frame count
143b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int half_overlap_frames_;   // half of the overlap
144b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int input_window_offset_;   // frame delta between input windows
145b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int target_merge_offset_;   // ideal frame delta between output windows
146b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int max_frames_to_merge_;   // ideal frame count to merge to output
147b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  int min_output_to_hold_;    // number of output frames needed for next merge
148b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
149b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  RingBuffer* input_buffer_;
150b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  RingBuffer* output_buffer_;
151b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  SolaAnalyzer* analyzer_;
152b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
153b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Generates processing parameters from the current settings.
154b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  void GenerateParameters();
155b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
156b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // Munges input samples to produce output.
157b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  // @returns true if any output samples were generated
158b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  bool Process();
159b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
160b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson  DISALLOW_COPY_AND_ASSIGN(SolaTimeScaler);
161b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson};
162b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
163b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson}  // namespace video_editing
164b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
165b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#endif  // FRAMEWORKS_EX_VARIABLESPEED_JNI_SOLA_TIME_SCALER_H_
166