webrtc/common_audio/resampler/main/source/resampler.cc

982 lines
31 KiB
C++

/*
* 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