text: /*
   *  Copyright (c) 2011 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.
   */
  
  
  /*
   * A wrapper for resampling a numerous amount of sampling combinations.
   */
  
  #include <stdlib.h>
  #include <string.h>
  
  #include "signal_processing_library.h"
  #include "resampler.h"
  
  
  namespace webrtc
  {
  
  Resampler::Resampler()
  {
      state1_ = NULL;
      state2_ = NULL;
      state3_ = NULL;
      in_buffer_ = NULL;
      out_buffer_ = NULL;
      in_buffer_size_ = 0;
      out_buffer_size_ = 0;
      in_buffer_size_max_ = 0;
      out_buffer_size_max_ = 0;
      // we need a reset before we will work
      my_in_frequency_khz_ = 0;
      my_out_frequency_khz_ = 0;
      my_mode_ = kResamplerMode1To1;
      my_type_ = kResamplerInvalid;
      slave_left_ = NULL;
      slave_right_ = NULL;
  }
  
  Resampler::Resampler(int inFreq, int outFreq, ResamplerType type)
  {
      state1_ = NULL;
      state2_ = NULL;
      state3_ = NULL;
      in_buffer_ = NULL;
      out_buffer_ = NULL;
      in_buffer_size_ = 0;
      out_buffer_size_ = 0;
      in_buffer_size_max_ = 0;
      out_buffer_size_max_ = 0;
      // we need a reset before we will work
      my_in_frequency_khz_ = 0;
      my_out_frequency_khz_ = 0;
      my_mode_ = kResamplerMode1To1;
      my_type_ = kResamplerInvalid;
      slave_left_ = NULL;
      slave_right_ = NULL;
  
      Reset(inFreq, outFreq, type);
  }
  
  Resampler::~Resampler()
  {
      if (state1_)
      {
          free(state1_);
      }
      if (state2_)
      {
          free(state2_);
      }
      if (state3_)
      {
          free(state3_);
      }
      if (in_buffer_)
      {
          free(in_buffer_);
      }
      if (out_buffer_)
      {
          free(out_buffer_);
      }
      if (slave_left_)
      {
          delete slave_left_;
      }
      if (slave_right_)
      {
          delete slave_right_;
      }
  }
  
  int Resampler::ResetIfNeeded(int inFreq, int outFreq, ResamplerType type)
  {
      int tmpInFreq_kHz = inFreq / 1000;
      int tmpOutFreq_kHz = outFreq / 1000;
  
      if ((tmpInFreq_kHz != my_in_frequency_khz_) || (tmpOutFreq_kHz != my_out_frequency_khz_)
              || (type != my_type_))
      {
          return Reset(inFreq, outFreq, type);
      } else
      {
          return 0;
      }
  }
  
  int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
  {
  
      if (state1_)
      {
          free(state1_);
          state1_ = NULL;
      }
      if (state2_)
      {
          free(state2_);
          state2_ = NULL;
      }
      if (state3_)
      {
          free(state3_);
          state3_ = NULL;
      }
      if (in_buffer_)
      {
          free(in_buffer_);
          in_buffer_ = NULL;
      }
      if (out_buffer_)
      {
          free(out_buffer_);
          out_buffer_ = NULL;
      }
      if (slave_left_)
      {
          delete slave_left_;
          slave_left_ = NULL;
      }
      if (slave_right_)
      {
          delete slave_right_;
          slave_right_ = NULL;
      }
  
      in_buffer_size_ = 0;
      out_buffer_size_ = 0;
      in_buffer_size_max_ = 0;
      out_buffer_size_max_ = 0;
  
      // This might be overridden if parameters are not accepted.
      my_type_ = type;
  
      // Start with a math exercise, Euclid's algorithm to find the gcd:
  
      int a = inFreq;
      int b = outFreq;
      int c = a % b;
      while (c != 0)
      {
          a = b;
          b = c;
          c = a % b;
      }
      // b is now the gcd;
  
      // We need to track what domain we're in.
      my_in_frequency_khz_ = inFreq / 1000;
      my_out_frequency_khz_ = outFreq / 1000;
  
      // Scale with GCD
      inFreq = inFreq / b;
      outFreq = outFreq / b;
  
      // Do we need stereo?
      if ((my_type_ & 0xf0) == 0x20)
      {
          // Change type to mono
          type = static_cast<ResamplerType>(
              ((static_cast<int>(type) & 0x0f) + 0x10));
          slave_left_ = new Resampler(inFreq, outFreq, type);
          slave_right_ = new Resampler(inFreq, outFreq, type);
      }
  
      if (inFreq == outFreq)
      {
          my_mode_ = kResamplerMode1To1;
      } else if (inFreq == 1)
      {
          switch (outFreq)
          {
              case 2:
                  my_mode_ = kResamplerMode1To2;
                  break;
              case 3:
                  my_mode_ = kResamplerMode1To3;
                  break;
              case 4:
                  my_mode_ = kResamplerMode1To4;
                  break;
              case 6:
                  my_mode_ = kResamplerMode1To6;
                  break;
              case 12:
                  my_mode_ = kResamplerMode1To12;
                  break;
              default:
                  my_type_ = kResamplerInvalid;
                  return -1;
          }
      } else if (outFreq == 1)
      {
          switch (inFreq)
          {
              case 2:
                  my_mode_ = kResamplerMode2To1;
                  break;
              case 3:
                  my_mode_ = kResamplerMode3To1;
                  break;
              case 4:
                  my_mode_ = kResamplerMode4To1;
                  break;
              case 6:
                  my_mode_ = kResamplerMode6To1;
                  break;
              case 12:
                  my_mode_ = kResamplerMode12To1;
                  break;
              default:
                  my_type_ = kResamplerInvalid;
                  return -1;
          }
      } else if ((inFreq == 2) && (outFreq == 3))
      {
          my_mode_ = kResamplerMode2To3;
      } else if ((inFreq == 2) && (outFreq == 11))
      {
          my_mode_ = kResamplerMode2To11;
      } else if ((inFreq == 4) && (outFreq == 11))
      {
          my_mode_ = kResamplerMode4To11;
      } else if ((inFreq == 8) && (outFreq == 11))
      {
          my_mode_ = kResamplerMode8To11;
      } else if ((inFreq == 3) && (outFreq == 2))
      {
          my_mode_ = kResamplerMode3To2;
      } else if ((inFreq == 11) && (outFreq == 2))
      {
          my_mode_ = kResamplerMode11To2;
      } else if ((inFreq == 11) && (outFreq == 4))
      {
          my_mode_ = kResamplerMode11To4;
      } else if ((inFreq == 11) && (outFreq == 16))
      {
          my_mode_ = kResamplerMode11To16;
      } else if ((inFreq == 11) && (outFreq == 32))
      {
          my_mode_ = kResamplerMode11To32;
      } else if ((inFreq == 11) && (outFreq == 8))
      {
          my_mode_ = kResamplerMode11To8;
      } else
      {
          my_type_ = kResamplerInvalid;
          return -1;
      }
  
      // Now create the states we need
      switch (my_mode_)
      {
          case kResamplerMode1To1:
              // No state needed;
              break;
          case kResamplerMode1To2:
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode1To3:
              state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
              WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_);
              break;
          case kResamplerMode1To4:
              // 1:2
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              // 2:4
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode1To6:
              // 1:2
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              // 2:6
              state2_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
              WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state2_);
              break;
          case kResamplerMode1To12:
              // 1:2
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              // 2:4
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
              // 4:12
              state3_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
              WebRtcSpl_ResetResample16khzTo48khz(
                  (WebRtcSpl_State16khzTo48khz*) state3_);
              break;
          case kResamplerMode2To3:
              // 2:6
              state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
              WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_);
              // 6:3
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode2To11:
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
  
              state2_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz));
              WebRtcSpl_ResetResample8khzTo22khz((WebRtcSpl_State8khzTo22khz *)state2_);
              break;
          case kResamplerMode4To11:
              state1_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz));
              WebRtcSpl_ResetResample8khzTo22khz((WebRtcSpl_State8khzTo22khz *)state1_);
              break;
          case kResamplerMode8To11:
              state1_ = malloc(sizeof(WebRtcSpl_State16khzTo22khz));
              WebRtcSpl_ResetResample16khzTo22khz((WebRtcSpl_State16khzTo22khz *)state1_);
              break;
          case kResamplerMode11To16:
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
  
              state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
              WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_);
              break;
          case kResamplerMode11To32:
              // 11 -> 22
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
  
              // 22 -> 16
              state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
              WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_);
  
              // 16 -> 32
              state3_ = malloc(8 * sizeof(int32_t));
              memset(state3_, 0, 8 * sizeof(int32_t));
  
              break;
          case kResamplerMode2To1:
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode3To1:
              state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
              WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_);
              break;
          case kResamplerMode4To1:
              // 4:2
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              // 2:1
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode6To1:
              // 6:2
              state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
              WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_);
              // 2:1
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode12To1:
              // 12:4
              state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
              WebRtcSpl_ResetResample48khzTo16khz(
                  (WebRtcSpl_State48khzTo16khz*) state1_);
              // 4:2
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
              // 2:1
              state3_ = malloc(8 * sizeof(int32_t));
              memset(state3_, 0, 8 * sizeof(int32_t));
              break;
          case kResamplerMode3To2:
              // 3:6
              state1_ = malloc(8 * sizeof(int32_t));
              memset(state1_, 0, 8 * sizeof(int32_t));
              // 6:2
              state2_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
              WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state2_);
              break;
          case kResamplerMode11To2:
              state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz));
              WebRtcSpl_ResetResample22khzTo8khz((WebRtcSpl_State22khzTo8khz *)state1_);
  
              state2_ = malloc(8 * sizeof(int32_t));
              memset(state2_, 0, 8 * sizeof(int32_t));
  
              break;
          case kResamplerMode11To4:
              state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz));
              WebRtcSpl_ResetResample22khzTo8khz((WebRtcSpl_State22khzTo8khz *)state1_);
              break;
          case kResamplerMode11To8:
              state1_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
              WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state1_);
              break;
  
      }
  
      return 0;
  }
  
  // Synchronous resampling, all output samples are written to samplesOut
  int Resampler::Push(const int16_t * samplesIn, int lengthIn, int16_t* samplesOut,
                      int maxLen, int &outLen)
  {
      // Check that the resampler is not in asynchronous mode
      if (my_type_ & 0x0f)
      {
          return -1;
      }
  
      // Do we have a stereo signal?
      if ((my_type_ & 0xf0) == 0x20)
      {
  
          // Split up the signal and call the slave object for each channel
  
          int16_t* left = (int16_t*)malloc(lengthIn * sizeof(int16_t) / 2);
          int16_t* right = (int16_t*)malloc(lengthIn * sizeof(int16_t) / 2);
          int16_t* out_left = (int16_t*)malloc(maxLen / 2 * sizeof(int16_t));
          int16_t* out_right =
                  (int16_t*)malloc(maxLen / 2 * sizeof(int16_t));
          int res = 0;
          for (int i = 0; i < lengthIn; i += 2)
          {
              left[i >> 1] = samplesIn[i];
              right[i >> 1] = samplesIn[i + 1];
          }
  
          // It's OK to overwrite the local parameter, since it's just a copy
          lengthIn = lengthIn / 2;
  
          int actualOutLen_left = 0;
          int actualOutLen_right = 0;
          // Do resampling for right channel
          res |= slave_left_->Push(left, lengthIn, out_left, maxLen / 2, actualOutLen_left);
          res |= slave_right_->Push(right, lengthIn, out_right, maxLen / 2, actualOutLen_right);
          if (res || (actualOutLen_left != actualOutLen_right))
          {
              free(left);
              free(right);
              free(out_left);
              free(out_right);
              return -1;
          }
  
          // Reassemble the signal
          for (int i = 0; i < actualOutLen_left; i++)
          {
              samplesOut[i * 2] = out_left[i];
              samplesOut[i * 2 + 1] = out_right[i];
          }
          outLen = 2 * actualOutLen_left;
  
          free(left);
          free(right);
          free(out_left);
          free(out_right);
  
          return 0;
      }
  
      // Containers for temp samples
      int16_t* tmp;
      int16_t* tmp_2;
      // tmp data for resampling routines
      int32_t* tmp_mem;
  
      switch (my_mode_)
      {
          case kResamplerMode1To1:
              memcpy(samplesOut, samplesIn, lengthIn * sizeof(int16_t));
              outLen = lengthIn;
              break;
          case kResamplerMode1To2:
              if (maxLen < (lengthIn * 2))
              {
                  return -1;
              }
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (int32_t*)state1_);
              outLen = lengthIn * 2;
              return 0;
          case kResamplerMode1To3:
  
              // We can only handle blocks of 160 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 160) != 0)
              {
                  return -1;
              }
              if (maxLen < (lengthIn * 3))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(336 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 160)
              {
                  WebRtcSpl_Resample16khzTo48khz(samplesIn + i, samplesOut + i * 3,
                                                 (WebRtcSpl_State16khzTo48khz *)state1_,
                                                 tmp_mem);
              }
              outLen = lengthIn * 3;
              free(tmp_mem);
              return 0;
          case kResamplerMode1To4:
              if (maxLen < (lengthIn * 4))
              {
                  return -1;
              }
  
              tmp = (int16_t*)malloc(sizeof(int16_t) * 2 * lengthIn);
              // 1:2
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (int32_t*)state1_);
              // 2:4
              WebRtcSpl_UpsampleBy2(tmp, lengthIn * 2, samplesOut, (int32_t*)state2_);
              outLen = lengthIn * 4;
              free(tmp);
              return 0;
          case kResamplerMode1To6:
              // We can only handle blocks of 80 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 80) != 0)
              {
                  return -1;
              }
              if (maxLen < (lengthIn * 6))
              {
                  return -1;
              }
  
              //1:2
  
              tmp_mem = (int32_t*)malloc(336 * sizeof(int32_t));
              tmp = (int16_t*)malloc(sizeof(int16_t) * 2 * lengthIn);
  
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (int32_t*)state1_);
              outLen = lengthIn * 2;
  
              for (int i = 0; i < outLen; i += 160)
              {
                  WebRtcSpl_Resample16khzTo48khz(tmp + i, samplesOut + i * 3,
                                                 (WebRtcSpl_State16khzTo48khz *)state2_,
                                                 tmp_mem);
              }
              outLen = outLen * 3;
              free(tmp_mem);
              free(tmp);
  
              return 0;
          case kResamplerMode1To12:
              // We can only handle blocks of 40 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 40) != 0) {
                return -1;
              }
              if (maxLen < (lengthIn * 12)) {
                return -1;
              }
  
              tmp_mem = (int32_t*) malloc(336 * sizeof(int32_t));
              tmp = (int16_t*) malloc(sizeof(int16_t) * 4 * lengthIn);
              //1:2
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut,
                                    (int32_t*) state1_);
              outLen = lengthIn * 2;
              //2:4
              WebRtcSpl_UpsampleBy2(samplesOut, outLen, tmp, (int32_t*) state2_);
              outLen = outLen * 2;
              // 4:12
              for (int i = 0; i < outLen; i += 160) {
                // WebRtcSpl_Resample16khzTo48khz() takes a block of 160 samples
                // as input and outputs a resampled block of 480 samples. The
                // data is now actually in 32 kHz sampling rate, despite the
                // function name, and with a resampling factor of three becomes
                // 96 kHz.
                WebRtcSpl_Resample16khzTo48khz(tmp + i, samplesOut + i * 3,
                                               (WebRtcSpl_State16khzTo48khz*) state3_,
                                               tmp_mem);
              }
              outLen = outLen * 3;
              free(tmp_mem);
              free(tmp);
  
              return 0;
          case kResamplerMode2To3:
              if (maxLen < (lengthIn * 3 / 2))
              {
                  return -1;
              }
              // 2:6
              // We can only handle blocks of 160 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 160) != 0)
              {
                  return -1;
              }
              tmp = static_cast<int16_t*> (malloc(sizeof(int16_t) * lengthIn * 3));
              tmp_mem = (int32_t*)malloc(336 * sizeof(int32_t));
              for (int i = 0; i < lengthIn; i += 160)
              {
                  WebRtcSpl_Resample16khzTo48khz(samplesIn + i, tmp + i * 3,
                                                 (WebRtcSpl_State16khzTo48khz *)state1_,
                                                 tmp_mem);
              }
              lengthIn = lengthIn * 3;
              // 6:3
              WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, (int32_t*)state2_);
              outLen = lengthIn / 2;
              free(tmp);
              free(tmp_mem);
              return 0;
          case kResamplerMode2To11:
  
              // We can only handle blocks of 80 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 80) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 11) / 2))
              {
                  return -1;
              }
              tmp = (int16_t*)malloc(sizeof(int16_t) * 2 * lengthIn);
              // 1:2
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (int32_t*)state1_);
              lengthIn *= 2;
  
              tmp_mem = (int32_t*)malloc(98 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 80)
              {
                  WebRtcSpl_Resample8khzTo22khz(tmp + i, samplesOut + (i * 11) / 4,
                                                (WebRtcSpl_State8khzTo22khz *)state2_,
                                                tmp_mem);
              }
              outLen = (lengthIn * 11) / 4;
              free(tmp_mem);
              free(tmp);
              return 0;
          case kResamplerMode4To11:
  
              // We can only handle blocks of 80 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 80) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 11) / 4))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(98 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 80)
              {
                  WebRtcSpl_Resample8khzTo22khz(samplesIn + i, samplesOut + (i * 11) / 4,
                                                (WebRtcSpl_State8khzTo22khz *)state1_,
                                                tmp_mem);
              }
              outLen = (lengthIn * 11) / 4;
              free(tmp_mem);
              return 0;
          case kResamplerMode8To11:
              // We can only handle blocks of 160 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 160) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 11) / 8))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(88 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 160)
              {
                  WebRtcSpl_Resample16khzTo22khz(samplesIn + i, samplesOut + (i * 11) / 8,
                                                 (WebRtcSpl_State16khzTo22khz *)state1_,
                                                 tmp_mem);
              }
              outLen = (lengthIn * 11) / 8;
              free(tmp_mem);
              return 0;
  
          case kResamplerMode11To16:
              // We can only handle blocks of 110 samples
              if ((lengthIn % 110) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 16) / 11))
              {
                  return -1;
              }
  
              tmp_mem = (int32_t*)malloc(104 * sizeof(int32_t));
              tmp = (int16_t*)malloc((sizeof(int16_t) * lengthIn * 2));
  
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (int32_t*)state1_);
  
              for (int i = 0; i < (lengthIn * 2); i += 220)
              {
                  WebRtcSpl_Resample22khzTo16khz(tmp + i, samplesOut + (i / 220) * 160,
                                                 (WebRtcSpl_State22khzTo16khz *)state2_,
                                                 tmp_mem);
              }
  
              outLen = (lengthIn * 16) / 11;
  
              free(tmp_mem);
              free(tmp);
              return 0;
  
          case kResamplerMode11To32:
  
              // We can only handle blocks of 110 samples
              if ((lengthIn % 110) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 32) / 11))
              {
                  return -1;
              }
  
              tmp_mem = (int32_t*)malloc(104 * sizeof(int32_t));
              tmp = (int16_t*)malloc((sizeof(int16_t) * lengthIn * 2));
  
              // 11 -> 22 kHz in samplesOut
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (int32_t*)state1_);
  
              // 22 -> 16 in tmp
              for (int i = 0; i < (lengthIn * 2); i += 220)
              {
                  WebRtcSpl_Resample22khzTo16khz(samplesOut + i, tmp + (i / 220) * 160,
                                                 (WebRtcSpl_State22khzTo16khz *)state2_,
                                                 tmp_mem);
              }
  
              // 16 -> 32 in samplesOut
              WebRtcSpl_UpsampleBy2(tmp, (lengthIn * 16) / 11, samplesOut,
                                    (int32_t*)state3_);
  
              outLen = (lengthIn * 32) / 11;
  
              free(tmp_mem);
              free(tmp);
              return 0;
  
          case kResamplerMode2To1:
              if (maxLen < (lengthIn / 2))
              {
                  return -1;
              }
              WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, samplesOut, (int32_t*)state1_);
              outLen = lengthIn / 2;
              return 0;
          case kResamplerMode3To1:
              // We can only handle blocks of 480 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 480) != 0)
              {
                  return -1;
              }
              if (maxLen < (lengthIn / 3))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(496 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 480)
              {
                  WebRtcSpl_Resample48khzTo16khz(samplesIn + i, samplesOut + i / 3,
                                                 (WebRtcSpl_State48khzTo16khz *)state1_,
                                                 tmp_mem);
              }
              outLen = lengthIn / 3;
              free(tmp_mem);
              return 0;
          case kResamplerMode4To1:
              if (maxLen < (lengthIn / 4))
              {
                  return -1;
              }
              tmp = (int16_t*)malloc(sizeof(int16_t) * lengthIn / 2);
              // 4:2
              WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, tmp, (int32_t*)state1_);
              // 2:1
              WebRtcSpl_DownsampleBy2(tmp, lengthIn / 2, samplesOut, (int32_t*)state2_);
              outLen = lengthIn / 4;
              free(tmp);
              return 0;
  
          case kResamplerMode6To1:
              // We can only handle blocks of 480 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 480) != 0)
              {
                  return -1;
              }
              if (maxLen < (lengthIn / 6))
              {
                  return -1;
              }
  
              tmp_mem = (int32_t*)malloc(496 * sizeof(int32_t));
              tmp = (int16_t*)malloc((sizeof(int16_t) * lengthIn) / 3);
  
              for (int i = 0; i < lengthIn; i += 480)
              {
                  WebRtcSpl_Resample48khzTo16khz(samplesIn + i, tmp + i / 3,
                                                 (WebRtcSpl_State48khzTo16khz *)state1_,
                                                 tmp_mem);
              }
              outLen = lengthIn / 3;
              free(tmp_mem);
              WebRtcSpl_DownsampleBy2(tmp, outLen, samplesOut, (int32_t*)state2_);
              free(tmp);
              outLen = outLen / 2;
              return 0;
          case kResamplerMode12To1:
              // We can only handle blocks of 480 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 480) != 0) {
                return -1;
              }
              if (maxLen < (lengthIn / 12)) {
                return -1;
              }
  
              tmp_mem = (int32_t*) malloc(496 * sizeof(int32_t));
              tmp = (int16_t*) malloc((sizeof(int16_t) * lengthIn) / 3);
              tmp_2 = (int16_t*) malloc((sizeof(int16_t) * lengthIn) / 6);
              // 12:4
              for (int i = 0; i < lengthIn; i += 480) {
                // WebRtcSpl_Resample48khzTo16khz() takes a block of 480 samples
                // as input and outputs a resampled block of 160 samples. The
                // data is now actually in 96 kHz sampling rate, despite the
                // function name, and with a resampling factor of 1/3 becomes
                // 32 kHz.
                WebRtcSpl_Resample48khzTo16khz(samplesIn + i, tmp + i / 3,
                                               (WebRtcSpl_State48khzTo16khz*) state1_,
                                               tmp_mem);
              }
              outLen = lengthIn / 3;
              free(tmp_mem);
              // 4:2
              WebRtcSpl_DownsampleBy2(tmp, outLen, tmp_2,
                                      (int32_t*) state2_);
              outLen = outLen / 2;
              free(tmp);
              // 2:1
              WebRtcSpl_DownsampleBy2(tmp_2, outLen, samplesOut,
                                      (int32_t*) state3_);
              free(tmp_2);
              outLen = outLen / 2;
              return 0;
          case kResamplerMode3To2:
              if (maxLen < (lengthIn * 2 / 3))
              {
                  return -1;
              }
              // 3:6
              tmp = static_cast<int16_t*> (malloc(sizeof(int16_t) * lengthIn * 2));
              WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (int32_t*)state1_);
              lengthIn *= 2;
              // 6:2
              // We can only handle blocks of 480 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 480) != 0)
              {
                  free(tmp);
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(496 * sizeof(int32_t));
              for (int i = 0; i < lengthIn; i += 480)
              {
                  WebRtcSpl_Resample48khzTo16khz(tmp + i, samplesOut + i / 3,
                                                 (WebRtcSpl_State48khzTo16khz *)state2_,
                                                 tmp_mem);
              }
              outLen = lengthIn / 3;
              free(tmp);
              free(tmp_mem);
              return 0;
          case kResamplerMode11To2:
              // We can only handle blocks of 220 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 220) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 2) / 11))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(126 * sizeof(int32_t));
              tmp = (int16_t*)malloc((lengthIn * 4) / 11 * sizeof(int16_t));
  
              for (int i = 0; i < lengthIn; i += 220)
              {
                  WebRtcSpl_Resample22khzTo8khz(samplesIn + i, tmp + (i * 4) / 11,
                                                (WebRtcSpl_State22khzTo8khz *)state1_,
                                                tmp_mem);
              }
              lengthIn = (lengthIn * 4) / 11;
  
              WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, (int32_t*)state2_);
              outLen = lengthIn / 2;
  
              free(tmp_mem);
              free(tmp);
              return 0;
          case kResamplerMode11To4:
              // We can only handle blocks of 220 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 220) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 4) / 11))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(126 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 220)
              {
                  WebRtcSpl_Resample22khzTo8khz(samplesIn + i, samplesOut + (i * 4) / 11,
                                                (WebRtcSpl_State22khzTo8khz *)state1_,
                                                tmp_mem);
              }
              outLen = (lengthIn * 4) / 11;
              free(tmp_mem);
              return 0;
          case kResamplerMode11To8:
              // We can only handle blocks of 160 samples
              // Can be fixed, but I don't think it's needed
              if ((lengthIn % 220) != 0)
              {
                  return -1;
              }
              if (maxLen < ((lengthIn * 8) / 11))
              {
                  return -1;
              }
              tmp_mem = (int32_t*)malloc(104 * sizeof(int32_t));
  
              for (int i = 0; i < lengthIn; i += 220)
              {
                  WebRtcSpl_Resample22khzTo16khz(samplesIn + i, samplesOut + (i * 8) / 11,
                                                 (WebRtcSpl_State22khzTo16khz *)state1_,
                                                 tmp_mem);
              }
              outLen = (lengthIn * 8) / 11;
              free(tmp_mem);
              return 0;
              break;
  
      }
      return 0;
  }
  
  // Asynchronous resampling, input
  int Resampler::Insert(int16_t * samplesIn, int lengthIn)
  {
      if (my_type_ != kResamplerAsynchronous)
      {
          return -1;
      }
      int sizeNeeded, tenMsblock;
  
      // Determine need for size of outBuffer
      sizeNeeded = out_buffer_size_ + ((lengthIn + in_buffer_size_) * my_out_frequency_khz_)
              / my_in_frequency_khz_;
      if (sizeNeeded > out_buffer_size_max_)
      {
          // Round the value upwards to complete 10 ms blocks
          tenMsblock = my_out_frequency_khz_ * 10;
          sizeNeeded = (sizeNeeded / tenMsblock + 1) * tenMsblock;
          out_buffer_ = (int16_t*)realloc(out_buffer_, sizeNeeded * sizeof(int16_t));
          out_buffer_size_max_ = sizeNeeded;
      }
  
      // If we need to use inBuffer, make sure all input data fits there.
  
      tenMsblock = my_in_frequency_khz_ * 10;
      if (in_buffer_size_ || (lengthIn % tenMsblock))
      {
          // Check if input buffer size is enough
          if ((in_buffer_size_ + lengthIn) > in_buffer_size_max_)
          {
              // Round the value upwards to complete 10 ms blocks
              sizeNeeded = ((in_buffer_size_ + lengthIn) / tenMsblock + 1) * tenMsblock;
              in_buffer_ = (int16_t*)realloc(in_buffer_,
                                             sizeNeeded * sizeof(int16_t));
              in_buffer_size_max_ = sizeNeeded;
          }
          // Copy in data to input buffer
          memcpy(in_buffer_ + in_buffer_size_, samplesIn, lengthIn * sizeof(int16_t));
  
          // Resample all available 10 ms blocks
          int lenOut;
          int dataLenToResample = (in_buffer_size_ / tenMsblock) * tenMsblock;
          Push(in_buffer_, dataLenToResample, out_buffer_ + out_buffer_size_,
               out_buffer_size_max_ - out_buffer_size_, lenOut);
          out_buffer_size_ += lenOut;
  
          // Save the rest
          memmove(in_buffer_, in_buffer_ + dataLenToResample,
                  (in_buffer_size_ - dataLenToResample) * sizeof(int16_t));
          in_buffer_size_ -= dataLenToResample;
      } else
      {
          // Just resample
          int lenOut;
          Push(in_buffer_, lengthIn, out_buffer_ + out_buffer_size_,
               out_buffer_size_max_ - out_buffer_size_, lenOut);
          out_buffer_size_ += lenOut;
      }
  
      return 0;
  }
  
  // Asynchronous resampling output, remaining samples are buffered
  int Resampler::Pull(int16_t* samplesOut, int desiredLen, int &outLen)
  {
      if (my_type_ != kResamplerAsynchronous)
      {
          return -1;
      }
  
      // Check that we have enough data
      if (desiredLen <= out_buffer_size_)
      {
          // Give out the date
          memcpy(samplesOut, out_buffer_, desiredLen * sizeof(int32_t));
  
          // Shuffle down remaining
          memmove(out_buffer_, out_buffer_ + desiredLen,
                  (out_buffer_size_ - desiredLen) * sizeof(int16_t));
  
          // Update remaining size
          out_buffer_size_ -= desiredLen;
  
          return 0;
      } else
      {
          return -1;
      }
  }
  
  } // namespace webrtc
  