1 /*
2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
23 * DAMAGE.
24 */
25
26 #include "third_party/blink/renderer/platform/audio/audio_resampler.h"
27 #include "third_party/blink/renderer/platform/audio/audio_resampler_kernel.h"
28 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
29
30 namespace blink {
31
32 const size_t AudioResamplerKernel::kMaxFramesToProcess = 128;
33
AudioResamplerKernel(AudioResampler * resampler)34 AudioResamplerKernel::AudioResamplerKernel(AudioResampler* resampler)
35 : resampler_(resampler),
36 // The buffer size must be large enough to hold up to two extra sample
37 // frames for the linear interpolation.
38 source_buffer_(
39 2 + static_cast<int>(kMaxFramesToProcess * AudioResampler::kMaxRate)),
40 virtual_read_index_(0.0),
41 fill_index_(0) {
42 last_values_[0] = 0.0f;
43 last_values_[1] = 0.0f;
44 }
45
GetSourcePointer(uint32_t frames_to_process,size_t * number_of_source_frames_needed_p)46 float* AudioResamplerKernel::GetSourcePointer(
47 uint32_t frames_to_process,
48 size_t* number_of_source_frames_needed_p) {
49 DCHECK_LE(frames_to_process, kMaxFramesToProcess);
50
51 // Calculate the next "virtual" index. After process() is called,
52 // m_virtualReadIndex will equal this value.
53 double next_fractional_index =
54 virtual_read_index_ + frames_to_process * Rate();
55
56 // Because we're linearly interpolating between the previous and next sample
57 // we need to round up so we include the next sample.
58 int end_index = static_cast<int>(next_fractional_index +
59 1.0); // round up to next integer index
60
61 // Determine how many input frames we'll need.
62 // We need to fill the buffer up to and including endIndex (so add 1) but
63 // we've already buffered m_fillIndex frames from last time.
64 size_t frames_needed = 1 + end_index - fill_index_;
65 if (number_of_source_frames_needed_p)
66 *number_of_source_frames_needed_p = frames_needed;
67
68 // Do bounds checking for the source buffer.
69 DCHECK_LT(fill_index_, source_buffer_.size());
70 DCHECK_LE(fill_index_ + frames_needed, source_buffer_.size());
71
72 return source_buffer_.Data() + fill_index_;
73 }
74
Process(float * destination,uint32_t frames_to_process)75 void AudioResamplerKernel::Process(float* destination,
76 uint32_t frames_to_process) {
77 DCHECK_LE(frames_to_process, kMaxFramesToProcess);
78
79 float* source = source_buffer_.Data();
80
81 double rate = this->Rate();
82 rate = clampTo(rate, 0.0, AudioResampler::kMaxRate);
83
84 // Start out with the previous saved values (if any).
85 if (fill_index_ > 0) {
86 source[0] = last_values_[0];
87 source[1] = last_values_[1];
88 }
89
90 // Make a local copy.
91 double virtual_read_index = virtual_read_index_;
92
93 // Sanity check source buffer access.
94 DCHECK_GT(frames_to_process, 0u);
95 DCHECK_GE(virtual_read_index, 0);
96 DCHECK_LT(1 + static_cast<unsigned>(virtual_read_index +
97 (frames_to_process - 1) * rate),
98 source_buffer_.size());
99
100 // Do the linear interpolation.
101 int n = frames_to_process;
102 while (n--) {
103 unsigned read_index = static_cast<unsigned>(virtual_read_index);
104 double interpolation_factor = virtual_read_index - read_index;
105
106 double sample1 = source[read_index];
107 double sample2 = source[read_index + 1];
108
109 double sample =
110 (1.0 - interpolation_factor) * sample1 + interpolation_factor * sample2;
111
112 *destination++ = static_cast<float>(sample);
113
114 virtual_read_index += rate;
115 }
116
117 // Save the last two sample-frames which will later be used at the beginning
118 // of the source buffer the next time around.
119 int read_index = static_cast<int>(virtual_read_index);
120 last_values_[0] = source[read_index];
121 last_values_[1] = source[read_index + 1];
122 fill_index_ = 2;
123
124 // Wrap the virtual read index back to the start of the buffer.
125 virtual_read_index -= read_index;
126
127 // Put local copy back into member variable.
128 virtual_read_index_ = virtual_read_index;
129 }
130
Reset()131 void AudioResamplerKernel::Reset() {
132 virtual_read_index_ = 0.0;
133 fill_index_ = 0;
134 last_values_[0] = 0.0f;
135 last_values_[1] = 0.0f;
136 }
137
Rate() const138 double AudioResamplerKernel::Rate() const {
139 return resampler_->Rate();
140 }
141
142 } // namespace blink
143