|  | /* | 
|  | *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #ifndef AUDIO_UTILITY_CHANNEL_MIXER_H_ | 
|  | #define AUDIO_UTILITY_CHANNEL_MIXER_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <memory> | 
|  | #include <vector> | 
|  |  | 
|  | #include "api/audio/audio_frame.h" | 
|  | #include "api/audio/channel_layout.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | // ChannelMixer is for converting audio between channel layouts.  The conversion | 
|  | // matrix is built upon construction and used during each Transform() call.  The | 
|  | // algorithm works by generating a conversion matrix mapping each output channel | 
|  | // to list of input channels.  The transform renders all of the output channels, | 
|  | // with each output channel rendered according to a weighted sum of the relevant | 
|  | // input channels as defined in the matrix. | 
|  | // This file is derived from Chromium's media/base/channel_mixer.h. | 
|  | class ChannelMixer { | 
|  | public: | 
|  | // To mix two channels into one and preserve loudness, we must apply | 
|  | // (1 / sqrt(2)) gain to each. | 
|  | static constexpr float kHalfPower = 0.707106781186547524401f; | 
|  |  | 
|  | ChannelMixer(ChannelLayout input_layout, ChannelLayout output_layout); | 
|  | ~ChannelMixer(); | 
|  |  | 
|  | // Transforms all input channels corresponding to the selected |input_layout| | 
|  | // to the number of channels in the selected |output_layout|. | 
|  | // Example usage (downmix from stereo to mono): | 
|  | // | 
|  | //   ChannelMixer mixer(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO); | 
|  | //   AudioFrame frame; | 
|  | //   frame.samples_per_channel_ = 160; | 
|  | //   frame.num_channels_ = 2; | 
|  | //   EXPECT_EQ(2u, frame.channels()); | 
|  | //   mixer.Transform(&frame); | 
|  | //   EXPECT_EQ(1u, frame.channels()); | 
|  | // | 
|  | void Transform(AudioFrame* frame); | 
|  |  | 
|  | private: | 
|  | bool IsUpMixing() const { return output_channels_ > input_channels_; } | 
|  |  | 
|  | // Selected channel layouts. | 
|  | const ChannelLayout input_layout_; | 
|  | const ChannelLayout output_layout_; | 
|  |  | 
|  | // Channel counts for input and output. | 
|  | const size_t input_channels_; | 
|  | const size_t output_channels_; | 
|  |  | 
|  | // 2D matrix of output channels to input channels. | 
|  | std::vector<std::vector<float> > matrix_; | 
|  |  | 
|  | // 1D array used as temporary storage during the transformation. | 
|  | std::unique_ptr<int16_t[]> audio_vector_; | 
|  |  | 
|  | // Number of elements allocated for |audio_vector_|. | 
|  | size_t audio_vector_size_ = 0; | 
|  |  | 
|  | // Optimization case for when we can simply remap the input channels to output | 
|  | // channels, i.e., when all scaling factors in |matrix_| equals 1.0. | 
|  | bool remapping_; | 
|  |  | 
|  | // Delete the copy constructor and assignment operator. | 
|  | ChannelMixer(const ChannelMixer& other) = delete; | 
|  | ChannelMixer& operator=(const ChannelMixer& other) = delete; | 
|  | }; | 
|  |  | 
|  | }  // namespace webrtc | 
|  |  | 
|  | #endif  // AUDIO_UTILITY_CHANNEL_MIXER_H_ |