diff options
Diffstat (limited to 'src/common_audio/resampler/main/source/resampler.cc')
-rw-r--r-- | src/common_audio/resampler/main/source/resampler.cc | 981 |
1 files changed, 981 insertions, 0 deletions
diff --git a/src/common_audio/resampler/main/source/resampler.cc b/src/common_audio/resampler/main/source/resampler.cc new file mode 100644 index 0000000000..f866739752 --- /dev/null +++ b/src/common_audio/resampler/main/source/resampler.cc @@ -0,0 +1,981 @@ +/* + * 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; + + int res = 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 = (ResamplerType)((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; + default: + my_type_ = kResamplerInvalid; + break; + } + } 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; + default: + my_type_ = kResamplerInvalid; + break; + } + } 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(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + break; + case kResamplerMode1To3: + state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz)); + WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_); + break; + case kResamplerMode1To4: + // 1:2 + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + // 2:4 + state2_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state2_, 0, 8 * sizeof(WebRtc_Word32)); + break; + case kResamplerMode1To6: + // 1:2 + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + // 2:6 + state2_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz)); + WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state2_); + break; + case kResamplerMode2To3: + // 2:6 + state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz)); + WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_); + // 6:3 + state2_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state2_, 0, 8 * sizeof(WebRtc_Word32)); + break; + case kResamplerMode2To11: + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + + 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(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + + state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz)); + WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_); + break; + case kResamplerMode11To32: + // 11 -> 22 + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + + // 22 -> 16 + state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz)); + WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_); + + // 16 -> 32 + state3_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state3_, 0, 8 * sizeof(WebRtc_Word32)); + + break; + case kResamplerMode2To1: + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + break; + case kResamplerMode3To1: + state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz)); + WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_); + break; + case kResamplerMode4To1: + // 4:2 + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + // 2:1 + state2_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state2_, 0, 8 * sizeof(WebRtc_Word32)); + break; + case kResamplerMode6To1: + // 6:2 + state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz)); + WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_); + // 2:1 + state2_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state2_, 0, 8 * sizeof(WebRtc_Word32)); + break; + case kResamplerMode3To2: + // 3:6 + state1_ = malloc(8 * sizeof(WebRtc_Word32)); + memset(state1_, 0, 8 * sizeof(WebRtc_Word32)); + // 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(WebRtc_Word32)); + memset(state2_, 0, 8 * sizeof(WebRtc_Word32)); + + 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 WebRtc_Word16 * samplesIn, int lengthIn, WebRtc_Word16* 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 + + WebRtc_Word16* left = (WebRtc_Word16*)malloc(lengthIn * sizeof(WebRtc_Word16) / 2); + WebRtc_Word16* right = (WebRtc_Word16*)malloc(lengthIn * sizeof(WebRtc_Word16) / 2); + WebRtc_Word16* out_left = (WebRtc_Word16*)malloc(maxLen / 2 * sizeof(WebRtc_Word16)); + WebRtc_Word16* out_right = + (WebRtc_Word16*)malloc(maxLen / 2 * sizeof(WebRtc_Word16)); + 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; + } + + // Container for temp samples + WebRtc_Word16* tmp; + // tmp data for resampling routines + WebRtc_Word32* tmp_mem; + + switch (my_mode_) + { + case kResamplerMode1To1: + memcpy(samplesOut, samplesIn, lengthIn * sizeof(WebRtc_Word16)); + outLen = lengthIn; + break; + case kResamplerMode1To2: + if (maxLen < (lengthIn * 2)) + { + return -1; + } + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32)); + + 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 = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn); + // 1:2 + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_); + // 2:4 + WebRtcSpl_UpsampleBy2(tmp, lengthIn * 2, samplesOut, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32)); + tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn); + + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)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 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<WebRtc_Word16*> (malloc(sizeof(WebRtc_Word16) * lengthIn * 3)); + tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32)); + 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, (WebRtc_Word32*)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 = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn); + // 1:2 + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_); + lengthIn *= 2; + + tmp_mem = (WebRtc_Word32*)malloc(98 * sizeof(WebRtc_Word32)); + + 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 = (WebRtc_Word32*)malloc(98 * sizeof(WebRtc_Word32)); + + 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 = (WebRtc_Word32*)malloc(88 * sizeof(WebRtc_Word32)); + + 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 = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32)); + tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn * 2)); + + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32)); + tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn * 2)); + + // 11 -> 22 kHz in samplesOut + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)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, + (WebRtc_Word32*)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, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32)); + + 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 = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * lengthIn / 2); + // 4:2 + WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_); + // 2:1 + WebRtcSpl_DownsampleBy2(tmp, lengthIn / 2, samplesOut, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32)); + tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * 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, (WebRtc_Word32*)state2_); + free(tmp); + outLen = outLen / 2; + return 0; + case kResamplerMode3To2: + if (maxLen < (lengthIn * 2 / 3)) + { + return -1; + } + // 3:6 + tmp = static_cast<WebRtc_Word16*> (malloc(sizeof(WebRtc_Word16) * lengthIn * 2)); + WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32)); + 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 = (WebRtc_Word32*)malloc(126 * sizeof(WebRtc_Word32)); + tmp = (WebRtc_Word16*)malloc((lengthIn * 4) / 11 * sizeof(WebRtc_Word16)); + + 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, (WebRtc_Word32*)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 = (WebRtc_Word32*)malloc(126 * sizeof(WebRtc_Word32)); + + 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 = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32)); + + 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(WebRtc_Word16 * 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_ = (WebRtc_Word16*)realloc(out_buffer_, sizeNeeded * sizeof(WebRtc_Word16)); + 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_ = (WebRtc_Word16*)realloc(in_buffer_, + sizeNeeded * sizeof(WebRtc_Word16)); + in_buffer_size_max_ = sizeNeeded; + } + // Copy in data to input buffer + memcpy(in_buffer_ + in_buffer_size_, samplesIn, lengthIn * sizeof(WebRtc_Word16)); + + // 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(WebRtc_Word16)); + 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(WebRtc_Word16* 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(WebRtc_Word32)); + + // Shuffle down remaining + memmove(out_buffer_, out_buffer_ + desiredLen, + (out_buffer_size_ - desiredLen) * sizeof(WebRtc_Word16)); + + // Update remaining size + out_buffer_size_ -= desiredLen; + + return 0; + } else + { + return -1; + } +} + +} // namespace webrtc |