Home | History | Annotate | Download | only in include
      1 /*
      2  *  Copyright (c) 2013 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 #ifndef WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
     12 #define WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
     13 
     14 #include <limits>
     15 #include <cstring>
     16 
     17 #include "webrtc/base/checks.h"
     18 #include "webrtc/base/scoped_ptr.h"
     19 #include "webrtc/typedefs.h"
     20 
     21 namespace webrtc {
     22 
     23 typedef std::numeric_limits<int16_t> limits_int16;
     24 
     25 // The conversion functions use the following naming convention:
     26 // S16:      int16_t [-32768, 32767]
     27 // Float:    float   [-1.0, 1.0]
     28 // FloatS16: float   [-32768.0, 32767.0]
     29 static inline int16_t FloatToS16(float v) {
     30   if (v > 0)
     31     return v >= 1 ? limits_int16::max()
     32                   : static_cast<int16_t>(v * limits_int16::max() + 0.5f);
     33   return v <= -1 ? limits_int16::min()
     34                  : static_cast<int16_t>(-v * limits_int16::min() - 0.5f);
     35 }
     36 
     37 static inline float S16ToFloat(int16_t v) {
     38   static const float kMaxInt16Inverse = 1.f / limits_int16::max();
     39   static const float kMinInt16Inverse = 1.f / limits_int16::min();
     40   return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
     41 }
     42 
     43 static inline int16_t FloatS16ToS16(float v) {
     44   static const float kMaxRound = limits_int16::max() - 0.5f;
     45   static const float kMinRound = limits_int16::min() + 0.5f;
     46   if (v > 0)
     47     return v >= kMaxRound ? limits_int16::max()
     48                           : static_cast<int16_t>(v + 0.5f);
     49   return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f);
     50 }
     51 
     52 static inline float FloatToFloatS16(float v) {
     53   return v * (v > 0 ? limits_int16::max() : -limits_int16::min());
     54 }
     55 
     56 static inline float FloatS16ToFloat(float v) {
     57   static const float kMaxInt16Inverse = 1.f / limits_int16::max();
     58   static const float kMinInt16Inverse = 1.f / limits_int16::min();
     59   return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
     60 }
     61 
     62 void FloatToS16(const float* src, size_t size, int16_t* dest);
     63 void S16ToFloat(const int16_t* src, size_t size, float* dest);
     64 void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
     65 void FloatToFloatS16(const float* src, size_t size, float* dest);
     66 void FloatS16ToFloat(const float* src, size_t size, float* dest);
     67 
     68 // Copy audio from |src| channels to |dest| channels unless |src| and |dest|
     69 // point to the same address. |src| and |dest| must have the same number of
     70 // channels, and there must be sufficient space allocated in |dest|.
     71 template <typename T>
     72 void CopyAudioIfNeeded(const T* const* src,
     73                        int num_frames,
     74                        int num_channels,
     75                        T* const* dest) {
     76   for (int i = 0; i < num_channels; ++i) {
     77     if (src[i] != dest[i]) {
     78       std::copy(src[i], src[i] + num_frames, dest[i]);
     79     }
     80   }
     81 }
     82 
     83 // Deinterleave audio from |interleaved| to the channel buffers pointed to
     84 // by |deinterleaved|. There must be sufficient space allocated in the
     85 // |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
     86 // per buffer).
     87 template <typename T>
     88 void Deinterleave(const T* interleaved,
     89                   size_t samples_per_channel,
     90                   size_t num_channels,
     91                   T* const* deinterleaved) {
     92   for (size_t i = 0; i < num_channels; ++i) {
     93     T* channel = deinterleaved[i];
     94     size_t interleaved_idx = i;
     95     for (size_t j = 0; j < samples_per_channel; ++j) {
     96       channel[j] = interleaved[interleaved_idx];
     97       interleaved_idx += num_channels;
     98     }
     99   }
    100 }
    101 
    102 // Interleave audio from the channel buffers pointed to by |deinterleaved| to
    103 // |interleaved|. There must be sufficient space allocated in |interleaved|
    104 // (|samples_per_channel| * |num_channels|).
    105 template <typename T>
    106 void Interleave(const T* const* deinterleaved,
    107                 size_t samples_per_channel,
    108                 size_t num_channels,
    109                 T* interleaved) {
    110   for (size_t i = 0; i < num_channels; ++i) {
    111     const T* channel = deinterleaved[i];
    112     size_t interleaved_idx = i;
    113     for (size_t j = 0; j < samples_per_channel; ++j) {
    114       interleaved[interleaved_idx] = channel[j];
    115       interleaved_idx += num_channels;
    116     }
    117   }
    118 }
    119 
    120 // Copies audio from a single channel buffer pointed to by |mono| to each
    121 // channel of |interleaved|. There must be sufficient space allocated in
    122 // |interleaved| (|samples_per_channel| * |num_channels|).
    123 template <typename T>
    124 void UpmixMonoToInterleaved(const T* mono,
    125                             int num_frames,
    126                             int num_channels,
    127                             T* interleaved) {
    128   int interleaved_idx = 0;
    129   for (int i = 0; i < num_frames; ++i) {
    130     for (int j = 0; j < num_channels; ++j) {
    131       interleaved[interleaved_idx++] = mono[i];
    132     }
    133   }
    134 }
    135 
    136 template <typename T, typename Intermediate>
    137 void DownmixToMono(const T* const* input_channels,
    138                    size_t num_frames,
    139                    int num_channels,
    140                    T* out) {
    141   for (size_t i = 0; i < num_frames; ++i) {
    142     Intermediate value = input_channels[0][i];
    143     for (int j = 1; j < num_channels; ++j) {
    144       value += input_channels[j][i];
    145     }
    146     out[i] = value / num_channels;
    147   }
    148 }
    149 
    150 // Downmixes an interleaved multichannel signal to a single channel by averaging
    151 // all channels.
    152 template <typename T, typename Intermediate>
    153 void DownmixInterleavedToMonoImpl(const T* interleaved,
    154                                   size_t num_frames,
    155                                   int num_channels,
    156                                   T* deinterleaved) {
    157   RTC_DCHECK_GT(num_channels, 0);
    158   RTC_DCHECK_GT(num_frames, 0u);
    159 
    160   const T* const end = interleaved + num_frames * num_channels;
    161 
    162   while (interleaved < end) {
    163     const T* const frame_end = interleaved + num_channels;
    164 
    165     Intermediate value = *interleaved++;
    166     while (interleaved < frame_end) {
    167       value += *interleaved++;
    168     }
    169 
    170     *deinterleaved++ = value / num_channels;
    171   }
    172 }
    173 
    174 template <typename T>
    175 void DownmixInterleavedToMono(const T* interleaved,
    176                               size_t num_frames,
    177                               int num_channels,
    178                               T* deinterleaved);
    179 
    180 template <>
    181 void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
    182                                        size_t num_frames,
    183                                        int num_channels,
    184                                        int16_t* deinterleaved);
    185 
    186 }  // namespace webrtc
    187 
    188 #endif  // WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
    189