| /* | |
| * 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 "common_audio/resampler/include/resampler.h" | |
| #include <cstdint> | |
| #include <cstdlib> | |
| #include <cstring> | |
| #include "common_audio/signal_processing/include/signal_processing_library.h" | |
| #include "rtc_base/logging.h" | |
| namespace webrtc { | |
| Resampler::Resampler() | |
| : state1_(nullptr), | |
| state2_(nullptr), | |
| state3_(nullptr), | |
| in_buffer_(nullptr), | |
| out_buffer_(nullptr), | |
| in_buffer_size_(0), | |
| out_buffer_size_(0), | |
| in_buffer_size_max_(0), | |
| out_buffer_size_max_(0), | |
| my_in_frequency_khz_(0), | |
| my_out_frequency_khz_(0), | |
| my_mode_(kResamplerMode1To1), | |
| num_channels_(0), | |
| helper_left_(nullptr), | |
| helper_right_(nullptr) {} | |
| Resampler::Resampler(int inFreq, int outFreq, size_t num_channels) | |
| : Resampler() { | |
| Reset(inFreq, outFreq, num_channels); | |
| } | |
| 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 (helper_left_) { | |
| delete helper_left_; | |
| } | |
| if (helper_right_) { | |
| delete helper_right_; | |
| } | |
| } | |
| int Resampler::ResetIfNeeded(int inFreq, int outFreq, size_t num_channels) { | |
| int tmpInFreq_kHz = inFreq / 1000; | |
| int tmpOutFreq_kHz = outFreq / 1000; | |
| if ((tmpInFreq_kHz != my_in_frequency_khz_) || | |
| (tmpOutFreq_kHz != my_out_frequency_khz_) || | |
| (num_channels != num_channels_)) { | |
| return Reset(inFreq, outFreq, num_channels); | |
| } else { | |
| return 0; | |
| } | |
| } | |
| int Resampler::Reset(int inFreq, int outFreq, size_t num_channels) { | |
| if (num_channels != 1 && num_channels != 2) { | |
| RTC_LOG(LS_WARNING) | |
| << "Reset() called with unsupported channel count, num_channels = " | |
| << num_channels; | |
| return -1; | |
| } | |
| ResamplerMode mode; | |
| if (ComputeResamplerMode(inFreq, outFreq, &mode) != 0) { | |
| RTC_LOG(LS_WARNING) | |
| << "Reset() called with unsupported sample rates, inFreq = " << inFreq | |
| << ", outFreq = " << outFreq; | |
| return -1; | |
| } | |
| // Reinitialize internal state for the frequencies and sample rates. | |
| num_channels_ = num_channels; | |
| my_mode_ = mode; | |
| if (state1_) { | |
| free(state1_); | |
| state1_ = nullptr; | |
| } | |
| if (state2_) { | |
| free(state2_); | |
| state2_ = nullptr; | |
| } | |
| if (state3_) { | |
| free(state3_); | |
| state3_ = nullptr; | |
| } | |
| if (in_buffer_) { | |
| free(in_buffer_); | |
| in_buffer_ = nullptr; | |
| } | |
| if (out_buffer_) { | |
| free(out_buffer_); | |
| out_buffer_ = nullptr; | |
| } | |
| if (helper_left_) { | |
| delete helper_left_; | |
| helper_left_ = nullptr; | |
| } | |
| if (helper_right_) { | |
| delete helper_right_; | |
| helper_right_ = nullptr; | |
| } | |
| in_buffer_size_ = 0; | |
| out_buffer_size_ = 0; | |
| in_buffer_size_max_ = 0; | |
| out_buffer_size_max_ = 0; | |
| // We need to track what domain we're in. | |
| my_in_frequency_khz_ = inFreq / 1000; | |
| my_out_frequency_khz_ = outFreq / 1000; | |
| if (num_channels_ == 2) { | |
| // Create two mono resamplers. | |
| helper_left_ = new Resampler(inFreq, outFreq, 1); | |
| helper_right_ = new Resampler(inFreq, outFreq, 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( | |
| static_cast<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( | |
| static_cast<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( | |
| static_cast<WebRtcSpl_State16khzTo48khz*>(state3_)); | |
| break; | |
| case kResamplerMode2To3: | |
| // 2:6 | |
| state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz)); | |
| WebRtcSpl_ResetResample16khzTo48khz( | |
| static_cast<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( | |
| static_cast<WebRtcSpl_State8khzTo22khz*>(state2_)); | |
| break; | |
| case kResamplerMode4To11: | |
| state1_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz)); | |
| WebRtcSpl_ResetResample8khzTo22khz( | |
| static_cast<WebRtcSpl_State8khzTo22khz*>(state1_)); | |
| break; | |
| case kResamplerMode8To11: | |
| state1_ = malloc(sizeof(WebRtcSpl_State16khzTo22khz)); | |
| WebRtcSpl_ResetResample16khzTo22khz( | |
| static_cast<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( | |
| static_cast<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( | |
| static_cast<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( | |
| static_cast<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( | |
| static_cast<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( | |
| static_cast<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( | |
| static_cast<WebRtcSpl_State48khzTo16khz*>(state2_)); | |
| break; | |
| case kResamplerMode11To2: | |
| state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz)); | |
| WebRtcSpl_ResetResample22khzTo8khz( | |
| static_cast<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( | |
| static_cast<WebRtcSpl_State22khzTo8khz*>(state1_)); | |
| break; | |
| case kResamplerMode11To8: | |
| state1_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz)); | |
| WebRtcSpl_ResetResample22khzTo16khz( | |
| static_cast<WebRtcSpl_State22khzTo16khz*>(state1_)); | |
| break; | |
| } | |
| return 0; | |
| } | |
| int Resampler::ComputeResamplerMode(int in_freq_hz, | |
| int out_freq_hz, | |
| ResamplerMode* mode) { | |
| // Start with a math exercise, Euclid's algorithm to find the gcd: | |
| int a = in_freq_hz; | |
| int b = out_freq_hz; | |
| int c = a % b; | |
| while (c != 0) { | |
| a = b; | |
| b = c; | |
| c = a % b; | |
| } | |
| // b is now the gcd; | |
| // Scale with GCD | |
| const int reduced_in_freq = in_freq_hz / b; | |
| const int reduced_out_freq = out_freq_hz / b; | |
| if (reduced_in_freq == reduced_out_freq) { | |
| *mode = kResamplerMode1To1; | |
| } else if (reduced_in_freq == 1) { | |
| switch (reduced_out_freq) { | |
| case 2: | |
| *mode = kResamplerMode1To2; | |
| break; | |
| case 3: | |
| *mode = kResamplerMode1To3; | |
| break; | |
| case 4: | |
| *mode = kResamplerMode1To4; | |
| break; | |
| case 6: | |
| *mode = kResamplerMode1To6; | |
| break; | |
| case 12: | |
| *mode = kResamplerMode1To12; | |
| break; | |
| default: | |
| return -1; | |
| } | |
| } else if (reduced_out_freq == 1) { | |
| switch (reduced_in_freq) { | |
| case 2: | |
| *mode = kResamplerMode2To1; | |
| break; | |
| case 3: | |
| *mode = kResamplerMode3To1; | |
| break; | |
| case 4: | |
| *mode = kResamplerMode4To1; | |
| break; | |
| case 6: | |
| *mode = kResamplerMode6To1; | |
| break; | |
| case 12: | |
| *mode = kResamplerMode12To1; | |
| break; | |
| default: | |
| return -1; | |
| } | |
| } else if ((reduced_in_freq == 2) && (reduced_out_freq == 3)) { | |
| *mode = kResamplerMode2To3; | |
| } else if ((reduced_in_freq == 2) && (reduced_out_freq == 11)) { | |
| *mode = kResamplerMode2To11; | |
| } else if ((reduced_in_freq == 4) && (reduced_out_freq == 11)) { | |
| *mode = kResamplerMode4To11; | |
| } else if ((reduced_in_freq == 8) && (reduced_out_freq == 11)) { | |
| *mode = kResamplerMode8To11; | |
| } else if ((reduced_in_freq == 3) && (reduced_out_freq == 2)) { | |
| *mode = kResamplerMode3To2; | |
| } else if ((reduced_in_freq == 11) && (reduced_out_freq == 2)) { | |
| *mode = kResamplerMode11To2; | |
| } else if ((reduced_in_freq == 11) && (reduced_out_freq == 4)) { | |
| *mode = kResamplerMode11To4; | |
| } else if ((reduced_in_freq == 11) && (reduced_out_freq == 16)) { | |
| *mode = kResamplerMode11To16; | |
| } else if ((reduced_in_freq == 11) && (reduced_out_freq == 32)) { | |
| *mode = kResamplerMode11To32; | |
| } else if ((reduced_in_freq == 11) && (reduced_out_freq == 8)) { | |
| *mode = kResamplerMode11To8; | |
| } else { | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| // Synchronous resampling, all output samples are written to samplesOut | |
| int Resampler::Push(const int16_t* samplesIn, | |
| size_t lengthIn, | |
| int16_t* samplesOut, | |
| size_t maxLen, | |
| size_t& outLen) { | |
| if (num_channels_ == 2) { | |
| // Split up the signal and call the helper object for each channel | |
| int16_t* left = | |
| static_cast<int16_t*>(malloc(lengthIn * sizeof(int16_t) / 2)); | |
| int16_t* right = | |
| static_cast<int16_t*>(malloc(lengthIn * sizeof(int16_t) / 2)); | |
| int16_t* out_left = | |
| static_cast<int16_t*>(malloc(maxLen / 2 * sizeof(int16_t))); | |
| int16_t* out_right = | |
| static_cast<int16_t*>(malloc(maxLen / 2 * sizeof(int16_t))); | |
| int res = 0; | |
| for (size_t 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; | |
| size_t actualOutLen_left = 0; | |
| size_t actualOutLen_right = 0; | |
| // Do resampling for right channel | |
| res |= helper_left_->Push(left, lengthIn, out_left, maxLen / 2, | |
| actualOutLen_left); | |
| res |= helper_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 (size_t 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, | |
| static_cast<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 = static_cast<int32_t*>(malloc(336 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 160) { | |
| WebRtcSpl_Resample16khzTo48khz( | |
| samplesIn + i, samplesOut + i * 3, | |
| static_cast<WebRtcSpl_State16khzTo48khz*>(state1_), tmp_mem); | |
| } | |
| outLen = lengthIn * 3; | |
| free(tmp_mem); | |
| return 0; | |
| case kResamplerMode1To4: | |
| if (maxLen < (lengthIn * 4)) { | |
| return -1; | |
| } | |
| tmp = static_cast<int16_t*>(malloc(sizeof(int16_t) * 2 * lengthIn)); | |
| // 1:2 | |
| WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, | |
| static_cast<int32_t*>(state1_)); | |
| // 2:4 | |
| WebRtcSpl_UpsampleBy2(tmp, lengthIn * 2, samplesOut, | |
| static_cast<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 = static_cast<int32_t*>(malloc(336 * sizeof(int32_t))); | |
| tmp = static_cast<int16_t*>(malloc(sizeof(int16_t) * 2 * lengthIn)); | |
| WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, | |
| static_cast<int32_t*>(state1_)); | |
| outLen = lengthIn * 2; | |
| for (size_t i = 0; i < outLen; i += 160) { | |
| WebRtcSpl_Resample16khzTo48khz( | |
| tmp + i, samplesOut + i * 3, | |
| static_cast<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 = static_cast<int32_t*>(malloc(336 * sizeof(int32_t))); | |
| tmp = static_cast<int16_t*>(malloc(sizeof(int16_t) * 4 * lengthIn)); | |
| // 1:2 | |
| WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, | |
| static_cast<int32_t*>(state1_)); | |
| outLen = lengthIn * 2; | |
| // 2:4 | |
| WebRtcSpl_UpsampleBy2(samplesOut, outLen, tmp, | |
| static_cast<int32_t*>(state2_)); | |
| outLen = outLen * 2; | |
| // 4:12 | |
| for (size_t 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, | |
| static_cast<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 = static_cast<int32_t*>(malloc(336 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 160) { | |
| WebRtcSpl_Resample16khzTo48khz( | |
| samplesIn + i, tmp + i * 3, | |
| static_cast<WebRtcSpl_State16khzTo48khz*>(state1_), tmp_mem); | |
| } | |
| lengthIn = lengthIn * 3; | |
| // 6:3 | |
| WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, | |
| static_cast<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 = static_cast<int16_t*>(malloc(sizeof(int16_t) * 2 * lengthIn)); | |
| // 1:2 | |
| WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, | |
| static_cast<int32_t*>(state1_)); | |
| lengthIn *= 2; | |
| tmp_mem = static_cast<int32_t*>(malloc(98 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 80) { | |
| WebRtcSpl_Resample8khzTo22khz( | |
| tmp + i, samplesOut + (i * 11) / 4, | |
| static_cast<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 = static_cast<int32_t*>(malloc(98 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 80) { | |
| WebRtcSpl_Resample8khzTo22khz( | |
| samplesIn + i, samplesOut + (i * 11) / 4, | |
| static_cast<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 = static_cast<int32_t*>(malloc(88 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 160) { | |
| WebRtcSpl_Resample16khzTo22khz( | |
| samplesIn + i, samplesOut + (i * 11) / 8, | |
| static_cast<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 = static_cast<int32_t*>(malloc(104 * sizeof(int32_t))); | |
| tmp = static_cast<int16_t*>(malloc((sizeof(int16_t) * lengthIn * 2))); | |
| WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, | |
| static_cast<int32_t*>(state1_)); | |
| for (size_t i = 0; i < (lengthIn * 2); i += 220) { | |
| WebRtcSpl_Resample22khzTo16khz( | |
| tmp + i, samplesOut + (i / 220) * 160, | |
| static_cast<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 = static_cast<int32_t*>(malloc(104 * sizeof(int32_t))); | |
| tmp = static_cast<int16_t*>(malloc((sizeof(int16_t) * lengthIn * 2))); | |
| // 11 -> 22 kHz in samplesOut | |
| WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, | |
| static_cast<int32_t*>(state1_)); | |
| // 22 -> 16 in tmp | |
| for (size_t i = 0; i < (lengthIn * 2); i += 220) { | |
| WebRtcSpl_Resample22khzTo16khz( | |
| samplesOut + i, tmp + (i / 220) * 160, | |
| static_cast<WebRtcSpl_State22khzTo16khz*>(state2_), tmp_mem); | |
| } | |
| // 16 -> 32 in samplesOut | |
| WebRtcSpl_UpsampleBy2(tmp, (lengthIn * 16) / 11, samplesOut, | |
| static_cast<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, | |
| static_cast<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 = static_cast<int32_t*>(malloc(496 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 480) { | |
| WebRtcSpl_Resample48khzTo16khz( | |
| samplesIn + i, samplesOut + i / 3, | |
| static_cast<WebRtcSpl_State48khzTo16khz*>(state1_), tmp_mem); | |
| } | |
| outLen = lengthIn / 3; | |
| free(tmp_mem); | |
| return 0; | |
| case kResamplerMode4To1: | |
| if (maxLen < (lengthIn / 4)) { | |
| return -1; | |
| } | |
| tmp = static_cast<int16_t*>(malloc(sizeof(int16_t) * lengthIn / 2)); | |
| // 4:2 | |
| WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, tmp, | |
| static_cast<int32_t*>(state1_)); | |
| // 2:1 | |
| WebRtcSpl_DownsampleBy2(tmp, lengthIn / 2, samplesOut, | |
| static_cast<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 = static_cast<int32_t*>(malloc(496 * sizeof(int32_t))); | |
| tmp = static_cast<int16_t*>(malloc((sizeof(int16_t) * lengthIn) / 3)); | |
| for (size_t i = 0; i < lengthIn; i += 480) { | |
| WebRtcSpl_Resample48khzTo16khz( | |
| samplesIn + i, tmp + i / 3, | |
| static_cast<WebRtcSpl_State48khzTo16khz*>(state1_), tmp_mem); | |
| } | |
| outLen = lengthIn / 3; | |
| free(tmp_mem); | |
| WebRtcSpl_DownsampleBy2(tmp, outLen, samplesOut, | |
| static_cast<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 = static_cast<int32_t*>(malloc(496 * sizeof(int32_t))); | |
| tmp = static_cast<int16_t*>(malloc((sizeof(int16_t) * lengthIn) / 3)); | |
| tmp_2 = static_cast<int16_t*>(malloc((sizeof(int16_t) * lengthIn) / 6)); | |
| // 12:4 | |
| for (size_t 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, | |
| static_cast<WebRtcSpl_State48khzTo16khz*>(state1_), tmp_mem); | |
| } | |
| outLen = lengthIn / 3; | |
| free(tmp_mem); | |
| // 4:2 | |
| WebRtcSpl_DownsampleBy2(tmp, outLen, tmp_2, | |
| static_cast<int32_t*>(state2_)); | |
| outLen = outLen / 2; | |
| free(tmp); | |
| // 2:1 | |
| WebRtcSpl_DownsampleBy2(tmp_2, outLen, samplesOut, | |
| static_cast<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, | |
| static_cast<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 = static_cast<int32_t*>(malloc(496 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 480) { | |
| WebRtcSpl_Resample48khzTo16khz( | |
| tmp + i, samplesOut + i / 3, | |
| static_cast<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 = static_cast<int32_t*>(malloc(126 * sizeof(int32_t))); | |
| tmp = | |
| static_cast<int16_t*>(malloc((lengthIn * 4) / 11 * sizeof(int16_t))); | |
| for (size_t i = 0; i < lengthIn; i += 220) { | |
| WebRtcSpl_Resample22khzTo8khz( | |
| samplesIn + i, tmp + (i * 4) / 11, | |
| static_cast<WebRtcSpl_State22khzTo8khz*>(state1_), tmp_mem); | |
| } | |
| lengthIn = (lengthIn * 4) / 11; | |
| WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, | |
| static_cast<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 = static_cast<int32_t*>(malloc(126 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 220) { | |
| WebRtcSpl_Resample22khzTo8khz( | |
| samplesIn + i, samplesOut + (i * 4) / 11, | |
| static_cast<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 = static_cast<int32_t*>(malloc(104 * sizeof(int32_t))); | |
| for (size_t i = 0; i < lengthIn; i += 220) { | |
| WebRtcSpl_Resample22khzTo16khz( | |
| samplesIn + i, samplesOut + (i * 8) / 11, | |
| static_cast<WebRtcSpl_State22khzTo16khz*>(state1_), tmp_mem); | |
| } | |
| outLen = (lengthIn * 8) / 11; | |
| free(tmp_mem); | |
| return 0; | |
| } | |
| return 0; | |
| } | |
| } // namespace webrtc |