- update (C)

This commit is contained in:
Dmytro Bogovych 2018-11-02 16:39:38 +02:00
parent 1dd0e16869
commit 6099b4fc04
2 changed files with 155 additions and 154 deletions

View File

@ -1,4 +1,4 @@
/* Copyright(C) 2007-2014 VoIP objects (voipobjects.com) /* Copyright(C) 2007-2018 VoIP objects (voipobjects.com)
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -16,94 +16,95 @@ using namespace Audio;
#define IS_FRACTIONAL_RATE(X) (((X) % 8000) != 0) #define IS_FRACTIONAL_RATE(X) (((X) % 8000) != 0)
SpeexResampler::SpeexResampler() SpeexResampler::SpeexResampler()
:mContext(NULL), mErrorCode(0), mSourceRate(0), mDestRate(0), mLastSample(0) :mContext(NULL), mErrorCode(0), mSourceRate(0), mDestRate(0), mLastSample(0)
{ {
} }
void SpeexResampler::start(int channels, int sourceRate, int destRate) void SpeexResampler::start(int channels, int sourceRate, int destRate)
{ {
if (mSourceRate == sourceRate && mDestRate == destRate && mContext) if (mSourceRate == sourceRate && mDestRate == destRate && mContext)
return; return;
if (mContext) if (mContext)
stop(); stop();
mSourceRate = sourceRate; mSourceRate = sourceRate;
mDestRate = destRate; mDestRate = destRate;
mChannels = channels; mChannels = channels;
if (sourceRate != destRate) if (sourceRate != destRate)
{ {
// Defer context creation until first request // Defer context creation until first request
//mContext = speex_resampler_init(channels, sourceRate, destRate, AUDIO_RESAMPLER_QUALITY, &mErrorCode); //mContext = speex_resampler_init(channels, sourceRate, destRate, AUDIO_RESAMPLER_QUALITY, &mErrorCode);
//assert(mContext != NULL); //assert(mContext != NULL);
} }
} }
void SpeexResampler::stop() void SpeexResampler::stop()
{ {
if (mContext) if (mContext)
{ {
speex_resampler_destroy((SpeexResamplerState*)mContext); speex_resampler_destroy((SpeexResamplerState*)mContext);
mContext = NULL; mContext = NULL;
} }
} }
SpeexResampler::~SpeexResampler() SpeexResampler::~SpeexResampler()
{ {
stop(); stop();
} }
int SpeexResampler::processBuffer(const void* src, int sourceLength, int& sourceProcessed, void* dest, int destCapacity) int SpeexResampler::processBuffer(const void* src, int sourceLength, int& sourceProcessed, void* dest, int destCapacity)
{ {
assert(mSourceRate != 0 && mDestRate != 0); assert(mSourceRate != 0 && mDestRate != 0);
if (mDestRate == mSourceRate) if (mDestRate == mSourceRate)
{ {
assert(destCapacity >= sourceLength); assert(destCapacity >= sourceLength);
memcpy(dest, src, (size_t)sourceLength); memcpy(dest, src, (size_t)sourceLength);
sourceProcessed = sourceLength; sourceProcessed = sourceLength;
return sourceLength; return sourceLength;
} }
if (!mContext)
{
mContext = speex_resampler_init(mChannels, mSourceRate, mDestRate, AUDIO_RESAMPLER_QUALITY, &mErrorCode);
if (!mContext) if (!mContext)
return 0; {
} mContext = speex_resampler_init(mChannels, mSourceRate, mDestRate, AUDIO_RESAMPLER_QUALITY, &mErrorCode);
if (!mContext)
return 0;
}
// Check if there is zero samples passed // Check if there is zero samples passed
if (sourceLength / (sizeof(short) * mChannels) == 0) if (sourceLength / (sizeof(short) * mChannels) == 0)
{ {
// Consume all data // Consume all data
sourceProcessed = sourceLength; sourceProcessed = sourceLength;
// But no output // But no output
return 0; return 0;
} }
unsigned outLen = getDestLength(sourceLength);
if (outLen > (unsigned)destCapacity)
return 0; // Skip resampling if not enough space
assert((unsigned)destCapacity >= outLen); unsigned outLen = getDestLength(sourceLength);
if (outLen > (unsigned)destCapacity)
return 0; // Skip resampling if not enough space
// Calculate number of samples - input length is in bytes assert((unsigned)destCapacity >= outLen);
unsigned inLen = sourceLength / (sizeof(short) * mChannels);
outLen /= sizeof(short) * mChannels;
assert(mContext != NULL);
int speexCode = speex_resampler_process_interleaved_int((SpeexResamplerState *)mContext, (spx_int16_t*)src, &inLen,
(spx_int16_t*)dest, &outLen);
assert(speexCode == RESAMPLER_ERR_SUCCESS);
// Return results in bytes // Calculate number of samples - input length is in bytes
sourceProcessed = inLen * sizeof(short) * mChannels; unsigned inLen = sourceLength / (sizeof(short) * mChannels);
return outLen * sizeof(short) * mChannels; outLen /= sizeof(short) * mChannels;
assert(mContext != NULL);
int speexCode = speex_resampler_process_interleaved_int((SpeexResamplerState *)mContext, (spx_int16_t*)src, &inLen,
(spx_int16_t*)dest, &outLen);
assert(speexCode == RESAMPLER_ERR_SUCCESS);
// Return results in bytes
sourceProcessed = inLen * sizeof(short) * mChannels;
return outLen * sizeof(short) * mChannels;
} }
int SpeexResampler::sourceRate() int SpeexResampler::sourceRate()
{ {
return mSourceRate; return mSourceRate;
} }
int SpeexResampler::destRate() int SpeexResampler::destRate()
@ -113,18 +114,18 @@ int SpeexResampler::destRate()
int SpeexResampler::getDestLength(int sourceLen) int SpeexResampler::getDestLength(int sourceLen)
{ {
return int(sourceLen * (float(mDestRate) / mSourceRate) + 0.5) / 2 * 2; return int(sourceLen * (float(mDestRate) / mSourceRate) + 0.5) / 2 * 2;
} }
int SpeexResampler::getSourceLength(int destLen) int SpeexResampler::getSourceLength(int destLen)
{ {
return int(destLen * (float(mSourceRate) / mDestRate) + 0.5) / 2 * 2; return int(destLen * (float(mSourceRate) / mDestRate) + 0.5) / 2 * 2;
} }
// Returns instance + speex resampler size in bytes // Returns instance + speex resampler size in bytes
int SpeexResampler::getSize() const int SpeexResampler::getSize() const
{ {
return sizeof(*this) + 200; // 200 is approximate size of speex resample structure return sizeof(*this) + 200; // 200 is approximate size of speex resample structure
} }
// -------------------------- ChannelConverter -------------------- // -------------------------- ChannelConverter --------------------
@ -142,62 +143,62 @@ int ChannelConverter::stereoToMono(const void *source, int sourceLength, void *d
int ChannelConverter::monoToStereo(const void *source, int sourceLength, void *dest, int destLength) int ChannelConverter::monoToStereo(const void *source, int sourceLength, void *dest, int destLength)
{ {
assert(destLength == sourceLength * 2); assert(destLength == sourceLength * 2);
const short* input = (const short*)source; const short* input = (const short*)source;
short* output = (short*)dest; short* output = (short*)dest;
// Convert starting from the end of buffer to allow inplace conversion // Convert starting from the end of buffer to allow inplace conversion
for (int sampleIndex = sourceLength/2 - 1; sampleIndex >= 0; sampleIndex--) for (int sampleIndex = sourceLength/2 - 1; sampleIndex >= 0; sampleIndex--)
{ {
output[2*sampleIndex] = output[2*sampleIndex+1] = input[sampleIndex]; output[2*sampleIndex] = output[2*sampleIndex+1] = input[sampleIndex];
} }
return sourceLength * 2; return sourceLength * 2;
} }
#if defined(USE_WEBRTC_RESAMPLER) #if defined(USE_WEBRTC_RESAMPLER)
Resampler48kTo16k::Resampler48kTo16k() Resampler48kTo16k::Resampler48kTo16k()
{ {
WebRtcSpl_ResetResample48khzTo16khz(&mContext); WebRtcSpl_ResetResample48khzTo16khz(&mContext);
} }
Resampler48kTo16k::~Resampler48kTo16k() Resampler48kTo16k::~Resampler48kTo16k()
{ {
WebRtcSpl_ResetResample48khzTo16khz(&mContext); WebRtcSpl_ResetResample48khzTo16khz(&mContext);
} }
int Resampler48kTo16k::process(const void *source, int sourceLen, void *dest, int destLen) int Resampler48kTo16k::process(const void *source, int sourceLen, void *dest, int destLen)
{ {
const short* input = (const short*)source; int inputLen = sourceLen / 2; const short* input = (const short*)source; int inputLen = sourceLen / 2;
short* output = (short*)dest; //int outputCapacity = destLen / 2; short* output = (short*)dest; //int outputCapacity = destLen / 2;
assert(inputLen % 480 == 0); assert(inputLen % 480 == 0);
int frames = inputLen / 480; int frames = inputLen / 480;
for (int i=0; i<frames; i++) for (int i=0; i<frames; i++)
WebRtcSpl_Resample48khzTo16khz(input + i * 480, output + i * 160, &mContext, mTemp); WebRtcSpl_Resample48khzTo16khz(input + i * 480, output + i * 160, &mContext, mTemp);
return sourceLen / 3; return sourceLen / 3;
} }
Resampler16kto48k::Resampler16kto48k() Resampler16kto48k::Resampler16kto48k()
{ {
WebRtcSpl_ResetResample16khzTo48khz(&mContext); WebRtcSpl_ResetResample16khzTo48khz(&mContext);
} }
Resampler16kto48k::~Resampler16kto48k() Resampler16kto48k::~Resampler16kto48k()
{ {
WebRtcSpl_ResetResample16khzTo48khz(&mContext); WebRtcSpl_ResetResample16khzTo48khz(&mContext);
} }
int Resampler16kto48k::process(const void *source, int sourceLen, void *dest, int destLen) int Resampler16kto48k::process(const void *source, int sourceLen, void *dest, int destLen)
{ {
const WebRtc_Word16* input = (const WebRtc_Word16*)source; int inputLen = sourceLen / 2; const WebRtc_Word16* input = (const WebRtc_Word16*)source; int inputLen = sourceLen / 2;
WebRtc_Word16* output = (WebRtc_Word16*)dest; //int outputCapacity = destLen / 2; WebRtc_Word16* output = (WebRtc_Word16*)dest; //int outputCapacity = destLen / 2;
assert(inputLen % 160 == 0); assert(inputLen % 160 == 0);
int frames = inputLen / 160; int frames = inputLen / 160;
for (int i=0; i<frames; i++) for (int i=0; i<frames; i++)
WebRtcSpl_Resample16khzTo48khz(input + i * 160, output + i * 480, &mContext, mTemp); WebRtcSpl_Resample16khzTo48khz(input + i * 160, output + i * 480, &mContext, mTemp);
return sourceLen * 3; return sourceLen * 3;
} }
#endif #endif
@ -215,21 +216,21 @@ UniversalResampler::~UniversalResampler()
int UniversalResampler::resample(int sourceRate, const void *sourceBuffer, int sourceLength, int& sourceProcessed, int destRate, void *destBuffer, int destCapacity) int UniversalResampler::resample(int sourceRate, const void *sourceBuffer, int sourceLength, int& sourceProcessed, int destRate, void *destBuffer, int destCapacity)
{ {
assert(destBuffer && sourceBuffer); assert(destBuffer && sourceBuffer);
int result; int result;
if (sourceRate == destRate) if (sourceRate == destRate)
{ {
assert(destCapacity >= sourceLength); assert(destCapacity >= sourceLength);
memcpy(destBuffer, sourceBuffer, (size_t)sourceLength); memcpy(destBuffer, sourceBuffer, (size_t)sourceLength);
sourceProcessed = sourceLength; sourceProcessed = sourceLength;
result = sourceLength; result = sourceLength;
} }
else else
{ {
PResampler r = findResampler(sourceRate, destRate); PResampler r = findResampler(sourceRate, destRate);
result = r->processBuffer(sourceBuffer, sourceLength, sourceProcessed, destBuffer, destCapacity); result = r->processBuffer(sourceBuffer, sourceLength, sourceProcessed, destBuffer, destCapacity);
} }
return result; return result;
} }
void UniversalResampler::preload() void UniversalResampler::preload()
@ -239,33 +240,33 @@ void UniversalResampler::preload()
int UniversalResampler::getDestLength(int sourceRate, int destRate, int sourceLength) int UniversalResampler::getDestLength(int sourceRate, int destRate, int sourceLength)
{ {
if (sourceRate == destRate) if (sourceRate == destRate)
return sourceLength; return sourceLength;
else else
return findResampler(sourceRate, destRate)->getDestLength(sourceLength); return findResampler(sourceRate, destRate)->getDestLength(sourceLength);
} }
int UniversalResampler::getSourceLength(int sourceRate, int destRate, int destLength) int UniversalResampler::getSourceLength(int sourceRate, int destRate, int destLength)
{ {
if (sourceRate == destRate) if (sourceRate == destRate)
return destLength; return destLength;
else else
return findResampler(sourceRate, destRate)->getSourceLength(destLength); return findResampler(sourceRate, destRate)->getSourceLength(destLength);
} }
PResampler UniversalResampler::findResampler(int sourceRate, int destRate) PResampler UniversalResampler::findResampler(int sourceRate, int destRate)
{ {
assert(sourceRate != destRate); assert(sourceRate != destRate);
ResamplerMap::iterator resamplerIter = mResamplerMap.find(RatePair(sourceRate, destRate)); ResamplerMap::iterator resamplerIter = mResamplerMap.find(RatePair(sourceRate, destRate));
PResampler r; PResampler r;
if (resamplerIter == mResamplerMap.end()) if (resamplerIter == mResamplerMap.end())
{ {
r = PResampler(new Resampler()); r = PResampler(new Resampler());
r->start(AUDIO_CHANNELS, sourceRate, destRate); r->start(AUDIO_CHANNELS, sourceRate, destRate);
mResamplerMap[RatePair(sourceRate, destRate)] = r; mResamplerMap[RatePair(sourceRate, destRate)] = r;
} }
else else
r = resamplerIter->second; r = resamplerIter->second;
return r; return r;
} }

View File

@ -1,4 +1,4 @@
/* Copyright(C) 2007-2014 VoIP objects (voipobjects.com) /* Copyright(C) 2007-2018 VoIP objects (voipobjects.com)
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -16,9 +16,9 @@
namespace Audio namespace Audio
{ {
class SpeexResampler class SpeexResampler
{ {
public: public:
SpeexResampler(); SpeexResampler();
~SpeexResampler(); ~SpeexResampler();
@ -33,29 +33,29 @@ namespace Audio
// Returns instance + speex encoder size in bytes // Returns instance + speex encoder size in bytes
int getSize() const; int getSize() const;
protected: protected:
void* mContext; void* mContext;
int mErrorCode; int mErrorCode;
int mSourceRate, int mSourceRate,
mDestRate, mDestRate,
mChannels; mChannels;
short mLastSample; short mLastSample;
}; };
typedef SpeexResampler Resampler; typedef SpeexResampler Resampler;
typedef std::shared_ptr<Resampler> PResampler; typedef std::shared_ptr<Resampler> PResampler;
class ChannelConverter class ChannelConverter
{ {
public: public:
static int stereoToMono(const void* source, int sourceLength, void* dest, int destLength); static int stereoToMono(const void* source, int sourceLength, void* dest, int destLength);
static int monoToStereo(const void* source, int sourceLength, void* dest, int destLength); static int monoToStereo(const void* source, int sourceLength, void* dest, int destLength);
}; };
// Operates with AUDIO_CHANNELS number of channels // Operates with AUDIO_CHANNELS number of channels
class UniversalResampler class UniversalResampler
{ {
public: public:
UniversalResampler(); UniversalResampler();
~UniversalResampler(); ~UniversalResampler();
@ -63,39 +63,39 @@ namespace Audio
int getDestLength(int sourceRate, int destRate, int sourceLength); int getDestLength(int sourceRate, int destRate, int sourceLength);
int getSourceLength(int sourceRate, int destRate, int destLength); int getSourceLength(int sourceRate, int destRate, int destLength);
protected: protected:
typedef std::pair<int, int> RatePair; typedef std::pair<int, int> RatePair;
typedef std::map<RatePair, PResampler> ResamplerMap; typedef std::map<RatePair, PResampler> ResamplerMap;
ResamplerMap mResamplerMap; ResamplerMap mResamplerMap;
PResampler findResampler(int sourceRate, int destRate); PResampler findResampler(int sourceRate, int destRate);
void preload(); void preload();
}; };
#ifdef USE_WEBRTC_RESAMPLER #ifdef USE_WEBRTC_RESAMPLER
// n*10 milliseconds buffers required! // n*10 milliseconds buffers required!
class Resampler48kTo16k class Resampler48kTo16k
{ {
public: public:
Resampler48kTo16k(); Resampler48kTo16k();
~Resampler48kTo16k(); ~Resampler48kTo16k();
int process(const void* source, int sourceLen, void* dest, int destLen); int process(const void* source, int sourceLen, void* dest, int destLen);
protected: protected:
WebRtc_Word32 mTemp[496]; WebRtc_Word32 mTemp[496];
WebRtcSpl_State48khzTo16khz mContext; WebRtcSpl_State48khzTo16khz mContext;
}; };
class Resampler16kto48k class Resampler16kto48k
{ {
public: public:
Resampler16kto48k(); Resampler16kto48k();
~Resampler16kto48k(); ~Resampler16kto48k();
int process(const void* source, int sourceLen, void* dest, int destLen); int process(const void* source, int sourceLen, void* dest, int destLen);
protected: protected:
WebRtc_Word32 mTemp[336]; WebRtc_Word32 mTemp[336];
WebRtcSpl_State16khzTo48khz mContext; WebRtcSpl_State16khzTo48khz mContext;
}; };
#endif #endif
} }