summaryrefslogtreecommitdiffstats
path: root/variablespeed/jni/sola_time_scaler.h
blob: c903f610b250fbe7b69190bb712902c8df4f6b9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
 * 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_