• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "audio/utility/audio_frame_operations.h"
12 
13 #include <string.h>
14 
15 #include <algorithm>
16 #include <cstdint>
17 #include <utility>
18 
19 #include "common_audio/include/audio_util.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/numerics/safe_conversions.h"
22 
23 namespace webrtc {
24 namespace {
25 
26 // 2.7ms @ 48kHz, 4ms @ 32kHz, 8ms @ 16kHz.
27 const size_t kMuteFadeFrames = 128;
28 const float kMuteFadeInc = 1.0f / kMuteFadeFrames;
29 
30 }  // namespace
31 
Add(const AudioFrame & frame_to_add,AudioFrame * result_frame)32 void AudioFrameOperations::Add(const AudioFrame& frame_to_add,
33                                AudioFrame* result_frame) {
34   // Sanity check.
35   RTC_DCHECK(result_frame);
36   RTC_DCHECK_GT(result_frame->num_channels_, 0);
37   RTC_DCHECK_EQ(result_frame->num_channels_, frame_to_add.num_channels_);
38 
39   bool no_previous_data = result_frame->muted();
40   if (result_frame->samples_per_channel_ != frame_to_add.samples_per_channel_) {
41     // Special case we have no data to start with.
42     RTC_DCHECK_EQ(result_frame->samples_per_channel_, 0);
43     result_frame->samples_per_channel_ = frame_to_add.samples_per_channel_;
44     no_previous_data = true;
45   }
46 
47   if (result_frame->vad_activity_ == AudioFrame::kVadActive ||
48       frame_to_add.vad_activity_ == AudioFrame::kVadActive) {
49     result_frame->vad_activity_ = AudioFrame::kVadActive;
50   } else if (result_frame->vad_activity_ == AudioFrame::kVadUnknown ||
51              frame_to_add.vad_activity_ == AudioFrame::kVadUnknown) {
52     result_frame->vad_activity_ = AudioFrame::kVadUnknown;
53   }
54 
55   if (result_frame->speech_type_ != frame_to_add.speech_type_)
56     result_frame->speech_type_ = AudioFrame::kUndefined;
57 
58   if (!frame_to_add.muted()) {
59     const int16_t* in_data = frame_to_add.data();
60     int16_t* out_data = result_frame->mutable_data();
61     size_t length =
62         frame_to_add.samples_per_channel_ * frame_to_add.num_channels_;
63     if (no_previous_data) {
64       std::copy(in_data, in_data + length, out_data);
65     } else {
66       for (size_t i = 0; i < length; i++) {
67         const int32_t wrap_guard = static_cast<int32_t>(out_data[i]) +
68                                    static_cast<int32_t>(in_data[i]);
69         out_data[i] = rtc::saturated_cast<int16_t>(wrap_guard);
70       }
71     }
72   }
73 }
74 
MonoToStereo(AudioFrame * frame)75 int AudioFrameOperations::MonoToStereo(AudioFrame* frame) {
76   if (frame->num_channels_ != 1) {
77     return -1;
78   }
79   UpmixChannels(2, frame);
80   return 0;
81 }
82 
StereoToMono(AudioFrame * frame)83 int AudioFrameOperations::StereoToMono(AudioFrame* frame) {
84   if (frame->num_channels_ != 2) {
85     return -1;
86   }
87   DownmixChannels(1, frame);
88   return frame->num_channels_ == 1 ? 0 : -1;
89 }
90 
QuadToStereo(const int16_t * src_audio,size_t samples_per_channel,int16_t * dst_audio)91 void AudioFrameOperations::QuadToStereo(const int16_t* src_audio,
92                                         size_t samples_per_channel,
93                                         int16_t* dst_audio) {
94   for (size_t i = 0; i < samples_per_channel; i++) {
95     dst_audio[i * 2] =
96         (static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1]) >> 1;
97     dst_audio[i * 2 + 1] =
98         (static_cast<int32_t>(src_audio[4 * i + 2]) + src_audio[4 * i + 3]) >>
99         1;
100   }
101 }
102 
QuadToStereo(AudioFrame * frame)103 int AudioFrameOperations::QuadToStereo(AudioFrame* frame) {
104   if (frame->num_channels_ != 4) {
105     return -1;
106   }
107 
108   RTC_DCHECK_LE(frame->samples_per_channel_ * 4,
109                 AudioFrame::kMaxDataSizeSamples);
110 
111   if (!frame->muted()) {
112     QuadToStereo(frame->data(), frame->samples_per_channel_,
113                  frame->mutable_data());
114   }
115   frame->num_channels_ = 2;
116 
117   return 0;
118 }
119 
DownmixChannels(const int16_t * src_audio,size_t src_channels,size_t samples_per_channel,size_t dst_channels,int16_t * dst_audio)120 void AudioFrameOperations::DownmixChannels(const int16_t* src_audio,
121                                            size_t src_channels,
122                                            size_t samples_per_channel,
123                                            size_t dst_channels,
124                                            int16_t* dst_audio) {
125   if (src_channels > 1 && dst_channels == 1) {
126     DownmixInterleavedToMono(src_audio, samples_per_channel, src_channels,
127                              dst_audio);
128     return;
129   } else if (src_channels == 4 && dst_channels == 2) {
130     QuadToStereo(src_audio, samples_per_channel, dst_audio);
131     return;
132   }
133 
134   RTC_NOTREACHED() << "src_channels: " << src_channels
135                    << ", dst_channels: " << dst_channels;
136 }
137 
DownmixChannels(size_t dst_channels,AudioFrame * frame)138 void AudioFrameOperations::DownmixChannels(size_t dst_channels,
139                                            AudioFrame* frame) {
140   RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_,
141                 AudioFrame::kMaxDataSizeSamples);
142   if (frame->num_channels_ > 1 && dst_channels == 1) {
143     if (!frame->muted()) {
144       DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_,
145                                frame->num_channels_, frame->mutable_data());
146     }
147     frame->num_channels_ = 1;
148   } else if (frame->num_channels_ == 4 && dst_channels == 2) {
149     int err = QuadToStereo(frame);
150     RTC_DCHECK_EQ(err, 0);
151   } else {
152     RTC_NOTREACHED() << "src_channels: " << frame->num_channels_
153                      << ", dst_channels: " << dst_channels;
154   }
155 }
156 
UpmixChannels(size_t target_number_of_channels,AudioFrame * frame)157 void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels,
158                                          AudioFrame* frame) {
159   RTC_DCHECK_EQ(frame->num_channels_, 1);
160   RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels,
161                 AudioFrame::kMaxDataSizeSamples);
162 
163   if (frame->num_channels_ != 1 ||
164       frame->samples_per_channel_ * target_number_of_channels >
165           AudioFrame::kMaxDataSizeSamples) {
166     return;
167   }
168 
169   if (!frame->muted()) {
170     // Up-mixing done in place. Going backwards through the frame ensure nothing
171     // is irrevocably overwritten.
172     for (int i = frame->samples_per_channel_ - 1; i >= 0; i--) {
173       for (size_t j = 0; j < target_number_of_channels; ++j) {
174         frame->mutable_data()[target_number_of_channels * i + j] =
175             frame->data()[i];
176       }
177     }
178   }
179   frame->num_channels_ = target_number_of_channels;
180 }
181 
SwapStereoChannels(AudioFrame * frame)182 void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
183   RTC_DCHECK(frame);
184   if (frame->num_channels_ != 2 || frame->muted()) {
185     return;
186   }
187 
188   int16_t* frame_data = frame->mutable_data();
189   for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
190     std::swap(frame_data[i], frame_data[i + 1]);
191   }
192 }
193 
Mute(AudioFrame * frame,bool previous_frame_muted,bool current_frame_muted)194 void AudioFrameOperations::Mute(AudioFrame* frame,
195                                 bool previous_frame_muted,
196                                 bool current_frame_muted) {
197   RTC_DCHECK(frame);
198   if (!previous_frame_muted && !current_frame_muted) {
199     // Not muted, don't touch.
200   } else if (previous_frame_muted && current_frame_muted) {
201     // Frame fully muted.
202     size_t total_samples = frame->samples_per_channel_ * frame->num_channels_;
203     RTC_DCHECK_GE(AudioFrame::kMaxDataSizeSamples, total_samples);
204     frame->Mute();
205   } else {
206     // Fade is a no-op on a muted frame.
207     if (frame->muted()) {
208       return;
209     }
210 
211     // Limit number of samples to fade, if frame isn't long enough.
212     size_t count = kMuteFadeFrames;
213     float inc = kMuteFadeInc;
214     if (frame->samples_per_channel_ < kMuteFadeFrames) {
215       count = frame->samples_per_channel_;
216       if (count > 0) {
217         inc = 1.0f / count;
218       }
219     }
220 
221     size_t start = 0;
222     size_t end = count;
223     float start_g = 0.0f;
224     if (current_frame_muted) {
225       // Fade out the last |count| samples of frame.
226       RTC_DCHECK(!previous_frame_muted);
227       start = frame->samples_per_channel_ - count;
228       end = frame->samples_per_channel_;
229       start_g = 1.0f;
230       inc = -inc;
231     } else {
232       // Fade in the first |count| samples of frame.
233       RTC_DCHECK(previous_frame_muted);
234     }
235 
236     // Perform fade.
237     int16_t* frame_data = frame->mutable_data();
238     size_t channels = frame->num_channels_;
239     for (size_t j = 0; j < channels; ++j) {
240       float g = start_g;
241       for (size_t i = start * channels; i < end * channels; i += channels) {
242         g += inc;
243         frame_data[i + j] *= g;
244       }
245     }
246   }
247 }
248 
Mute(AudioFrame * frame)249 void AudioFrameOperations::Mute(AudioFrame* frame) {
250   Mute(frame, true, true);
251 }
252 
ApplyHalfGain(AudioFrame * frame)253 void AudioFrameOperations::ApplyHalfGain(AudioFrame* frame) {
254   RTC_DCHECK(frame);
255   RTC_DCHECK_GT(frame->num_channels_, 0);
256   if (frame->num_channels_ < 1 || frame->muted()) {
257     return;
258   }
259 
260   int16_t* frame_data = frame->mutable_data();
261   for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
262        i++) {
263     frame_data[i] = frame_data[i] >> 1;
264   }
265 }
266 
Scale(float left,float right,AudioFrame * frame)267 int AudioFrameOperations::Scale(float left, float right, AudioFrame* frame) {
268   if (frame->num_channels_ != 2) {
269     return -1;
270   } else if (frame->muted()) {
271     return 0;
272   }
273 
274   int16_t* frame_data = frame->mutable_data();
275   for (size_t i = 0; i < frame->samples_per_channel_; i++) {
276     frame_data[2 * i] = static_cast<int16_t>(left * frame_data[2 * i]);
277     frame_data[2 * i + 1] = static_cast<int16_t>(right * frame_data[2 * i + 1]);
278   }
279   return 0;
280 }
281 
ScaleWithSat(float scale,AudioFrame * frame)282 int AudioFrameOperations::ScaleWithSat(float scale, AudioFrame* frame) {
283   if (frame->muted()) {
284     return 0;
285   }
286 
287   int16_t* frame_data = frame->mutable_data();
288   for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
289        i++) {
290     frame_data[i] = rtc::saturated_cast<int16_t>(scale * frame_data[i]);
291   }
292   return 0;
293 }
294 }  // namespace webrtc
295