audio_frame_operations.cc (7311B)
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 <algorithm> 14 #include <cstdint> 15 #include <cstring> 16 #include <utility> 17 18 #include "api/audio/audio_frame.h" 19 #include "api/audio/audio_view.h" 20 #include "common_audio/include/audio_util.h" 21 #include "rtc_base/checks.h" 22 #include "rtc_base/numerics/safe_conversions.h" 23 24 namespace webrtc { 25 namespace { 26 27 // 2.7ms @ 48kHz, 4ms @ 32kHz, 8ms @ 16kHz. 28 const size_t kMuteFadeFrames = 128; 29 const float kMuteFadeInc = 1.0f / kMuteFadeFrames; 30 31 } // namespace 32 33 void AudioFrameOperations::QuadToStereo( 34 InterleavedView<const int16_t> src_audio, 35 InterleavedView<int16_t> dst_audio) { 36 RTC_DCHECK_EQ(NumChannels(src_audio), 4); 37 RTC_DCHECK_EQ(NumChannels(dst_audio), 2); 38 RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio)); 39 for (size_t i = 0; i < SamplesPerChannel(src_audio); ++i) { 40 auto dst_frame = i * 2; 41 dst_audio[dst_frame] = 42 (static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1]) >> 1; 43 dst_audio[dst_frame + 1] = 44 (static_cast<int32_t>(src_audio[4 * i + 2]) + src_audio[4 * i + 3]) >> 45 1; 46 } 47 } 48 49 int AudioFrameOperations::QuadToStereo(AudioFrame* frame) { 50 if (frame->num_channels_ != 4) { 51 return -1; 52 } 53 54 RTC_DCHECK_LE(frame->samples_per_channel_ * 4, 55 AudioFrame::kMaxDataSizeSamples); 56 57 if (!frame->muted()) { 58 // Note that `src` and `dst` will map in to the same buffer, but the call 59 // to `mutable_data()` changes the layout of `frame`, so `src` and `dst` 60 // will have different dimensions (important to call `data_view()` first). 61 auto src = frame->data_view(); 62 auto dst = frame->mutable_data(frame->samples_per_channel_, 2); 63 QuadToStereo(src, dst); 64 } else { 65 frame->num_channels_ = 2; 66 } 67 68 return 0; 69 } 70 71 void AudioFrameOperations::DownmixChannels( 72 InterleavedView<const int16_t> src_audio, 73 InterleavedView<int16_t> dst_audio) { 74 RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio)); 75 if (NumChannels(src_audio) > 1 && IsMono(dst_audio)) { 76 // TODO(tommi): change DownmixInterleavedToMono to support InterleavedView 77 // and MonoView. 78 DownmixInterleavedToMono(&src_audio.data()[0], SamplesPerChannel(src_audio), 79 NumChannels(src_audio), &dst_audio.data()[0]); 80 } else if (NumChannels(src_audio) == 4 && NumChannels(dst_audio) == 2) { 81 QuadToStereo(src_audio, dst_audio); 82 } else { 83 RTC_DCHECK_NOTREACHED() << "src_channels: " << NumChannels(src_audio) 84 << ", dst_channels: " << NumChannels(dst_audio); 85 } 86 } 87 88 void AudioFrameOperations::DownmixChannels(size_t dst_channels, 89 AudioFrame* frame) { 90 RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_, 91 AudioFrame::kMaxDataSizeSamples); 92 if (frame->num_channels_ > 1 && dst_channels == 1) { 93 if (!frame->muted()) { 94 DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_, 95 frame->num_channels_, frame->mutable_data()); 96 } 97 frame->num_channels_ = 1; 98 } else if (frame->num_channels_ == 4 && dst_channels == 2) { 99 int err = QuadToStereo(frame); 100 RTC_DCHECK_EQ(err, 0); 101 } else { 102 RTC_DCHECK_NOTREACHED() << "src_channels: " << frame->num_channels_ 103 << ", dst_channels: " << dst_channels; 104 } 105 } 106 107 void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels, 108 AudioFrame* frame) { 109 RTC_DCHECK_EQ(frame->num_channels_, 1); 110 RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels, 111 AudioFrame::kMaxDataSizeSamples); 112 113 if (frame->num_channels_ != 1 || 114 frame->samples_per_channel_ * target_number_of_channels > 115 AudioFrame::kMaxDataSizeSamples) { 116 return; 117 } 118 119 if (!frame->muted()) { 120 // Up-mixing done in place. Going backwards through the frame ensure nothing 121 // is irrevocably overwritten. 122 auto frame_data = frame->mutable_data(frame->samples_per_channel_, 123 target_number_of_channels); 124 for (int i = frame->samples_per_channel_ - 1; i >= 0; --i) { 125 for (size_t j = 0; j < target_number_of_channels; ++j) { 126 frame_data[target_number_of_channels * i + j] = frame_data[i]; 127 } 128 } 129 } else { 130 frame->num_channels_ = target_number_of_channels; 131 } 132 } 133 134 void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) { 135 RTC_DCHECK(frame); 136 if (frame->num_channels_ != 2 || frame->muted()) { 137 return; 138 } 139 140 int16_t* frame_data = frame->mutable_data(); 141 for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) { 142 std::swap(frame_data[i], frame_data[i + 1]); 143 } 144 } 145 146 void AudioFrameOperations::Mute(AudioFrame* frame, 147 bool previous_frame_muted, 148 bool current_frame_muted) { 149 RTC_DCHECK(frame); 150 if (!previous_frame_muted && !current_frame_muted) { 151 // Not muted, don't touch. 152 } else if (previous_frame_muted && current_frame_muted) { 153 // Frame fully muted. 154 size_t total_samples = frame->samples_per_channel_ * frame->num_channels_; 155 RTC_DCHECK_GE(AudioFrame::kMaxDataSizeSamples, total_samples); 156 frame->Mute(); 157 } else { 158 // Fade is a no-op on a muted frame. 159 if (frame->muted()) { 160 return; 161 } 162 163 // Limit number of samples to fade, if frame isn't long enough. 164 size_t count = kMuteFadeFrames; 165 float inc = kMuteFadeInc; 166 if (frame->samples_per_channel_ < kMuteFadeFrames) { 167 count = frame->samples_per_channel_; 168 if (count > 0) { 169 inc = 1.0f / count; 170 } 171 } 172 173 size_t start = 0; 174 size_t end = count; 175 float start_g = 0.0f; 176 if (current_frame_muted) { 177 // Fade out the last `count` samples of frame. 178 RTC_DCHECK(!previous_frame_muted); 179 start = frame->samples_per_channel_ - count; 180 end = frame->samples_per_channel_; 181 start_g = 1.0f; 182 inc = -inc; 183 } else { 184 // Fade in the first `count` samples of frame. 185 RTC_DCHECK(previous_frame_muted); 186 } 187 188 // Perform fade. 189 int16_t* frame_data = frame->mutable_data(); 190 size_t channels = frame->num_channels_; 191 for (size_t j = 0; j < channels; ++j) { 192 float g = start_g; 193 for (size_t i = start * channels; i < end * channels; i += channels) { 194 g += inc; 195 frame_data[i + j] *= g; 196 } 197 } 198 } 199 } 200 201 void AudioFrameOperations::Mute(AudioFrame* frame) { 202 Mute(frame, true, true); 203 } 204 205 int AudioFrameOperations::ScaleWithSat(float scale, AudioFrame* frame) { 206 if (frame->muted()) { 207 return 0; 208 } 209 210 int16_t* frame_data = frame->mutable_data(); 211 for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_; 212 i++) { 213 frame_data[i] = saturated_cast<int16_t>(scale * frame_data[i]); 214 } 215 return 0; 216 } 217 } // namespace webrtc