Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/audio/utility/audio_frame_operations.h"
12 :
13 : #include <algorithm>
14 :
15 : #include "webrtc/base/checks.h"
16 : #include "webrtc/base/safe_conversions.h"
17 : #include "webrtc/modules/include/module_common_types.h"
18 :
19 : namespace webrtc {
20 : namespace {
21 :
22 : // 2.7ms @ 48kHz, 4ms @ 32kHz, 8ms @ 16kHz.
23 : const size_t kMuteFadeFrames = 128;
24 : const float kMuteFadeInc = 1.0f / kMuteFadeFrames;
25 :
26 : } // namespace
27 :
28 0 : void AudioFrameOperations::Add(const AudioFrame& frame_to_add,
29 : AudioFrame* result_frame) {
30 : // Sanity check.
31 0 : RTC_DCHECK(result_frame);
32 0 : RTC_DCHECK_GT(result_frame->num_channels_, 0);
33 0 : RTC_DCHECK_EQ(result_frame->num_channels_, frame_to_add.num_channels_);
34 :
35 0 : bool no_previous_data = false;
36 0 : if (result_frame->samples_per_channel_ != frame_to_add.samples_per_channel_) {
37 : // Special case we have no data to start with.
38 0 : RTC_DCHECK_EQ(result_frame->samples_per_channel_, 0);
39 0 : result_frame->samples_per_channel_ = frame_to_add.samples_per_channel_;
40 0 : no_previous_data = true;
41 : }
42 :
43 0 : if (result_frame->vad_activity_ == AudioFrame::kVadActive ||
44 0 : frame_to_add.vad_activity_ == AudioFrame::kVadActive) {
45 0 : result_frame->vad_activity_ = AudioFrame::kVadActive;
46 0 : } else if (result_frame->vad_activity_ == AudioFrame::kVadUnknown ||
47 0 : frame_to_add.vad_activity_ == AudioFrame::kVadUnknown) {
48 0 : result_frame->vad_activity_ = AudioFrame::kVadUnknown;
49 : }
50 :
51 0 : if (result_frame->speech_type_ != frame_to_add.speech_type_)
52 0 : result_frame->speech_type_ = AudioFrame::kUndefined;
53 :
54 0 : if (no_previous_data) {
55 0 : std::copy(frame_to_add.data_, frame_to_add.data_ +
56 0 : frame_to_add.samples_per_channel_ *
57 0 : result_frame->num_channels_,
58 0 : result_frame->data_);
59 : } else {
60 0 : for (size_t i = 0;
61 0 : i < result_frame->samples_per_channel_ * result_frame->num_channels_;
62 : i++) {
63 0 : const int32_t wrap_guard = static_cast<int32_t>(result_frame->data_[i]) +
64 0 : static_cast<int32_t>(frame_to_add.data_[i]);
65 0 : result_frame->data_[i] = rtc::saturated_cast<int16_t>(wrap_guard);
66 : }
67 : }
68 0 : return;
69 : }
70 :
71 0 : void AudioFrameOperations::MonoToStereo(const int16_t* src_audio,
72 : size_t samples_per_channel,
73 : int16_t* dst_audio) {
74 0 : for (size_t i = 0; i < samples_per_channel; i++) {
75 0 : dst_audio[2 * i] = src_audio[i];
76 0 : dst_audio[2 * i + 1] = src_audio[i];
77 : }
78 0 : }
79 :
80 0 : int AudioFrameOperations::MonoToStereo(AudioFrame* frame) {
81 0 : if (frame->num_channels_ != 1) {
82 0 : return -1;
83 : }
84 0 : if ((frame->samples_per_channel_ * 2) >= AudioFrame::kMaxDataSizeSamples) {
85 : // Not enough memory to expand from mono to stereo.
86 0 : return -1;
87 : }
88 :
89 : int16_t data_copy[AudioFrame::kMaxDataSizeSamples];
90 0 : memcpy(data_copy, frame->data_,
91 0 : sizeof(int16_t) * frame->samples_per_channel_);
92 0 : MonoToStereo(data_copy, frame->samples_per_channel_, frame->data_);
93 0 : frame->num_channels_ = 2;
94 :
95 0 : return 0;
96 : }
97 :
98 0 : void AudioFrameOperations::StereoToMono(const int16_t* src_audio,
99 : size_t samples_per_channel,
100 : int16_t* dst_audio) {
101 0 : for (size_t i = 0; i < samples_per_channel; i++) {
102 0 : dst_audio[i] = (src_audio[2 * i] + src_audio[2 * i + 1]) >> 1;
103 : }
104 0 : }
105 :
106 0 : int AudioFrameOperations::StereoToMono(AudioFrame* frame) {
107 0 : if (frame->num_channels_ != 2) {
108 0 : return -1;
109 : }
110 :
111 0 : StereoToMono(frame->data_, frame->samples_per_channel_, frame->data_);
112 0 : frame->num_channels_ = 1;
113 :
114 0 : return 0;
115 : }
116 :
117 0 : void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
118 0 : RTC_DCHECK(frame);
119 0 : if (frame->num_channels_ != 2) {
120 0 : return;
121 : }
122 :
123 0 : for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
124 0 : int16_t temp_data = frame->data_[i];
125 0 : frame->data_[i] = frame->data_[i + 1];
126 0 : frame->data_[i + 1] = temp_data;
127 : }
128 : }
129 :
130 0 : void AudioFrameOperations::Mute(AudioFrame* frame,
131 : bool previous_frame_muted,
132 : bool current_frame_muted) {
133 0 : RTC_DCHECK(frame);
134 0 : if (!previous_frame_muted && !current_frame_muted) {
135 : // Not muted, don't touch.
136 0 : } else if (previous_frame_muted && current_frame_muted) {
137 : // Frame fully muted.
138 0 : size_t total_samples = frame->samples_per_channel_ * frame->num_channels_;
139 0 : RTC_DCHECK_GE(AudioFrame::kMaxDataSizeSamples, total_samples);
140 0 : memset(frame->data_, 0, sizeof(frame->data_[0]) * total_samples);
141 : } else {
142 : // Limit number of samples to fade, if frame isn't long enough.
143 0 : size_t count = kMuteFadeFrames;
144 0 : float inc = kMuteFadeInc;
145 0 : if (frame->samples_per_channel_ < kMuteFadeFrames) {
146 0 : count = frame->samples_per_channel_;
147 0 : if (count > 0) {
148 0 : inc = 1.0f / count;
149 : }
150 : }
151 :
152 0 : size_t start = 0;
153 0 : size_t end = count;
154 0 : float start_g = 0.0f;
155 0 : if (current_frame_muted) {
156 : // Fade out the last |count| samples of frame.
157 0 : RTC_DCHECK(!previous_frame_muted);
158 0 : start = frame->samples_per_channel_ - count;
159 0 : end = frame->samples_per_channel_;
160 0 : start_g = 1.0f;
161 0 : inc = -inc;
162 : } else {
163 : // Fade in the first |count| samples of frame.
164 0 : RTC_DCHECK(previous_frame_muted);
165 : }
166 :
167 : // Perform fade.
168 0 : size_t channels = frame->num_channels_;
169 0 : for (size_t j = 0; j < channels; ++j) {
170 0 : float g = start_g;
171 0 : for (size_t i = start * channels; i < end * channels; i += channels) {
172 0 : g += inc;
173 0 : frame->data_[i + j] *= g;
174 : }
175 : }
176 : }
177 0 : }
178 :
179 0 : void AudioFrameOperations::Mute(AudioFrame* frame) {
180 0 : Mute(frame, true, true);
181 0 : }
182 :
183 0 : void AudioFrameOperations::ApplyHalfGain(AudioFrame* frame) {
184 0 : RTC_DCHECK(frame);
185 0 : RTC_DCHECK_GT(frame->num_channels_, 0);
186 0 : if (frame->num_channels_ < 1) {
187 0 : return;
188 : }
189 :
190 0 : for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
191 : i++) {
192 0 : frame->data_[i] = frame->data_[i] >> 1;
193 : }
194 : }
195 :
196 0 : int AudioFrameOperations::Scale(float left, float right, AudioFrame& frame) {
197 0 : if (frame.num_channels_ != 2) {
198 0 : return -1;
199 : }
200 :
201 0 : for (size_t i = 0; i < frame.samples_per_channel_; i++) {
202 0 : frame.data_[2 * i] = static_cast<int16_t>(left * frame.data_[2 * i]);
203 0 : frame.data_[2 * i + 1] =
204 0 : static_cast<int16_t>(right * frame.data_[2 * i + 1]);
205 : }
206 0 : return 0;
207 : }
208 :
209 0 : int AudioFrameOperations::ScaleWithSat(float scale, AudioFrame& frame) {
210 0 : int32_t temp_data = 0;
211 :
212 : // Ensure that the output result is saturated [-32768, +32767].
213 0 : for (size_t i = 0; i < frame.samples_per_channel_ * frame.num_channels_;
214 : i++) {
215 0 : temp_data = static_cast<int32_t>(scale * frame.data_[i]);
216 0 : if (temp_data < -32768) {
217 0 : frame.data_[i] = -32768;
218 0 : } else if (temp_data > 32767) {
219 0 : frame.data_[i] = 32767;
220 : } else {
221 0 : frame.data_[i] = static_cast<int16_t>(temp_data);
222 : }
223 : }
224 0 : return 0;
225 : }
226 : } // namespace webrtc
|