LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/common_audio - audio_converter.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 101 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2014 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/common_audio/audio_converter.h"
      12             : 
      13             : #include <cstring>
      14             : #include <memory>
      15             : #include <utility>
      16             : #include <vector>
      17             : 
      18             : #include "webrtc/base/checks.h"
      19             : #include "webrtc/base/safe_conversions.h"
      20             : #include "webrtc/common_audio/channel_buffer.h"
      21             : #include "webrtc/common_audio/resampler/push_sinc_resampler.h"
      22             : 
      23             : using rtc::checked_cast;
      24             : 
      25             : namespace webrtc {
      26             : 
      27             : class CopyConverter : public AudioConverter {
      28             :  public:
      29           0 :   CopyConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
      30             :                 size_t dst_frames)
      31           0 :       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
      32           0 :   ~CopyConverter() override {};
      33             : 
      34           0 :   void Convert(const float* const* src, size_t src_size, float* const* dst,
      35             :                size_t dst_capacity) override {
      36           0 :     CheckSizes(src_size, dst_capacity);
      37           0 :     if (src != dst) {
      38           0 :       for (size_t i = 0; i < src_channels(); ++i)
      39           0 :         std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i]));
      40             :     }
      41           0 :   }
      42             : };
      43             : 
      44             : class UpmixConverter : public AudioConverter {
      45             :  public:
      46           0 :   UpmixConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
      47             :                  size_t dst_frames)
      48           0 :       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
      49           0 :   ~UpmixConverter() override {};
      50             : 
      51           0 :   void Convert(const float* const* src, size_t src_size, float* const* dst,
      52             :                size_t dst_capacity) override {
      53           0 :     CheckSizes(src_size, dst_capacity);
      54           0 :     for (size_t i = 0; i < dst_frames(); ++i) {
      55           0 :       const float value = src[0][i];
      56           0 :       for (size_t j = 0; j < dst_channels(); ++j)
      57           0 :         dst[j][i] = value;
      58             :     }
      59           0 :   }
      60             : };
      61             : 
      62             : class DownmixConverter : public AudioConverter {
      63             :  public:
      64           0 :   DownmixConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
      65             :                    size_t dst_frames)
      66           0 :       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
      67           0 :   }
      68           0 :   ~DownmixConverter() override {};
      69             : 
      70           0 :   void Convert(const float* const* src, size_t src_size, float* const* dst,
      71             :                size_t dst_capacity) override {
      72           0 :     CheckSizes(src_size, dst_capacity);
      73           0 :     float* dst_mono = dst[0];
      74           0 :     for (size_t i = 0; i < src_frames(); ++i) {
      75           0 :       float sum = 0;
      76           0 :       for (size_t j = 0; j < src_channels(); ++j)
      77           0 :         sum += src[j][i];
      78           0 :       dst_mono[i] = sum / src_channels();
      79             :     }
      80           0 :   }
      81             : };
      82             : 
      83             : class ResampleConverter : public AudioConverter {
      84             :  public:
      85           0 :   ResampleConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
      86             :                     size_t dst_frames)
      87           0 :       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
      88           0 :     resamplers_.reserve(src_channels);
      89           0 :     for (size_t i = 0; i < src_channels; ++i)
      90           0 :       resamplers_.push_back(std::unique_ptr<PushSincResampler>(
      91           0 :           new PushSincResampler(src_frames, dst_frames)));
      92           0 :   }
      93           0 :   ~ResampleConverter() override {};
      94             : 
      95           0 :   void Convert(const float* const* src, size_t src_size, float* const* dst,
      96             :                size_t dst_capacity) override {
      97           0 :     CheckSizes(src_size, dst_capacity);
      98           0 :     for (size_t i = 0; i < resamplers_.size(); ++i)
      99           0 :       resamplers_[i]->Resample(src[i], src_frames(), dst[i], dst_frames());
     100           0 :   }
     101             : 
     102             :  private:
     103             :   std::vector<std::unique_ptr<PushSincResampler>> resamplers_;
     104             : };
     105             : 
     106             : // Apply a vector of converters in serial, in the order given. At least two
     107             : // converters must be provided.
     108             : class CompositionConverter : public AudioConverter {
     109             :  public:
     110           0 :   CompositionConverter(std::vector<std::unique_ptr<AudioConverter>> converters)
     111           0 :       : converters_(std::move(converters)) {
     112           0 :     RTC_CHECK_GE(converters_.size(), 2);
     113             :     // We need an intermediate buffer after every converter.
     114           0 :     for (auto it = converters_.begin(); it != converters_.end() - 1; ++it)
     115           0 :       buffers_.push_back(
     116           0 :           std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
     117           0 :               (*it)->dst_frames(), (*it)->dst_channels())));
     118           0 :   }
     119           0 :   ~CompositionConverter() override {};
     120             : 
     121           0 :   void Convert(const float* const* src, size_t src_size, float* const* dst,
     122             :                size_t dst_capacity) override {
     123           0 :     converters_.front()->Convert(src, src_size, buffers_.front()->channels(),
     124           0 :                                  buffers_.front()->size());
     125           0 :     for (size_t i = 2; i < converters_.size(); ++i) {
     126           0 :       auto& src_buffer = buffers_[i - 2];
     127           0 :       auto& dst_buffer = buffers_[i - 1];
     128           0 :       converters_[i]->Convert(src_buffer->channels(),
     129             :                               src_buffer->size(),
     130             :                               dst_buffer->channels(),
     131           0 :                               dst_buffer->size());
     132             :     }
     133           0 :     converters_.back()->Convert(buffers_.back()->channels(),
     134           0 :                                 buffers_.back()->size(), dst, dst_capacity);
     135           0 :   }
     136             : 
     137             :  private:
     138             :   std::vector<std::unique_ptr<AudioConverter>> converters_;
     139             :   std::vector<std::unique_ptr<ChannelBuffer<float>>> buffers_;
     140             : };
     141             : 
     142           0 : std::unique_ptr<AudioConverter> AudioConverter::Create(size_t src_channels,
     143             :                                                        size_t src_frames,
     144             :                                                        size_t dst_channels,
     145             :                                                        size_t dst_frames) {
     146           0 :   std::unique_ptr<AudioConverter> sp;
     147           0 :   if (src_channels > dst_channels) {
     148           0 :     if (src_frames != dst_frames) {
     149           0 :       std::vector<std::unique_ptr<AudioConverter>> converters;
     150           0 :       converters.push_back(std::unique_ptr<AudioConverter>(new DownmixConverter(
     151           0 :           src_channels, src_frames, dst_channels, src_frames)));
     152             :       converters.push_back(
     153           0 :           std::unique_ptr<AudioConverter>(new ResampleConverter(
     154           0 :               dst_channels, src_frames, dst_channels, dst_frames)));
     155           0 :       sp.reset(new CompositionConverter(std::move(converters)));
     156             :     } else {
     157             :       sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels,
     158           0 :                                     dst_frames));
     159             :     }
     160           0 :   } else if (src_channels < dst_channels) {
     161           0 :     if (src_frames != dst_frames) {
     162           0 :       std::vector<std::unique_ptr<AudioConverter>> converters;
     163             :       converters.push_back(
     164           0 :           std::unique_ptr<AudioConverter>(new ResampleConverter(
     165           0 :               src_channels, src_frames, src_channels, dst_frames)));
     166           0 :       converters.push_back(std::unique_ptr<AudioConverter>(new UpmixConverter(
     167           0 :           src_channels, dst_frames, dst_channels, dst_frames)));
     168           0 :       sp.reset(new CompositionConverter(std::move(converters)));
     169             :     } else {
     170             :       sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels,
     171           0 :                                   dst_frames));
     172             :     }
     173           0 :   } else if (src_frames != dst_frames) {
     174             :     sp.reset(new ResampleConverter(src_channels, src_frames, dst_channels,
     175           0 :                                    dst_frames));
     176             :   } else {
     177             :     sp.reset(new CopyConverter(src_channels, src_frames, dst_channels,
     178           0 :                                dst_frames));
     179             :   }
     180             : 
     181           0 :   return sp;
     182             : }
     183             : 
     184             : // For CompositionConverter.
     185           0 : AudioConverter::AudioConverter()
     186             :     : src_channels_(0),
     187             :       src_frames_(0),
     188             :       dst_channels_(0),
     189           0 :       dst_frames_(0) {}
     190             : 
     191           0 : AudioConverter::AudioConverter(size_t src_channels, size_t src_frames,
     192           0 :                                size_t dst_channels, size_t dst_frames)
     193             :     : src_channels_(src_channels),
     194             :       src_frames_(src_frames),
     195             :       dst_channels_(dst_channels),
     196           0 :       dst_frames_(dst_frames) {
     197           0 :   RTC_CHECK(dst_channels == src_channels || dst_channels == 1 ||
     198           0 :             src_channels == 1);
     199           0 : }
     200             : 
     201           0 : void AudioConverter::CheckSizes(size_t src_size, size_t dst_capacity) const {
     202           0 :   RTC_CHECK_EQ(src_size, src_channels() * src_frames());
     203           0 :   RTC_CHECK_GE(dst_capacity, dst_channels() * dst_frames());
     204           0 : }
     205             : 
     206             : }  // namespace webrtc

Generated by: LCOV version 1.13