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