Use backticks not vertical bars to denote variables in comments for /common_audio
Bug: webrtc:12338 Change-Id: I884db28e6d9a87d343be7c2616571a8bee28252c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/226944 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34568}
This commit is contained in:
parent
37f664f6d5
commit
96315752d2
@ -20,7 +20,7 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Format conversion (remixing and resampling) for audio. Only simple remixing
|
// Format conversion (remixing and resampling) for audio. Only simple remixing
|
||||||
// conversions are supported: downmix to mono (i.e. |dst_channels| == 1) or
|
// conversions are supported: downmix to mono (i.e. `dst_channels` == 1) or
|
||||||
// upmix from mono (i.e. |src_channels == 1|).
|
// upmix from mono (i.e. |src_channels == 1|).
|
||||||
//
|
//
|
||||||
// The source and destination chunks have the same duration in time; specifying
|
// The source and destination chunks have the same duration in time; specifying
|
||||||
@ -35,8 +35,8 @@ class AudioConverter {
|
|||||||
size_t dst_frames);
|
size_t dst_frames);
|
||||||
virtual ~AudioConverter() {}
|
virtual ~AudioConverter() {}
|
||||||
|
|
||||||
// Convert |src|, containing |src_size| samples, to |dst|, having a sample
|
// Convert `src`, containing `src_size` samples, to `dst`, having a sample
|
||||||
// capacity of |dst_capacity|. Both point to a series of buffers containing
|
// capacity of `dst_capacity`. Both point to a series of buffers containing
|
||||||
// the samples for each channel. The sizes must correspond to the format
|
// the samples for each channel. The sizes must correspond to the format
|
||||||
// passed to Create().
|
// passed to Create().
|
||||||
virtual void Convert(const float* const* src,
|
virtual void Convert(const float* const* src,
|
||||||
|
|||||||
@ -25,7 +25,7 @@ namespace webrtc {
|
|||||||
|
|
||||||
typedef std::unique_ptr<ChannelBuffer<float>> ScopedBuffer;
|
typedef std::unique_ptr<ChannelBuffer<float>> ScopedBuffer;
|
||||||
|
|
||||||
// Sets the signal value to increase by |data| with every sample.
|
// Sets the signal value to increase by `data` with every sample.
|
||||||
ScopedBuffer CreateBuffer(const std::vector<float>& data, size_t frames) {
|
ScopedBuffer CreateBuffer(const std::vector<float>& data, size_t frames) {
|
||||||
const size_t num_channels = data.size();
|
const size_t num_channels = data.size();
|
||||||
ScopedBuffer sb(new ChannelBuffer<float>(frames, num_channels));
|
ScopedBuffer sb(new ChannelBuffer<float>(frames, num_channels));
|
||||||
@ -41,8 +41,8 @@ void VerifyParams(const ChannelBuffer<float>& ref,
|
|||||||
EXPECT_EQ(ref.num_frames(), test.num_frames());
|
EXPECT_EQ(ref.num_frames(), test.num_frames());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the best SNR based on the error between |ref_frame| and
|
// Computes the best SNR based on the error between `ref_frame` and
|
||||||
// |test_frame|. It searches around |expected_delay| in samples between the
|
// `test_frame`. It searches around `expected_delay` in samples between the
|
||||||
// signals to compensate for the resampling delay.
|
// signals to compensate for the resampling delay.
|
||||||
float ComputeSNR(const ChannelBuffer<float>& ref,
|
float ComputeSNR(const ChannelBuffer<float>& ref,
|
||||||
const ChannelBuffer<float>& test,
|
const ChannelBuffer<float>& test,
|
||||||
|
|||||||
@ -29,15 +29,15 @@ namespace webrtc {
|
|||||||
//
|
//
|
||||||
// The buffer structure is showed below for a 2 channel and 2 bands case:
|
// The buffer structure is showed below for a 2 channel and 2 bands case:
|
||||||
//
|
//
|
||||||
// |data_|:
|
// `data_`:
|
||||||
// { [ --- b1ch1 --- ] [ --- b2ch1 --- ] [ --- b1ch2 --- ] [ --- b2ch2 --- ] }
|
// { [ --- b1ch1 --- ] [ --- b2ch1 --- ] [ --- b1ch2 --- ] [ --- b2ch2 --- ] }
|
||||||
//
|
//
|
||||||
// The pointer arrays for the same example are as follows:
|
// The pointer arrays for the same example are as follows:
|
||||||
//
|
//
|
||||||
// |channels_|:
|
// `channels_`:
|
||||||
// { [ b1ch1* ] [ b1ch2* ] [ b2ch1* ] [ b2ch2* ] }
|
// { [ b1ch1* ] [ b1ch2* ] [ b2ch1* ] [ b2ch2* ] }
|
||||||
//
|
//
|
||||||
// |bands_|:
|
// `bands_`:
|
||||||
// { [ b1ch1* ] [ b2ch1* ] [ b1ch2* ] [ b2ch2* ] }
|
// { [ b1ch1* ] [ b2ch1* ] [ b1ch2* ] [ b2ch2* ] }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ChannelBuffer {
|
class ChannelBuffer {
|
||||||
@ -81,15 +81,15 @@ class ChannelBuffer {
|
|||||||
// If band is explicitly specificed, the channels for a specific band are
|
// If band is explicitly specificed, the channels for a specific band are
|
||||||
// returned and the usage becomes: channels(band)[channel][sample].
|
// returned and the usage becomes: channels(band)[channel][sample].
|
||||||
// Where:
|
// Where:
|
||||||
// 0 <= band < |num_bands_|
|
// 0 <= band < `num_bands_`
|
||||||
// 0 <= channel < |num_allocated_channels_|
|
// 0 <= channel < `num_allocated_channels_`
|
||||||
// 0 <= sample < |num_frames_per_band_|
|
// 0 <= sample < `num_frames_per_band_`
|
||||||
|
|
||||||
// If band is not explicitly specified, the full-band channels (or lower band
|
// If band is not explicitly specified, the full-band channels (or lower band
|
||||||
// channels) are returned and the usage becomes: channels()[channel][sample].
|
// channels) are returned and the usage becomes: channels()[channel][sample].
|
||||||
// Where:
|
// Where:
|
||||||
// 0 <= channel < |num_allocated_channels_|
|
// 0 <= channel < `num_allocated_channels_`
|
||||||
// 0 <= sample < |num_frames_|
|
// 0 <= sample < `num_frames_`
|
||||||
const T* const* channels(size_t band = 0) const {
|
const T* const* channels(size_t band = 0) const {
|
||||||
RTC_DCHECK_LT(band, num_bands_);
|
RTC_DCHECK_LT(band, num_bands_);
|
||||||
return &channels_[band * num_allocated_channels_];
|
return &channels_[band * num_allocated_channels_];
|
||||||
@ -109,9 +109,9 @@ class ChannelBuffer {
|
|||||||
// Usage:
|
// Usage:
|
||||||
// bands(channel)[band][sample].
|
// bands(channel)[band][sample].
|
||||||
// Where:
|
// Where:
|
||||||
// 0 <= channel < |num_channels_|
|
// 0 <= channel < `num_channels_`
|
||||||
// 0 <= band < |num_bands_|
|
// 0 <= band < `num_bands_`
|
||||||
// 0 <= sample < |num_frames_per_band_|
|
// 0 <= sample < `num_frames_per_band_`
|
||||||
const T* const* bands(size_t channel) const {
|
const T* const* bands(size_t channel) const {
|
||||||
RTC_DCHECK_LT(channel, num_channels_);
|
RTC_DCHECK_LT(channel, num_channels_);
|
||||||
RTC_DCHECK_GE(channel, 0);
|
RTC_DCHECK_GE(channel, 0);
|
||||||
@ -129,8 +129,8 @@ class ChannelBuffer {
|
|||||||
return bands_view_[channel];
|
return bands_view_[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the |slice| pointers to the |start_frame| position for each channel.
|
// Sets the `slice` pointers to the `start_frame` position for each channel.
|
||||||
// Returns |slice| for convenience.
|
// Returns `slice` for convenience.
|
||||||
const T* const* Slice(T** slice, size_t start_frame) const {
|
const T* const* Slice(T** slice, size_t start_frame) const {
|
||||||
RTC_DCHECK_LT(start_frame, num_frames_);
|
RTC_DCHECK_LT(start_frame, num_frames_);
|
||||||
for (size_t i = 0; i < num_channels_; ++i)
|
for (size_t i = 0; i < num_channels_; ++i)
|
||||||
|
|||||||
@ -20,8 +20,8 @@ class FIRFilter {
|
|||||||
public:
|
public:
|
||||||
virtual ~FIRFilter() {}
|
virtual ~FIRFilter() {}
|
||||||
|
|
||||||
// Filters the |in| data supplied.
|
// Filters the `in` data supplied.
|
||||||
// |out| must be previously allocated and it must be at least of |length|.
|
// `out` must be previously allocated and it must be at least of `length`.
|
||||||
virtual void Filter(const float* in, size_t length, float* out) = 0;
|
virtual void Filter(const float* in, size_t length, float* out) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ void FIRFilterAVX2::Filter(const float* in, size_t length, float* out) {
|
|||||||
|
|
||||||
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
||||||
|
|
||||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
// Convolves the input signal `in` with the filter kernel `coefficients_`
|
||||||
// taking into account the previous state.
|
// taking into account the previous state.
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
float* in_ptr = &state_[i];
|
float* in_ptr = &state_[i];
|
||||||
|
|||||||
@ -34,7 +34,7 @@ FIRFilterC::FIRFilterC(const float* coefficients, size_t coefficients_length)
|
|||||||
void FIRFilterC::Filter(const float* in, size_t length, float* out) {
|
void FIRFilterC::Filter(const float* in, size_t length, float* out) {
|
||||||
RTC_DCHECK_GT(length, 0);
|
RTC_DCHECK_GT(length, 0);
|
||||||
|
|
||||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
// Convolves the input signal `in` with the filter kernel `coefficients_`
|
||||||
// taking into account the previous state.
|
// taking into account the previous state.
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
out[i] = 0.f;
|
out[i] = 0.f;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class FIRFilter;
|
|||||||
// Creates a filter with the given coefficients. All initial state values will
|
// Creates a filter with the given coefficients. All initial state values will
|
||||||
// be zeros.
|
// be zeros.
|
||||||
// The length of the chunks fed to the filter should never be greater than
|
// The length of the chunks fed to the filter should never be greater than
|
||||||
// |max_input_length|. This is needed because, when vectorizing it is
|
// `max_input_length`. This is needed because, when vectorizing it is
|
||||||
// necessary to concatenate the input after the state, and resizing this array
|
// necessary to concatenate the input after the state, and resizing this array
|
||||||
// dynamically is expensive.
|
// dynamically is expensive.
|
||||||
FIRFilter* CreateFirFilter(const float* coefficients,
|
FIRFilter* CreateFirFilter(const float* coefficients,
|
||||||
|
|||||||
@ -48,7 +48,7 @@ void FIRFilterNEON::Filter(const float* in, size_t length, float* out) {
|
|||||||
|
|
||||||
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
||||||
|
|
||||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
// Convolves the input signal `in` with the filter kernel `coefficients_`
|
||||||
// taking into account the previous state.
|
// taking into account the previous state.
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
float* in_ptr = &state_[i];
|
float* in_ptr = &state_[i];
|
||||||
|
|||||||
@ -49,7 +49,7 @@ void FIRFilterSSE2::Filter(const float* in, size_t length, float* out) {
|
|||||||
|
|
||||||
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
||||||
|
|
||||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
// Convolves the input signal `in` with the filter kernel `coefficients_`
|
||||||
// taking into account the previous state.
|
// taking into account the previous state.
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
float* in_ptr = &state_[i];
|
float* in_ptr = &state_[i];
|
||||||
|
|||||||
@ -91,9 +91,9 @@ inline float FloatS16ToDbfs(float v) {
|
|||||||
return 20.0f * std::log10(v) + kMinDbfs;
|
return 20.0f * std::log10(v) + kMinDbfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
|
// Copy audio from `src` channels to `dest` channels unless `src` and `dest`
|
||||||
// point to the same address. |src| and |dest| must have the same number of
|
// point to the same address. `src` and `dest` must have the same number of
|
||||||
// channels, and there must be sufficient space allocated in |dest|.
|
// channels, and there must be sufficient space allocated in `dest`.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void CopyAudioIfNeeded(const T* const* src,
|
void CopyAudioIfNeeded(const T* const* src,
|
||||||
int num_frames,
|
int num_frames,
|
||||||
@ -106,9 +106,9 @@ void CopyAudioIfNeeded(const T* const* src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deinterleave audio from |interleaved| to the channel buffers pointed to
|
// Deinterleave audio from `interleaved` to the channel buffers pointed to
|
||||||
// by |deinterleaved|. There must be sufficient space allocated in the
|
// by `deinterleaved`. There must be sufficient space allocated in the
|
||||||
// |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
|
// `deinterleaved` buffers (`num_channel` buffers with `samples_per_channel`
|
||||||
// per buffer).
|
// per buffer).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Deinterleave(const T* interleaved,
|
void Deinterleave(const T* interleaved,
|
||||||
@ -125,9 +125,9 @@ void Deinterleave(const T* interleaved,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interleave audio from the channel buffers pointed to by |deinterleaved| to
|
// Interleave audio from the channel buffers pointed to by `deinterleaved` to
|
||||||
// |interleaved|. There must be sufficient space allocated in |interleaved|
|
// `interleaved`. There must be sufficient space allocated in `interleaved`
|
||||||
// (|samples_per_channel| * |num_channels|).
|
// (`samples_per_channel` * `num_channels`).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Interleave(const T* const* deinterleaved,
|
void Interleave(const T* const* deinterleaved,
|
||||||
size_t samples_per_channel,
|
size_t samples_per_channel,
|
||||||
@ -143,9 +143,9 @@ void Interleave(const T* const* deinterleaved,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies audio from a single channel buffer pointed to by |mono| to each
|
// Copies audio from a single channel buffer pointed to by `mono` to each
|
||||||
// channel of |interleaved|. There must be sufficient space allocated in
|
// channel of `interleaved`. There must be sufficient space allocated in
|
||||||
// |interleaved| (|samples_per_channel| * |num_channels|).
|
// `interleaved` (`samples_per_channel` * `num_channels`).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void UpmixMonoToInterleaved(const T* mono,
|
void UpmixMonoToInterleaved(const T* mono,
|
||||||
int num_frames,
|
int num_frames,
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class RealFourier {
|
|||||||
// output (i.e. |2^order / 2 + 1|).
|
// output (i.e. |2^order / 2 + 1|).
|
||||||
static size_t ComplexLength(int order);
|
static size_t ComplexLength(int order);
|
||||||
|
|
||||||
// Buffer allocation helpers. The buffers are large enough to hold |count|
|
// Buffer allocation helpers. The buffers are large enough to hold `count`
|
||||||
// floats/complexes and suitably aligned for use by the implementation.
|
// floats/complexes and suitably aligned for use by the implementation.
|
||||||
// The returned scopers are set up with proper deleters; the caller owns
|
// The returned scopers are set up with proper deleters; the caller owns
|
||||||
// the allocated memory.
|
// the allocated memory.
|
||||||
|
|||||||
@ -63,12 +63,12 @@ size_t PushSincResampler::Resample(const float* source,
|
|||||||
// request through Run().
|
// request through Run().
|
||||||
//
|
//
|
||||||
// If this wasn't done, SincResampler would call Run() twice on the first
|
// If this wasn't done, SincResampler would call Run() twice on the first
|
||||||
// pass, and we'd have to introduce an entire |source_frames| of delay, rather
|
// pass, and we'd have to introduce an entire `source_frames` of delay, rather
|
||||||
// than the minimum half kernel.
|
// than the minimum half kernel.
|
||||||
//
|
//
|
||||||
// It works out that ChunkSize() is exactly the amount of output we need to
|
// It works out that ChunkSize() is exactly the amount of output we need to
|
||||||
// request in order to prime the buffer with a single Run() request for
|
// request in order to prime the buffer with a single Run() request for
|
||||||
// |source_frames|.
|
// `source_frames`.
|
||||||
if (first_pass_)
|
if (first_pass_)
|
||||||
resampler_->Resample(resampler_->ChunkSize(), destination);
|
resampler_->Resample(resampler_->ChunkSize(), destination);
|
||||||
|
|
||||||
|
|||||||
@ -33,11 +33,11 @@ class PushSincResampler : public SincResamplerCallback {
|
|||||||
PushSincResampler(size_t source_frames, size_t destination_frames);
|
PushSincResampler(size_t source_frames, size_t destination_frames);
|
||||||
~PushSincResampler() override;
|
~PushSincResampler() override;
|
||||||
|
|
||||||
// Perform the resampling. |source_frames| must always equal the
|
// Perform the resampling. `source_frames` must always equal the
|
||||||
// |source_frames| provided at construction. |destination_capacity| must be
|
// `source_frames` provided at construction. `destination_capacity` must be
|
||||||
// at least as large as |destination_frames|. Returns the number of samples
|
// at least as large as `destination_frames`. Returns the number of samples
|
||||||
// provided in destination (for convenience, since this will always be equal
|
// provided in destination (for convenience, since this will always be equal
|
||||||
// to |destination_frames|).
|
// to `destination_frames`).
|
||||||
size_t Resample(const int16_t* source,
|
size_t Resample(const int16_t* source,
|
||||||
size_t source_frames,
|
size_t source_frames,
|
||||||
int16_t* destination,
|
int16_t* destination,
|
||||||
|
|||||||
@ -305,7 +305,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
|
|
||||||
// Next run through some additional cases interesting for WebRTC.
|
// Next run through some additional cases interesting for WebRTC.
|
||||||
// We skip some extreme downsampled cases (192 -> {8, 16}, 96 -> 8)
|
// We skip some extreme downsampled cases (192 -> {8, 16}, 96 -> 8)
|
||||||
// because they violate |kHighFrequencyMaxError|, which is not
|
// because they violate `kHighFrequencyMaxError`, which is not
|
||||||
// unexpected. It's very unlikely that we'll see these conversions in
|
// unexpected. It's very unlikely that we'll see these conversions in
|
||||||
// practice anyway.
|
// practice anyway.
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,7 @@
|
|||||||
// 8) Else, if we're not on the second load, goto (4).
|
// 8) Else, if we're not on the second load, goto (4).
|
||||||
//
|
//
|
||||||
// Note: we're glossing over how the sub-sample handling works with
|
// Note: we're glossing over how the sub-sample handling works with
|
||||||
// |virtual_source_idx_|, etc.
|
// `virtual_source_idx_`, etc.
|
||||||
|
|
||||||
// MSVC++ requires this to be set before any other includes to get M_PI.
|
// MSVC++ requires this to be set before any other includes to get M_PI.
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
@ -102,7 +102,7 @@ namespace webrtc {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
double SincScaleFactor(double io_ratio) {
|
double SincScaleFactor(double io_ratio) {
|
||||||
// |sinc_scale_factor| is basically the normalized cutoff frequency of the
|
// `sinc_scale_factor` is basically the normalized cutoff frequency of the
|
||||||
// low-pass filter.
|
// low-pass filter.
|
||||||
double sinc_scale_factor = io_ratio > 1.0 ? 1.0 / io_ratio : 1.0;
|
double sinc_scale_factor = io_ratio > 1.0 ? 1.0 / io_ratio : 1.0;
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ void SincResampler::SetRatio(double io_sample_rate_ratio) {
|
|||||||
io_sample_rate_ratio_ = io_sample_rate_ratio;
|
io_sample_rate_ratio_ = io_sample_rate_ratio;
|
||||||
|
|
||||||
// Optimize reinitialization by reusing values which are independent of
|
// Optimize reinitialization by reusing values which are independent of
|
||||||
// |sinc_scale_factor|. Provides a 3x speedup.
|
// `sinc_scale_factor`. Provides a 3x speedup.
|
||||||
const double sinc_scale_factor = SincScaleFactor(io_sample_rate_ratio_);
|
const double sinc_scale_factor = SincScaleFactor(io_sample_rate_ratio_);
|
||||||
for (size_t offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) {
|
for (size_t offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) {
|
||||||
for (size_t i = 0; i < kKernelSize; ++i) {
|
for (size_t i = 0; i < kKernelSize; ++i) {
|
||||||
@ -268,8 +268,8 @@ void SincResampler::Resample(size_t frames, float* destination) {
|
|||||||
const double current_io_ratio = io_sample_rate_ratio_;
|
const double current_io_ratio = io_sample_rate_ratio_;
|
||||||
const float* const kernel_ptr = kernel_storage_.get();
|
const float* const kernel_ptr = kernel_storage_.get();
|
||||||
while (remaining_frames) {
|
while (remaining_frames) {
|
||||||
// |i| may be negative if the last Resample() call ended on an iteration
|
// `i` may be negative if the last Resample() call ended on an iteration
|
||||||
// that put |virtual_source_idx_| over the limit.
|
// that put `virtual_source_idx_` over the limit.
|
||||||
//
|
//
|
||||||
// Note: The loop construct here can severely impact performance on ARM
|
// Note: The loop construct here can severely impact performance on ARM
|
||||||
// or when built with clang. See https://codereview.chromium.org/18566009/
|
// or when built with clang. See https://codereview.chromium.org/18566009/
|
||||||
@ -278,7 +278,7 @@ void SincResampler::Resample(size_t frames, float* destination) {
|
|||||||
i > 0; --i) {
|
i > 0; --i) {
|
||||||
RTC_DCHECK_LT(virtual_source_idx_, block_size_);
|
RTC_DCHECK_LT(virtual_source_idx_, block_size_);
|
||||||
|
|
||||||
// |virtual_source_idx_| lies in between two kernel offsets so figure out
|
// `virtual_source_idx_` lies in between two kernel offsets so figure out
|
||||||
// what they are.
|
// what they are.
|
||||||
const int source_idx = static_cast<int>(virtual_source_idx_);
|
const int source_idx = static_cast<int>(virtual_source_idx_);
|
||||||
const double subsample_remainder = virtual_source_idx_ - source_idx;
|
const double subsample_remainder = virtual_source_idx_ - source_idx;
|
||||||
@ -288,16 +288,16 @@ void SincResampler::Resample(size_t frames, float* destination) {
|
|||||||
const int offset_idx = static_cast<int>(virtual_offset_idx);
|
const int offset_idx = static_cast<int>(virtual_offset_idx);
|
||||||
|
|
||||||
// We'll compute "convolutions" for the two kernels which straddle
|
// We'll compute "convolutions" for the two kernels which straddle
|
||||||
// |virtual_source_idx_|.
|
// `virtual_source_idx_`.
|
||||||
const float* const k1 = kernel_ptr + offset_idx * kKernelSize;
|
const float* const k1 = kernel_ptr + offset_idx * kKernelSize;
|
||||||
const float* const k2 = k1 + kKernelSize;
|
const float* const k2 = k1 + kKernelSize;
|
||||||
|
|
||||||
// Ensure |k1|, |k2| are 32-byte aligned for SIMD usage. Should always be
|
// Ensure `k1`, `k2` are 32-byte aligned for SIMD usage. Should always be
|
||||||
// true so long as kKernelSize is a multiple of 32.
|
// true so long as kKernelSize is a multiple of 32.
|
||||||
RTC_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(k1) % 32);
|
RTC_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(k1) % 32);
|
||||||
RTC_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(k2) % 32);
|
RTC_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(k2) % 32);
|
||||||
|
|
||||||
// Initialize input pointer based on quantized |virtual_source_idx_|.
|
// Initialize input pointer based on quantized `virtual_source_idx_`.
|
||||||
const float* const input_ptr = r1_ + source_idx;
|
const float* const input_ptr = r1_ + source_idx;
|
||||||
|
|
||||||
// Figure out how much to weight each kernel's "convolution".
|
// Figure out how much to weight each kernel's "convolution".
|
||||||
|
|||||||
@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Callback class for providing more data into the resampler. Expects |frames|
|
// Callback class for providing more data into the resampler. Expects `frames`
|
||||||
// of data to be rendered into |destination|; zero padded if not enough frames
|
// of data to be rendered into `destination`; zero padded if not enough frames
|
||||||
// are available to satisfy the request.
|
// are available to satisfy the request.
|
||||||
class SincResamplerCallback {
|
class SincResamplerCallback {
|
||||||
public:
|
public:
|
||||||
@ -53,10 +53,10 @@ class SincResampler {
|
|||||||
static const size_t kKernelStorageSize =
|
static const size_t kKernelStorageSize =
|
||||||
kKernelSize * (kKernelOffsetCount + 1);
|
kKernelSize * (kKernelOffsetCount + 1);
|
||||||
|
|
||||||
// Constructs a SincResampler with the specified |read_cb|, which is used to
|
// Constructs a SincResampler with the specified `read_cb`, which is used to
|
||||||
// acquire audio data for resampling. |io_sample_rate_ratio| is the ratio
|
// acquire audio data for resampling. `io_sample_rate_ratio` is the ratio
|
||||||
// of input / output sample rates. |request_frames| controls the size in
|
// of input / output sample rates. `request_frames` controls the size in
|
||||||
// frames of the buffer requested by each |read_cb| call. The value must be
|
// frames of the buffer requested by each `read_cb` call. The value must be
|
||||||
// greater than kKernelSize. Specify kDefaultRequestSize if there are no
|
// greater than kKernelSize. Specify kDefaultRequestSize if there are no
|
||||||
// request size constraints.
|
// request size constraints.
|
||||||
SincResampler(double io_sample_rate_ratio,
|
SincResampler(double io_sample_rate_ratio,
|
||||||
@ -64,11 +64,11 @@ class SincResampler {
|
|||||||
SincResamplerCallback* read_cb);
|
SincResamplerCallback* read_cb);
|
||||||
virtual ~SincResampler();
|
virtual ~SincResampler();
|
||||||
|
|
||||||
// Resample |frames| of data from |read_cb_| into |destination|.
|
// Resample `frames` of data from `read_cb_` into `destination`.
|
||||||
void Resample(size_t frames, float* destination);
|
void Resample(size_t frames, float* destination);
|
||||||
|
|
||||||
// The maximum size in frames that guarantees Resample() will only make a
|
// The maximum size in frames that guarantees Resample() will only make a
|
||||||
// single call to |read_cb_| for more data.
|
// single call to `read_cb_` for more data.
|
||||||
size_t ChunkSize() const;
|
size_t ChunkSize() const;
|
||||||
|
|
||||||
size_t request_frames() const { return request_frames_; }
|
size_t request_frames() const { return request_frames_; }
|
||||||
@ -77,12 +77,12 @@ class SincResampler {
|
|||||||
// not call while Resample() is in progress.
|
// not call while Resample() is in progress.
|
||||||
void Flush();
|
void Flush();
|
||||||
|
|
||||||
// Update |io_sample_rate_ratio_|. SetRatio() will cause a reconstruction of
|
// Update `io_sample_rate_ratio_`. SetRatio() will cause a reconstruction of
|
||||||
// the kernels used for resampling. Not thread safe, do not call while
|
// the kernels used for resampling. Not thread safe, do not call while
|
||||||
// Resample() is in progress.
|
// Resample() is in progress.
|
||||||
//
|
//
|
||||||
// TODO(ajm): Use this in PushSincResampler rather than reconstructing
|
// TODO(ajm): Use this in PushSincResampler rather than reconstructing
|
||||||
// SincResampler. We would also need a way to update |request_frames_|.
|
// SincResampler. We would also need a way to update `request_frames_`.
|
||||||
void SetRatio(double io_sample_rate_ratio);
|
void SetRatio(double io_sample_rate_ratio);
|
||||||
|
|
||||||
float* get_kernel_for_testing() { return kernel_storage_.get(); }
|
float* get_kernel_for_testing() { return kernel_storage_.get(); }
|
||||||
@ -97,11 +97,11 @@ class SincResampler {
|
|||||||
// Selects runtime specific CPU features like SSE. Must be called before
|
// Selects runtime specific CPU features like SSE. Must be called before
|
||||||
// using SincResampler.
|
// using SincResampler.
|
||||||
// TODO(ajm): Currently managed by the class internally. See the note with
|
// TODO(ajm): Currently managed by the class internally. See the note with
|
||||||
// |convolve_proc_| below.
|
// `convolve_proc_` below.
|
||||||
void InitializeCPUSpecificFeatures();
|
void InitializeCPUSpecificFeatures();
|
||||||
|
|
||||||
// Compute convolution of |k1| and |k2| over |input_ptr|, resultant sums are
|
// Compute convolution of `k1` and `k2` over `input_ptr`, resultant sums are
|
||||||
// linearly interpolated using |kernel_interpolation_factor|. On x86 and ARM
|
// linearly interpolated using `kernel_interpolation_factor`. On x86 and ARM
|
||||||
// the underlying implementation is chosen at run time.
|
// the underlying implementation is chosen at run time.
|
||||||
static float Convolve_C(const float* input_ptr,
|
static float Convolve_C(const float* input_ptr,
|
||||||
const float* k1,
|
const float* k1,
|
||||||
@ -136,7 +136,7 @@ class SincResampler {
|
|||||||
// Source of data for resampling.
|
// Source of data for resampling.
|
||||||
SincResamplerCallback* read_cb_;
|
SincResamplerCallback* read_cb_;
|
||||||
|
|
||||||
// The size (in samples) to request from each |read_cb_| execution.
|
// The size (in samples) to request from each `read_cb_` execution.
|
||||||
const size_t request_frames_;
|
const size_t request_frames_;
|
||||||
|
|
||||||
// The number of source frames processed per pass.
|
// The number of source frames processed per pass.
|
||||||
@ -165,7 +165,7 @@ class SincResampler {
|
|||||||
double);
|
double);
|
||||||
ConvolveProc convolve_proc_;
|
ConvolveProc convolve_proc_;
|
||||||
|
|
||||||
// Pointers to the various regions inside |input_buffer_|. See the diagram at
|
// Pointers to the various regions inside `input_buffer_`. See the diagram at
|
||||||
// the top of the .cc file for more information.
|
// the top of the .cc file for more information.
|
||||||
float* r0_;
|
float* r0_;
|
||||||
float* const r1_;
|
float* const r1_;
|
||||||
|
|||||||
@ -25,7 +25,7 @@ float SincResampler::Convolve_AVX2(const float* input_ptr,
|
|||||||
__m256 m_sums1 = _mm256_setzero_ps();
|
__m256 m_sums1 = _mm256_setzero_ps();
|
||||||
__m256 m_sums2 = _mm256_setzero_ps();
|
__m256 m_sums2 = _mm256_setzero_ps();
|
||||||
|
|
||||||
// Based on |input_ptr| alignment, we need to use loadu or load. Unrolling
|
// Based on `input_ptr` alignment, we need to use loadu or load. Unrolling
|
||||||
// these loops has not been tested or benchmarked.
|
// these loops has not been tested or benchmarked.
|
||||||
bool aligned_input = (reinterpret_cast<uintptr_t>(input_ptr) & 0x1F) == 0;
|
bool aligned_input = (reinterpret_cast<uintptr_t>(input_ptr) & 0x1F) == 0;
|
||||||
if (!aligned_input) {
|
if (!aligned_input) {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ float SincResampler::Convolve_SSE(const float* input_ptr,
|
|||||||
__m128 m_sums1 = _mm_setzero_ps();
|
__m128 m_sums1 = _mm_setzero_ps();
|
||||||
__m128 m_sums2 = _mm_setzero_ps();
|
__m128 m_sums2 = _mm_setzero_ps();
|
||||||
|
|
||||||
// Based on |input_ptr| alignment, we need to use loadu or load. Unrolling
|
// Based on `input_ptr` alignment, we need to use loadu or load. Unrolling
|
||||||
// these loops hurt performance in local testing.
|
// these loops hurt performance in local testing.
|
||||||
if (reinterpret_cast<uintptr_t>(input_ptr) & 0x0F) {
|
if (reinterpret_cast<uintptr_t>(input_ptr) & 0x0F) {
|
||||||
for (size_t i = 0; i < kKernelSize; i += 4) {
|
for (size_t i = 0; i < kKernelSize; i += 4) {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ namespace webrtc {
|
|||||||
// resampler for the specific sample rate conversion being used.
|
// resampler for the specific sample rate conversion being used.
|
||||||
class SinusoidalLinearChirpSource : public SincResamplerCallback {
|
class SinusoidalLinearChirpSource : public SincResamplerCallback {
|
||||||
public:
|
public:
|
||||||
// |delay_samples| can be used to insert a fractional sample delay into the
|
// `delay_samples` can be used to insert a fractional sample delay into the
|
||||||
// source. It will produce zeros until non-negative time is reached.
|
// source. It will produce zeros until non-negative time is reached.
|
||||||
SinusoidalLinearChirpSource(int sample_rate,
|
SinusoidalLinearChirpSource(int sample_rate,
|
||||||
size_t samples,
|
size_t samples,
|
||||||
|
|||||||
@ -18,9 +18,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// Get address of region(s) from which we can read data.
|
// Get address of region(s) from which we can read data.
|
||||||
// If the region is contiguous, |data_ptr_bytes_2| will be zero.
|
// If the region is contiguous, `data_ptr_bytes_2` will be zero.
|
||||||
// If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second
|
// If non-contiguous, `data_ptr_bytes_2` will be the size in bytes of the second
|
||||||
// region. Returns room available to be read or |element_count|, whichever is
|
// region. Returns room available to be read or `element_count`, whichever is
|
||||||
// smaller.
|
// smaller.
|
||||||
static size_t GetBufferReadRegions(RingBuffer* buf,
|
static size_t GetBufferReadRegions(RingBuffer* buf,
|
||||||
size_t element_count,
|
size_t element_count,
|
||||||
@ -120,7 +120,7 @@ size_t WebRtc_ReadBuffer(RingBuffer* self,
|
|||||||
&buf_ptr_bytes_2);
|
&buf_ptr_bytes_2);
|
||||||
if (buf_ptr_bytes_2 > 0) {
|
if (buf_ptr_bytes_2 > 0) {
|
||||||
// We have a wrap around when reading the buffer. Copy the buffer data to
|
// We have a wrap around when reading the buffer. Copy the buffer data to
|
||||||
// |data| and point to it.
|
// `data` and point to it.
|
||||||
memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
|
memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
|
||||||
memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2);
|
memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2);
|
||||||
buf_ptr_1 = data;
|
buf_ptr_1 = data;
|
||||||
@ -129,7 +129,7 @@ size_t WebRtc_ReadBuffer(RingBuffer* self,
|
|||||||
memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
|
memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
|
||||||
}
|
}
|
||||||
if (data_ptr) {
|
if (data_ptr) {
|
||||||
// |buf_ptr_1| == |data| in the case of a wrap.
|
// `buf_ptr_1` == `data` in the case of a wrap.
|
||||||
*data_ptr = read_count == 0 ? NULL : buf_ptr_1;
|
*data_ptr = read_count == 0 ? NULL : buf_ptr_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,14 +39,14 @@ void WebRtc_InitBuffer(RingBuffer* handle);
|
|||||||
void WebRtc_FreeBuffer(void* handle);
|
void WebRtc_FreeBuffer(void* handle);
|
||||||
|
|
||||||
// Reads data from the buffer. Returns the number of elements that were read.
|
// Reads data from the buffer. Returns the number of elements that were read.
|
||||||
// The |data_ptr| will point to the address where the read data is located.
|
// The `data_ptr` will point to the address where the read data is located.
|
||||||
// If no data can be read, |data_ptr| is set to |NULL|. If all data can be read
|
// If no data can be read, `data_ptr` is set to `NULL`. If all data can be read
|
||||||
// without buffer wrap around then |data_ptr| will point to the location in the
|
// without buffer wrap around then `data_ptr` will point to the location in the
|
||||||
// buffer. Otherwise, the data will be copied to |data| (memory allocation done
|
// buffer. Otherwise, the data will be copied to `data` (memory allocation done
|
||||||
// by the user) and |data_ptr| points to the address of |data|. |data_ptr| is
|
// by the user) and `data_ptr` points to the address of `data`. `data_ptr` is
|
||||||
// only guaranteed to be valid until the next call to WebRtc_WriteBuffer().
|
// only guaranteed to be valid until the next call to WebRtc_WriteBuffer().
|
||||||
//
|
//
|
||||||
// To force a copying to |data|, pass a null |data_ptr|.
|
// To force a copying to `data`, pass a null `data_ptr`.
|
||||||
//
|
//
|
||||||
// Returns number of elements read.
|
// Returns number of elements read.
|
||||||
size_t WebRtc_ReadBuffer(RingBuffer* handle,
|
size_t WebRtc_ReadBuffer(RingBuffer* handle,
|
||||||
@ -54,14 +54,14 @@ size_t WebRtc_ReadBuffer(RingBuffer* handle,
|
|||||||
void* data,
|
void* data,
|
||||||
size_t element_count);
|
size_t element_count);
|
||||||
|
|
||||||
// Writes |data| to buffer and returns the number of elements written.
|
// Writes `data` to buffer and returns the number of elements written.
|
||||||
size_t WebRtc_WriteBuffer(RingBuffer* handle,
|
size_t WebRtc_WriteBuffer(RingBuffer* handle,
|
||||||
const void* data,
|
const void* data,
|
||||||
size_t element_count);
|
size_t element_count);
|
||||||
|
|
||||||
// Moves the buffer read position and returns the number of elements moved.
|
// Moves the buffer read position and returns the number of elements moved.
|
||||||
// Positive |element_count| moves the read position towards the write position,
|
// Positive `element_count` moves the read position towards the write position,
|
||||||
// that is, flushing the buffer. Negative |element_count| moves the read
|
// that is, flushing the buffer. Negative `element_count` moves the read
|
||||||
// position away from the the write position, that is, stuffing the buffer.
|
// position away from the the write position, that is, stuffing the buffer.
|
||||||
// Returns number of elements moved.
|
// Returns number of elements moved.
|
||||||
int WebRtc_MoveReadPtr(RingBuffer* handle, int element_count);
|
int WebRtc_MoveReadPtr(RingBuffer* handle, int element_count);
|
||||||
|
|||||||
@ -128,14 +128,14 @@ TEST(RingBufferTest, PassingNulltoReadBufferForcesMemcpy) {
|
|||||||
EXPECT_EQ(kDataSize,
|
EXPECT_EQ(kDataSize,
|
||||||
WebRtc_ReadBuffer(buffer.get(), reinterpret_cast<void**>(&data_ptr),
|
WebRtc_ReadBuffer(buffer.get(), reinterpret_cast<void**>(&data_ptr),
|
||||||
read_data, kDataSize));
|
read_data, kDataSize));
|
||||||
// Copying was not necessary, so |read_data| has not been updated.
|
// Copying was not necessary, so `read_data` has not been updated.
|
||||||
CheckIncrementingData(data_ptr, kDataSize, 0);
|
CheckIncrementingData(data_ptr, kDataSize, 0);
|
||||||
CheckIncrementingData(read_data, kDataSize, kDataSize);
|
CheckIncrementingData(read_data, kDataSize, kDataSize);
|
||||||
|
|
||||||
EXPECT_EQ(kDataSize, WebRtc_WriteBuffer(buffer.get(), write_data, kDataSize));
|
EXPECT_EQ(kDataSize, WebRtc_WriteBuffer(buffer.get(), write_data, kDataSize));
|
||||||
EXPECT_EQ(kDataSize,
|
EXPECT_EQ(kDataSize,
|
||||||
WebRtc_ReadBuffer(buffer.get(), nullptr, read_data, kDataSize));
|
WebRtc_ReadBuffer(buffer.get(), nullptr, read_data, kDataSize));
|
||||||
// Passing null forces a memcpy, so |read_data| is now updated.
|
// Passing null forces a memcpy, so `read_data` is now updated.
|
||||||
CheckIncrementingData(read_data, kDataSize, 0);
|
CheckIncrementingData(read_data, kDataSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ extern "C" {
|
|||||||
// - vector_length : Number of samples used in the dot product
|
// - vector_length : Number of samples used in the dot product
|
||||||
// - scaling : The number of right bit shifts to apply on each term
|
// - scaling : The number of right bit shifts to apply on each term
|
||||||
// during calculation to avoid overflow, i.e., the
|
// during calculation to avoid overflow, i.e., the
|
||||||
// output will be in Q(-|scaling|)
|
// output will be in Q(-`scaling`)
|
||||||
//
|
//
|
||||||
// Return value : The dot product in Q(-scaling)
|
// Return value : The dot product in Q(-scaling)
|
||||||
int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
|
int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
|
||||||
|
|||||||
@ -81,7 +81,7 @@ int WebRtcSpl_RealForwardFFT(struct RealFFT* self,
|
|||||||
// boundary.
|
// boundary.
|
||||||
//
|
//
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// 0 or a positive number - a value that the elements in the |real_data_out|
|
// 0 or a positive number - a value that the elements in the `real_data_out`
|
||||||
// should be shifted left with in order to get
|
// should be shifted left with in order to get
|
||||||
// correct physical values.
|
// correct physical values.
|
||||||
// -1 - Error with bad arguments (null pointers).
|
// -1 - Error with bad arguments (null pointers).
|
||||||
|
|||||||
@ -166,7 +166,7 @@ int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, size_t length);
|
|||||||
// - vector : 16-bit input vector.
|
// - vector : 16-bit input vector.
|
||||||
// - length : Number of samples in vector.
|
// - length : Number of samples in vector.
|
||||||
//
|
//
|
||||||
// Return value : Maximum sample value in |vector|.
|
// Return value : Maximum sample value in `vector`.
|
||||||
typedef int16_t (*MaxValueW16)(const int16_t* vector, size_t length);
|
typedef int16_t (*MaxValueW16)(const int16_t* vector, size_t length);
|
||||||
extern const MaxValueW16 WebRtcSpl_MaxValueW16;
|
extern const MaxValueW16 WebRtcSpl_MaxValueW16;
|
||||||
int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, size_t length);
|
int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, size_t length);
|
||||||
@ -183,7 +183,7 @@ int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, size_t length);
|
|||||||
// - vector : 32-bit input vector.
|
// - vector : 32-bit input vector.
|
||||||
// - length : Number of samples in vector.
|
// - length : Number of samples in vector.
|
||||||
//
|
//
|
||||||
// Return value : Maximum sample value in |vector|.
|
// Return value : Maximum sample value in `vector`.
|
||||||
typedef int32_t (*MaxValueW32)(const int32_t* vector, size_t length);
|
typedef int32_t (*MaxValueW32)(const int32_t* vector, size_t length);
|
||||||
extern const MaxValueW32 WebRtcSpl_MaxValueW32;
|
extern const MaxValueW32 WebRtcSpl_MaxValueW32;
|
||||||
int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, size_t length);
|
int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, size_t length);
|
||||||
@ -200,7 +200,7 @@ int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, size_t length);
|
|||||||
// - vector : 16-bit input vector.
|
// - vector : 16-bit input vector.
|
||||||
// - length : Number of samples in vector.
|
// - length : Number of samples in vector.
|
||||||
//
|
//
|
||||||
// Return value : Minimum sample value in |vector|.
|
// Return value : Minimum sample value in `vector`.
|
||||||
typedef int16_t (*MinValueW16)(const int16_t* vector, size_t length);
|
typedef int16_t (*MinValueW16)(const int16_t* vector, size_t length);
|
||||||
extern const MinValueW16 WebRtcSpl_MinValueW16;
|
extern const MinValueW16 WebRtcSpl_MinValueW16;
|
||||||
int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, size_t length);
|
int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, size_t length);
|
||||||
@ -217,7 +217,7 @@ int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, size_t length);
|
|||||||
// - vector : 32-bit input vector.
|
// - vector : 32-bit input vector.
|
||||||
// - length : Number of samples in vector.
|
// - length : Number of samples in vector.
|
||||||
//
|
//
|
||||||
// Return value : Minimum sample value in |vector|.
|
// Return value : Minimum sample value in `vector`.
|
||||||
typedef int32_t (*MinValueW32)(const int32_t* vector, size_t length);
|
typedef int32_t (*MinValueW32)(const int32_t* vector, size_t length);
|
||||||
extern const MinValueW32 WebRtcSpl_MinValueW32;
|
extern const MinValueW32 WebRtcSpl_MinValueW32;
|
||||||
int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, size_t length);
|
int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, size_t length);
|
||||||
@ -234,8 +234,8 @@ int32_t WebRtcSpl_MinValueW32_mips(const int32_t* vector, size_t length);
|
|||||||
// - vector : 16-bit input vector.
|
// - vector : 16-bit input vector.
|
||||||
// - length : Number of samples in vector.
|
// - length : Number of samples in vector.
|
||||||
// Ouput:
|
// Ouput:
|
||||||
// - max_val : Maximum sample value in |vector|.
|
// - max_val : Maximum sample value in `vector`.
|
||||||
// - min_val : Minimum sample value in |vector|.
|
// - min_val : Minimum sample value in `vector`.
|
||||||
void WebRtcSpl_MinMaxW16(const int16_t* vector,
|
void WebRtcSpl_MinMaxW16(const int16_t* vector,
|
||||||
size_t length,
|
size_t length,
|
||||||
int16_t* min_val,
|
int16_t* min_val,
|
||||||
@ -426,7 +426,7 @@ void WebRtcSpl_AffineTransformVector(int16_t* out_vector,
|
|||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - in_vector : Vector to calculate autocorrelation upon
|
// - in_vector : Vector to calculate autocorrelation upon
|
||||||
// - in_vector_length : Length (in samples) of |vector|
|
// - in_vector_length : Length (in samples) of `vector`
|
||||||
// - order : The order up to which the autocorrelation should be
|
// - order : The order up to which the autocorrelation should be
|
||||||
// calculated
|
// calculated
|
||||||
//
|
//
|
||||||
@ -438,7 +438,7 @@ void WebRtcSpl_AffineTransformVector(int16_t* out_vector,
|
|||||||
// - scale : The number of left shifts required to obtain the
|
// - scale : The number of left shifts required to obtain the
|
||||||
// auto-correlation in Q0
|
// auto-correlation in Q0
|
||||||
//
|
//
|
||||||
// Return value : Number of samples in |result|, i.e. (order+1)
|
// Return value : Number of samples in `result`, i.e. (order+1)
|
||||||
size_t WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
|
size_t WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
|
||||||
size_t in_vector_length,
|
size_t in_vector_length,
|
||||||
size_t order,
|
size_t order,
|
||||||
@ -449,7 +449,7 @@ size_t WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
|
|||||||
// does NOT use the 64 bit class
|
// does NOT use the 64 bit class
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - auto_corr : Vector with autocorrelation values of length >= |order|+1
|
// - auto_corr : Vector with autocorrelation values of length >= `order`+1
|
||||||
// - order : The LPC filter order (support up to order 20)
|
// - order : The LPC filter order (support up to order 20)
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
@ -462,7 +462,7 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* auto_corr,
|
|||||||
int16_t* refl_coef,
|
int16_t* refl_coef,
|
||||||
size_t order);
|
size_t order);
|
||||||
|
|
||||||
// Converts reflection coefficients |refl_coef| to LPC coefficients |lpc_coef|.
|
// Converts reflection coefficients `refl_coef` to LPC coefficients `lpc_coef`.
|
||||||
// This version is a 16 bit operation.
|
// This version is a 16 bit operation.
|
||||||
//
|
//
|
||||||
// NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a
|
// NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a
|
||||||
@ -472,7 +472,7 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* auto_corr,
|
|||||||
// Input:
|
// Input:
|
||||||
// - refl_coef : Reflection coefficients in Q15 that should be converted
|
// - refl_coef : Reflection coefficients in Q15 that should be converted
|
||||||
// to LPC coefficients
|
// to LPC coefficients
|
||||||
// - use_order : Number of coefficients in |refl_coef|
|
// - use_order : Number of coefficients in `refl_coef`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - lpc_coef : LPC coefficients in Q12
|
// - lpc_coef : LPC coefficients in Q12
|
||||||
@ -480,14 +480,14 @@ void WebRtcSpl_ReflCoefToLpc(const int16_t* refl_coef,
|
|||||||
int use_order,
|
int use_order,
|
||||||
int16_t* lpc_coef);
|
int16_t* lpc_coef);
|
||||||
|
|
||||||
// Converts LPC coefficients |lpc_coef| to reflection coefficients |refl_coef|.
|
// Converts LPC coefficients `lpc_coef` to reflection coefficients `refl_coef`.
|
||||||
// This version is a 16 bit operation.
|
// This version is a 16 bit operation.
|
||||||
// The conversion is implemented by the step-down algorithm.
|
// The conversion is implemented by the step-down algorithm.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - lpc_coef : LPC coefficients in Q12, that should be converted to
|
// - lpc_coef : LPC coefficients in Q12, that should be converted to
|
||||||
// reflection coefficients
|
// reflection coefficients
|
||||||
// - use_order : Number of coefficients in |lpc_coef|
|
// - use_order : Number of coefficients in `lpc_coef`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - refl_coef : Reflection coefficients in Q15.
|
// - refl_coef : Reflection coefficients in Q15.
|
||||||
@ -508,24 +508,24 @@ void WebRtcSpl_AutoCorrToReflCoef(const int32_t* auto_corr,
|
|||||||
int16_t* refl_coef);
|
int16_t* refl_coef);
|
||||||
|
|
||||||
// The functions (with related pointer) calculate the cross-correlation between
|
// The functions (with related pointer) calculate the cross-correlation between
|
||||||
// two sequences |seq1| and |seq2|.
|
// two sequences `seq1` and `seq2`.
|
||||||
// |seq1| is fixed and |seq2| slides as the pointer is increased with the
|
// `seq1` is fixed and `seq2` slides as the pointer is increased with the
|
||||||
// amount |step_seq2|. Note the arguments should obey the relationship:
|
// amount `step_seq2`. Note the arguments should obey the relationship:
|
||||||
// |dim_seq| - 1 + |step_seq2| * (|dim_cross_correlation| - 1) <
|
// `dim_seq` - 1 + `step_seq2` * (`dim_cross_correlation` - 1) <
|
||||||
// buffer size of |seq2|
|
// buffer size of `seq2`
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - seq1 : First sequence (fixed throughout the correlation)
|
// - seq1 : First sequence (fixed throughout the correlation)
|
||||||
// - seq2 : Second sequence (slides |step_vector2| for each
|
// - seq2 : Second sequence (slides `step_vector2` for each
|
||||||
// new correlation)
|
// new correlation)
|
||||||
// - dim_seq : Number of samples to use in the cross-correlation
|
// - dim_seq : Number of samples to use in the cross-correlation
|
||||||
// - dim_cross_correlation : Number of cross-correlations to calculate (the
|
// - dim_cross_correlation : Number of cross-correlations to calculate (the
|
||||||
// start position for |vector2| is updated for each
|
// start position for `vector2` is updated for each
|
||||||
// new one)
|
// new one)
|
||||||
// - right_shifts : Number of right bit shifts to use. This will
|
// - right_shifts : Number of right bit shifts to use. This will
|
||||||
// become the output Q-domain.
|
// become the output Q-domain.
|
||||||
// - step_seq2 : How many (positive or negative) steps the
|
// - step_seq2 : How many (positive or negative) steps the
|
||||||
// |vector2| pointer should be updated for each new
|
// `vector2` pointer should be updated for each new
|
||||||
// cross-correlation value.
|
// cross-correlation value.
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
@ -575,11 +575,11 @@ void WebRtcSpl_CrossCorrelation_mips(int32_t* cross_correlation,
|
|||||||
void WebRtcSpl_GetHanningWindow(int16_t* window, size_t size);
|
void WebRtcSpl_GetHanningWindow(int16_t* window, size_t size);
|
||||||
|
|
||||||
// Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector
|
// Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector
|
||||||
// |in_vector|. Input and output values are in Q15.
|
// `in_vector`. Input and output values are in Q15.
|
||||||
//
|
//
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// - in_vector : Values to calculate sqrt(1 - x^2) of
|
// - in_vector : Values to calculate sqrt(1 - x^2) of
|
||||||
// - vector_length : Length of vector |in_vector|
|
// - vector_length : Length of vector `in_vector`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Output values in Q15
|
// - out_vector : Output values in Q15
|
||||||
@ -667,9 +667,9 @@ void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
|
|||||||
// Input:
|
// Input:
|
||||||
// - data_in : Input samples (state in positions
|
// - data_in : Input samples (state in positions
|
||||||
// data_in[-order] .. data_in[-1])
|
// data_in[-order] .. data_in[-1])
|
||||||
// - data_in_length : Number of samples in |data_in| to be filtered.
|
// - data_in_length : Number of samples in `data_in` to be filtered.
|
||||||
// This must be at least
|
// This must be at least
|
||||||
// |delay| + |factor|*(|out_vector_length|-1) + 1)
|
// `delay` + `factor`*(`out_vector_length`-1) + 1)
|
||||||
// - data_out_length : Number of down sampled samples desired
|
// - data_out_length : Number of down sampled samples desired
|
||||||
// - coefficients : Filter coefficients (in Q12)
|
// - coefficients : Filter coefficients (in Q12)
|
||||||
// - coefficients_length: Number of coefficients (order+1)
|
// - coefficients_length: Number of coefficients (order+1)
|
||||||
@ -677,7 +677,7 @@ void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
|
|||||||
// - delay : Delay of filter (compensated for in out_vector)
|
// - delay : Delay of filter (compensated for in out_vector)
|
||||||
// Output:
|
// Output:
|
||||||
// - data_out : Filtered samples
|
// - data_out : Filtered samples
|
||||||
// Return value : 0 if OK, -1 if |in_vector| is too short
|
// Return value : 0 if OK, -1 if `in_vector` is too short
|
||||||
typedef int (*DownsampleFast)(const int16_t* data_in,
|
typedef int (*DownsampleFast)(const int16_t* data_in,
|
||||||
size_t data_in_length,
|
size_t data_in_length,
|
||||||
int16_t* data_out,
|
int16_t* data_out,
|
||||||
@ -723,12 +723,12 @@ int WebRtcSpl_DownsampleFast_mips(const int16_t* data_in,
|
|||||||
int WebRtcSpl_ComplexFFT(int16_t vector[], int stages, int mode);
|
int WebRtcSpl_ComplexFFT(int16_t vector[], int stages, int mode);
|
||||||
int WebRtcSpl_ComplexIFFT(int16_t vector[], int stages, int mode);
|
int WebRtcSpl_ComplexIFFT(int16_t vector[], int stages, int mode);
|
||||||
|
|
||||||
// Treat a 16-bit complex data buffer |complex_data| as an array of 32-bit
|
// Treat a 16-bit complex data buffer `complex_data` as an array of 32-bit
|
||||||
// values, and swap elements whose indexes are bit-reverses of each other.
|
// values, and swap elements whose indexes are bit-reverses of each other.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - complex_data : Complex data buffer containing 2^|stages| real
|
// - complex_data : Complex data buffer containing 2^`stages` real
|
||||||
// elements interleaved with 2^|stages| imaginary
|
// elements interleaved with 2^`stages` imaginary
|
||||||
// elements: [Re Im Re Im Re Im....]
|
// elements: [Re Im Re Im Re Im....]
|
||||||
// - stages : Number of FFT stages. Must be at least 3 and at most
|
// - stages : Number of FFT stages. Must be at least 3 and at most
|
||||||
// 10, since the table WebRtcSpl_kSinTable1024[] is 1024
|
// 10, since the table WebRtcSpl_kSinTable1024[] is 1024
|
||||||
@ -938,7 +938,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// WebRtcSpl_AddSatW32(...)
|
// WebRtcSpl_AddSatW32(...)
|
||||||
//
|
//
|
||||||
// Returns the result of a saturated 16-bit, respectively 32-bit, addition of
|
// Returns the result of a saturated 16-bit, respectively 32-bit, addition of
|
||||||
// the numbers specified by the |var1| and |var2| parameters.
|
// the numbers specified by the `var1` and `var2` parameters.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - var1 : Input variable 1
|
// - var1 : Input variable 1
|
||||||
@ -952,7 +952,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// WebRtcSpl_SubSatW32(...)
|
// WebRtcSpl_SubSatW32(...)
|
||||||
//
|
//
|
||||||
// Returns the result of a saturated 16-bit, respectively 32-bit, subtraction
|
// Returns the result of a saturated 16-bit, respectively 32-bit, subtraction
|
||||||
// of the numbers specified by the |var1| and |var2| parameters.
|
// of the numbers specified by the `var1` and `var2` parameters.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - var1 : Input variable 1
|
// - var1 : Input variable 1
|
||||||
@ -965,61 +965,61 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// WebRtcSpl_GetSizeInBits(...)
|
// WebRtcSpl_GetSizeInBits(...)
|
||||||
//
|
//
|
||||||
// Returns the # of bits that are needed at the most to represent the number
|
// Returns the # of bits that are needed at the most to represent the number
|
||||||
// specified by the |value| parameter.
|
// specified by the `value` parameter.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - value : Input value
|
// - value : Input value
|
||||||
//
|
//
|
||||||
// Return value : Number of bits needed to represent |value|
|
// Return value : Number of bits needed to represent `value`
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_NormW32(...)
|
// WebRtcSpl_NormW32(...)
|
||||||
//
|
//
|
||||||
// Norm returns the # of left shifts required to 32-bit normalize the 32-bit
|
// Norm returns the # of left shifts required to 32-bit normalize the 32-bit
|
||||||
// signed number specified by the |value| parameter.
|
// signed number specified by the `value` parameter.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - value : Input value
|
// - value : Input value
|
||||||
//
|
//
|
||||||
// Return value : Number of bit shifts needed to 32-bit normalize |value|
|
// Return value : Number of bit shifts needed to 32-bit normalize `value`
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_NormW16(...)
|
// WebRtcSpl_NormW16(...)
|
||||||
//
|
//
|
||||||
// Norm returns the # of left shifts required to 16-bit normalize the 16-bit
|
// Norm returns the # of left shifts required to 16-bit normalize the 16-bit
|
||||||
// signed number specified by the |value| parameter.
|
// signed number specified by the `value` parameter.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - value : Input value
|
// - value : Input value
|
||||||
//
|
//
|
||||||
// Return value : Number of bit shifts needed to 32-bit normalize |value|
|
// Return value : Number of bit shifts needed to 32-bit normalize `value`
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_NormU32(...)
|
// WebRtcSpl_NormU32(...)
|
||||||
//
|
//
|
||||||
// Norm returns the # of left shifts required to 32-bit normalize the unsigned
|
// Norm returns the # of left shifts required to 32-bit normalize the unsigned
|
||||||
// 32-bit number specified by the |value| parameter.
|
// 32-bit number specified by the `value` parameter.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - value : Input value
|
// - value : Input value
|
||||||
//
|
//
|
||||||
// Return value : Number of bit shifts needed to 32-bit normalize |value|
|
// Return value : Number of bit shifts needed to 32-bit normalize `value`
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_GetScalingSquare(...)
|
// WebRtcSpl_GetScalingSquare(...)
|
||||||
//
|
//
|
||||||
// Returns the # of bits required to scale the samples specified in the
|
// Returns the # of bits required to scale the samples specified in the
|
||||||
// |in_vector| parameter so that, if the squares of the samples are added the
|
// `in_vector` parameter so that, if the squares of the samples are added the
|
||||||
// # of times specified by the |times| parameter, the 32-bit addition will not
|
// # of times specified by the `times` parameter, the 32-bit addition will not
|
||||||
// overflow (result in int32_t).
|
// overflow (result in int32_t).
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - in_vector : Input vector to check scaling on
|
// - in_vector : Input vector to check scaling on
|
||||||
// - in_vector_length : Samples in |in_vector|
|
// - in_vector_length : Samples in `in_vector`
|
||||||
// - times : Number of additions to be performed
|
// - times : Number of additions to be performed
|
||||||
//
|
//
|
||||||
// Return value : Number of right bit shifts needed to avoid
|
// Return value : Number of right bit shifts needed to avoid
|
||||||
@ -1029,8 +1029,8 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_MemSetW16(...)
|
// WebRtcSpl_MemSetW16(...)
|
||||||
//
|
//
|
||||||
// Sets all the values in the int16_t vector |vector| of length
|
// Sets all the values in the int16_t vector `vector` of length
|
||||||
// |vector_length| to the specified value |set_value|
|
// `vector_length` to the specified value `set_value`
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - vector : Pointer to the int16_t vector
|
// - vector : Pointer to the int16_t vector
|
||||||
@ -1041,8 +1041,8 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_MemSetW32(...)
|
// WebRtcSpl_MemSetW32(...)
|
||||||
//
|
//
|
||||||
// Sets all the values in the int32_t vector |vector| of length
|
// Sets all the values in the int32_t vector `vector` of length
|
||||||
// |vector_length| to the specified value |set_value|
|
// `vector_length` to the specified value `set_value`
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - vector : Pointer to the int16_t vector
|
// - vector : Pointer to the int16_t vector
|
||||||
@ -1053,34 +1053,34 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_MemCpyReversedOrder(...)
|
// WebRtcSpl_MemCpyReversedOrder(...)
|
||||||
//
|
//
|
||||||
// Copies all the values from the source int16_t vector |in_vector| to a
|
// Copies all the values from the source int16_t vector `in_vector` to a
|
||||||
// destination int16_t vector |out_vector|. It is done in reversed order,
|
// destination int16_t vector `out_vector`. It is done in reversed order,
|
||||||
// meaning that the first sample of |in_vector| is copied to the last sample of
|
// meaning that the first sample of `in_vector` is copied to the last sample of
|
||||||
// the |out_vector|. The procedure continues until the last sample of
|
// the `out_vector`. The procedure continues until the last sample of
|
||||||
// |in_vector| has been copied to the first sample of |out_vector|. This
|
// `in_vector` has been copied to the first sample of `out_vector`. This
|
||||||
// creates a reversed vector. Used in e.g. prediction in iLBC.
|
// creates a reversed vector. Used in e.g. prediction in iLBC.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - in_vector : Pointer to the first sample in a int16_t vector
|
// - in_vector : Pointer to the first sample in a int16_t vector
|
||||||
// of length |length|
|
// of length `length`
|
||||||
// - vector_length : Number of elements to copy
|
// - vector_length : Number of elements to copy
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Pointer to the last sample in a int16_t vector
|
// - out_vector : Pointer to the last sample in a int16_t vector
|
||||||
// of length |length|
|
// of length `length`
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_CopyFromEndW16(...)
|
// WebRtcSpl_CopyFromEndW16(...)
|
||||||
//
|
//
|
||||||
// Copies the rightmost |samples| of |in_vector| (of length |in_vector_length|)
|
// Copies the rightmost `samples` of `in_vector` (of length `in_vector_length`)
|
||||||
// to the vector |out_vector|.
|
// to the vector `out_vector`.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - in_vector : Input vector
|
// - in_vector : Input vector
|
||||||
// - in_vector_length : Number of samples in |in_vector|
|
// - in_vector_length : Number of samples in `in_vector`
|
||||||
// - samples : Number of samples to extract (from right side)
|
// - samples : Number of samples to extract (from right side)
|
||||||
// from |in_vector|
|
// from `in_vector`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Vector with the requested samples
|
// - out_vector : Vector with the requested samples
|
||||||
@ -1115,7 +1115,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Pointer to the result vector (can be the same as
|
// - out_vector : Pointer to the result vector (can be the same as
|
||||||
// |in_vector|)
|
// `in_vector`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1133,7 +1133,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Pointer to the result vector (can be the same as
|
// - out_vector : Pointer to the result vector (can be the same as
|
||||||
// |in_vector|)
|
// `in_vector`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1145,11 +1145,11 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// Input:
|
// Input:
|
||||||
// - in_vector : Input vector
|
// - in_vector : Input vector
|
||||||
// - gain : Scaling gain
|
// - gain : Scaling gain
|
||||||
// - vector_length : Elements in the |in_vector|
|
// - vector_length : Elements in the `in_vector`
|
||||||
// - right_shifts : Number of right bit shifts applied
|
// - right_shifts : Number of right bit shifts applied
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Output vector (can be the same as |in_vector|)
|
// - out_vector : Output vector (can be the same as `in_vector`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1161,11 +1161,11 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// Input:
|
// Input:
|
||||||
// - in_vector : Input vector
|
// - in_vector : Input vector
|
||||||
// - gain : Scaling gain
|
// - gain : Scaling gain
|
||||||
// - vector_length : Elements in the |in_vector|
|
// - vector_length : Elements in the `in_vector`
|
||||||
// - right_shifts : Number of right bit shifts applied
|
// - right_shifts : Number of right bit shifts applied
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Output vector (can be the same as |in_vector|)
|
// - out_vector : Output vector (can be the same as `in_vector`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1200,10 +1200,10 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// should be set to the last value in the vector
|
// should be set to the last value in the vector
|
||||||
// - right_shifts : Number of right bit shift to be applied after the
|
// - right_shifts : Number of right bit shift to be applied after the
|
||||||
// multiplication
|
// multiplication
|
||||||
// - vector_length : Number of elements in |in_vector|
|
// - vector_length : Number of elements in `in_vector`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Output vector (can be same as |in_vector|)
|
// - out_vector : Output vector (can be same as `in_vector`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1217,10 +1217,10 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - window : Window vector.
|
// - window : Window vector.
|
||||||
// - right_shifts : Number of right bit shift to be applied after the
|
// - right_shifts : Number of right bit shift to be applied after the
|
||||||
// multiplication
|
// multiplication
|
||||||
// - vector_length : Number of elements in |in_vector|
|
// - vector_length : Number of elements in `in_vector`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Output vector (can be same as |in_vector|)
|
// - out_vector : Output vector (can be same as `in_vector`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1234,16 +1234,16 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - in_vector2 : Input vector 2
|
// - in_vector2 : Input vector 2
|
||||||
// - right_shifts : Number of right bit shift to be applied after the
|
// - right_shifts : Number of right bit shift to be applied after the
|
||||||
// multiplication
|
// multiplication
|
||||||
// - vector_length : Number of elements in |in_vector1| and |in_vector2|
|
// - vector_length : Number of elements in `in_vector1` and `in_vector2`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Output vector (can be same as |in_vector1|)
|
// - out_vector : Output vector (can be same as `in_vector1`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_AddAffineVectorToVector(...)
|
// WebRtcSpl_AddAffineVectorToVector(...)
|
||||||
//
|
//
|
||||||
// Adds an affine transformed vector to another vector |out_vector|, i.e,
|
// Adds an affine transformed vector to another vector `out_vector`, i.e,
|
||||||
// performs
|
// performs
|
||||||
// out_vector[k] += (in_vector[k]*gain+add_constant)>>right_shifts
|
// out_vector[k] += (in_vector[k]*gain+add_constant)>>right_shifts
|
||||||
//
|
//
|
||||||
@ -1253,7 +1253,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
|
// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
|
||||||
// but others can be used as well
|
// but others can be used as well
|
||||||
// - right_shifts : Number of right bit shifts (0-16)
|
// - right_shifts : Number of right bit shifts (0-16)
|
||||||
// - vector_length : Number of samples in |in_vector| and |out_vector|
|
// - vector_length : Number of samples in `in_vector` and `out_vector`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Vector with the output
|
// - out_vector : Vector with the output
|
||||||
@ -1271,7 +1271,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
|
// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
|
||||||
// but others can be used as well
|
// but others can be used as well
|
||||||
// - right_shifts : Number of right bit shifts (0-16)
|
// - right_shifts : Number of right bit shifts (0-16)
|
||||||
// - vector_length : Number of samples in |in_vector| and |out_vector|
|
// - vector_length : Number of samples in `in_vector` and `out_vector`
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_vector : Vector with the output
|
// - out_vector : Vector with the output
|
||||||
@ -1334,15 +1334,15 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - vector : Vector with the uniform values
|
// - vector : Vector with the uniform values
|
||||||
// - seed : Updated seed value
|
// - seed : Updated seed value
|
||||||
//
|
//
|
||||||
// Return value : Number of samples in vector, i.e., |vector_length|
|
// Return value : Number of samples in vector, i.e., `vector_length`
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebRtcSpl_Sqrt(...)
|
// WebRtcSpl_Sqrt(...)
|
||||||
//
|
//
|
||||||
// Returns the square root of the input value |value|. The precision of this
|
// Returns the square root of the input value `value`. The precision of this
|
||||||
// function is integer precision, i.e., sqrt(8) gives 2 as answer.
|
// function is integer precision, i.e., sqrt(8) gives 2 as answer.
|
||||||
// If |value| is a negative number then 0 is returned.
|
// If `value` is a negative number then 0 is returned.
|
||||||
//
|
//
|
||||||
// Algorithm:
|
// Algorithm:
|
||||||
//
|
//
|
||||||
@ -1362,9 +1362,9 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_DivU32U16(...)
|
// WebRtcSpl_DivU32U16(...)
|
||||||
//
|
//
|
||||||
// Divides a uint32_t |num| by a uint16_t |den|.
|
// Divides a uint32_t `num` by a uint16_t `den`.
|
||||||
//
|
//
|
||||||
// If |den|==0, (uint32_t)0xFFFFFFFF is returned.
|
// If `den`==0, (uint32_t)0xFFFFFFFF is returned.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - num : Numerator
|
// - num : Numerator
|
||||||
@ -1377,9 +1377,9 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_DivW32W16(...)
|
// WebRtcSpl_DivW32W16(...)
|
||||||
//
|
//
|
||||||
// Divides a int32_t |num| by a int16_t |den|.
|
// Divides a int32_t `num` by a int16_t `den`.
|
||||||
//
|
//
|
||||||
// If |den|==0, (int32_t)0x7FFFFFFF is returned.
|
// If `den`==0, (int32_t)0x7FFFFFFF is returned.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - num : Numerator
|
// - num : Numerator
|
||||||
@ -1392,10 +1392,10 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_DivW32W16ResW16(...)
|
// WebRtcSpl_DivW32W16ResW16(...)
|
||||||
//
|
//
|
||||||
// Divides a int32_t |num| by a int16_t |den|, assuming that the
|
// Divides a int32_t `num` by a int16_t `den`, assuming that the
|
||||||
// result is less than 32768, otherwise an unpredictable result will occur.
|
// result is less than 32768, otherwise an unpredictable result will occur.
|
||||||
//
|
//
|
||||||
// If |den|==0, (int16_t)0x7FFF is returned.
|
// If `den`==0, (int16_t)0x7FFF is returned.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - num : Numerator
|
// - num : Numerator
|
||||||
@ -1408,7 +1408,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_DivResultInQ31(...)
|
// WebRtcSpl_DivResultInQ31(...)
|
||||||
//
|
//
|
||||||
// Divides a int32_t |num| by a int16_t |den|, assuming that the
|
// Divides a int32_t `num` by a int16_t `den`, assuming that the
|
||||||
// absolute value of the denominator is larger than the numerator, otherwise
|
// absolute value of the denominator is larger than the numerator, otherwise
|
||||||
// an unpredictable result will occur.
|
// an unpredictable result will occur.
|
||||||
//
|
//
|
||||||
@ -1422,7 +1422,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_DivW32HiLow(...)
|
// WebRtcSpl_DivW32HiLow(...)
|
||||||
//
|
//
|
||||||
// Divides a int32_t |num| by a denominator in hi, low format. The
|
// Divides a int32_t `num` by a denominator in hi, low format. The
|
||||||
// absolute value of the denominator has to be larger (or equal to) the
|
// absolute value of the denominator has to be larger (or equal to) the
|
||||||
// numerator.
|
// numerator.
|
||||||
//
|
//
|
||||||
@ -1447,7 +1447,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - scale_factor : Number of left bit shifts needed to get the physical
|
// - scale_factor : Number of left bit shifts needed to get the physical
|
||||||
// energy value, i.e, to get the Q0 value
|
// energy value, i.e, to get the Q0 value
|
||||||
//
|
//
|
||||||
// Return value : Energy value in Q(-|scale_factor|)
|
// Return value : Energy value in Q(-`scale_factor`)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1458,15 +1458,15 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// Input:
|
// Input:
|
||||||
// - ar_coef : AR-coefficient vector (values in Q12),
|
// - ar_coef : AR-coefficient vector (values in Q12),
|
||||||
// ar_coef[0] must be 4096.
|
// ar_coef[0] must be 4096.
|
||||||
// - ar_coef_length : Number of coefficients in |ar_coef|.
|
// - ar_coef_length : Number of coefficients in `ar_coef`.
|
||||||
// - in_vector : Vector to be filtered.
|
// - in_vector : Vector to be filtered.
|
||||||
// - in_vector_length : Number of samples in |in_vector|.
|
// - in_vector_length : Number of samples in `in_vector`.
|
||||||
// - filter_state : Current state (higher part) of the filter.
|
// - filter_state : Current state (higher part) of the filter.
|
||||||
// - filter_state_length : Length (in samples) of |filter_state|.
|
// - filter_state_length : Length (in samples) of `filter_state`.
|
||||||
// - filter_state_low : Current state (lower part) of the filter.
|
// - filter_state_low : Current state (lower part) of the filter.
|
||||||
// - filter_state_low_length : Length (in samples) of |filter_state_low|.
|
// - filter_state_low_length : Length (in samples) of `filter_state_low`.
|
||||||
// - out_vector_low_length : Maximum length (in samples) of
|
// - out_vector_low_length : Maximum length (in samples) of
|
||||||
// |out_vector_low|.
|
// `out_vector_low`.
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - filter_state : Updated state (upper part) vector.
|
// - filter_state : Updated state (upper part) vector.
|
||||||
@ -1476,7 +1476,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - out_vector_low : Vector containing the lower part of the
|
// - out_vector_low : Vector containing the lower part of the
|
||||||
// filtered values.
|
// filtered values.
|
||||||
//
|
//
|
||||||
// Return value : Number of samples in the |out_vector|.
|
// Return value : Number of samples in the `out_vector`.
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1484,11 +1484,11 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// Complex Inverse FFT
|
// Complex Inverse FFT
|
||||||
//
|
//
|
||||||
// Computes an inverse complex 2^|stages|-point FFT on the input vector, which
|
// Computes an inverse complex 2^`stages`-point FFT on the input vector, which
|
||||||
// is in bit-reversed order. The original content of the vector is destroyed in
|
// is in bit-reversed order. The original content of the vector is destroyed in
|
||||||
// the process, since the input is overwritten by the output, normal-ordered,
|
// the process, since the input is overwritten by the output, normal-ordered,
|
||||||
// FFT vector. With X as the input complex vector, y as the output complex
|
// FFT vector. With X as the input complex vector, y as the output complex
|
||||||
// vector and with M = 2^|stages|, the following is computed:
|
// vector and with M = 2^`stages`, the following is computed:
|
||||||
//
|
//
|
||||||
// M-1
|
// M-1
|
||||||
// y(k) = sum[X(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
|
// y(k) = sum[X(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
|
||||||
@ -1498,8 +1498,8 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// decimation-in-time algorithm with radix-2 butterfly technique.
|
// decimation-in-time algorithm with radix-2 butterfly technique.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - vector : In pointer to complex vector containing 2^|stages|
|
// - vector : In pointer to complex vector containing 2^`stages`
|
||||||
// real elements interleaved with 2^|stages| imaginary
|
// real elements interleaved with 2^`stages` imaginary
|
||||||
// elements.
|
// elements.
|
||||||
// [ReImReImReIm....]
|
// [ReImReImReIm....]
|
||||||
// The elements are in Q(-scale) domain, see more on Return
|
// The elements are in Q(-scale) domain, see more on Return
|
||||||
@ -1518,10 +1518,10 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// - vector : Out pointer to the FFT vector (the same as input).
|
// - vector : Out pointer to the FFT vector (the same as input).
|
||||||
//
|
//
|
||||||
// Return Value : The scale value that tells the number of left bit shifts
|
// Return Value : The scale value that tells the number of left bit shifts
|
||||||
// that the elements in the |vector| should be shifted with
|
// that the elements in the `vector` should be shifted with
|
||||||
// in order to get Q0 values, i.e. the physically correct
|
// in order to get Q0 values, i.e. the physically correct
|
||||||
// values. The scale parameter is always 0 or positive,
|
// values. The scale parameter is always 0 or positive,
|
||||||
// except if N>1024 (|stages|>10), which returns a scale
|
// except if N>1024 (`stages`>10), which returns a scale
|
||||||
// value of -1, indicating error.
|
// value of -1, indicating error.
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -1530,11 +1530,11 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
//
|
//
|
||||||
// Complex FFT
|
// Complex FFT
|
||||||
//
|
//
|
||||||
// Computes a complex 2^|stages|-point FFT on the input vector, which is in
|
// Computes a complex 2^`stages`-point FFT on the input vector, which is in
|
||||||
// bit-reversed order. The original content of the vector is destroyed in
|
// bit-reversed order. The original content of the vector is destroyed in
|
||||||
// the process, since the input is overwritten by the output, normal-ordered,
|
// the process, since the input is overwritten by the output, normal-ordered,
|
||||||
// FFT vector. With x as the input complex vector, Y as the output complex
|
// FFT vector. With x as the input complex vector, Y as the output complex
|
||||||
// vector and with M = 2^|stages|, the following is computed:
|
// vector and with M = 2^`stages`, the following is computed:
|
||||||
//
|
//
|
||||||
// M-1
|
// M-1
|
||||||
// Y(k) = 1/M * sum[x(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
|
// Y(k) = 1/M * sum[x(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
|
||||||
@ -1549,8 +1549,8 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
|||||||
// accuracy.
|
// accuracy.
|
||||||
//
|
//
|
||||||
// Input:
|
// Input:
|
||||||
// - vector : In pointer to complex vector containing 2^|stages| real
|
// - vector : In pointer to complex vector containing 2^`stages` real
|
||||||
// elements interleaved with 2^|stages| imaginary elements.
|
// elements interleaved with 2^`stages` imaginary elements.
|
||||||
// [ReImReImReIm....]
|
// [ReImReImReIm....]
|
||||||
// The output is in the Q0 domain.
|
// The output is in the Q0 domain.
|
||||||
//
|
//
|
||||||
|
|||||||
@ -482,13 +482,13 @@ TEST(SplTest, FilterTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MA filters.
|
// MA filters.
|
||||||
// Note that the input data has |kFilterOrder| states before the actual
|
// Note that the input data has `kFilterOrder` states before the actual
|
||||||
// data (one sample).
|
// data (one sample).
|
||||||
WebRtcSpl_FilterMAFastQ12(&data_in[kFilterOrder], data_out, B,
|
WebRtcSpl_FilterMAFastQ12(&data_in[kFilterOrder], data_out, B,
|
||||||
kFilterOrder + 1, 1);
|
kFilterOrder + 1, 1);
|
||||||
EXPECT_EQ(0, data_out[0]);
|
EXPECT_EQ(0, data_out[0]);
|
||||||
// AR filters.
|
// AR filters.
|
||||||
// Note that the output data has |kFilterOrder| states before the actual
|
// Note that the output data has `kFilterOrder` states before the actual
|
||||||
// data (one sample).
|
// data (one sample).
|
||||||
WebRtcSpl_FilterARFastQ12(data_in, &data_out[kFilterOrder], A,
|
WebRtcSpl_FilterARFastQ12(data_in, &data_out[kFilterOrder], A,
|
||||||
kFilterOrder + 1, 1);
|
kFilterOrder + 1, 1);
|
||||||
@ -639,11 +639,11 @@ TEST(SplTest, Resample48WithSaturationTest) {
|
|||||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
|
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
|
||||||
32767, 32767, 32767, 32767, 32767, 32767, 32767};
|
32767, 32767, 32767, 32767, 32767, 32767, 32767};
|
||||||
|
|
||||||
// All values in |out_vector| should be |kRefValue32kHz|.
|
// All values in `out_vector` should be `kRefValue32kHz`.
|
||||||
const int32_t kRefValue32kHz1 = -1077493760;
|
const int32_t kRefValue32kHz1 = -1077493760;
|
||||||
const int32_t kRefValue32kHz2 = 1077493645;
|
const int32_t kRefValue32kHz2 = 1077493645;
|
||||||
|
|
||||||
// After bit shift with saturation, |out_vector_w16| is saturated.
|
// After bit shift with saturation, `out_vector_w16` is saturated.
|
||||||
|
|
||||||
const int16_t kRefValue16kHz1 = -32768;
|
const int16_t kRefValue16kHz1 = -32768;
|
||||||
const int16_t kRefValue16kHz2 = 32767;
|
const int16_t kRefValue16kHz2 = 32767;
|
||||||
|
|||||||
@ -41,7 +41,7 @@ static const uint16_t WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
|
|||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - out_data : Output data sequence (Q10), length equal to
|
// - out_data : Output data sequence (Q10), length equal to
|
||||||
// |data_length|
|
// `data_length`
|
||||||
//
|
//
|
||||||
|
|
||||||
static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
||||||
@ -50,28 +50,30 @@ static void WebRtcSpl_AllPassQMF(int32_t* in_data,
|
|||||||
const uint16_t* filter_coefficients,
|
const uint16_t* filter_coefficients,
|
||||||
int32_t* filter_state)
|
int32_t* filter_state)
|
||||||
{
|
{
|
||||||
// The procedure is to filter the input with three first order all pass filters
|
// The procedure is to filter the input with three first order all pass
|
||||||
// (cascade operations).
|
// filters (cascade operations).
|
||||||
//
|
//
|
||||||
// a_3 + q^-1 a_2 + q^-1 a_1 + q^-1
|
// a_3 + q^-1 a_2 + q^-1 a_1 + q^-1
|
||||||
// y[n] = ----------- ----------- ----------- x[n]
|
// y[n] = ----------- ----------- ----------- x[n]
|
||||||
// 1 + a_3q^-1 1 + a_2q^-1 1 + a_1q^-1
|
// 1 + a_3q^-1 1 + a_2q^-1 1 + a_1q^-1
|
||||||
//
|
//
|
||||||
// The input vector |filter_coefficients| includes these three filter coefficients.
|
// The input vector `filter_coefficients` includes these three filter
|
||||||
// The filter state contains the in_data state, in_data[-1], followed by
|
// coefficients. The filter state contains the in_data state, in_data[-1],
|
||||||
// the out_data state, out_data[-1]. This is repeated for each cascade.
|
// followed by the out_data state, out_data[-1]. This is repeated for each
|
||||||
// The first cascade filter will filter the |in_data| and store the output in
|
// cascade. The first cascade filter will filter the `in_data` and store
|
||||||
// |out_data|. The second will the take the |out_data| as input and make an
|
// the output in `out_data`. The second will the take the `out_data` as
|
||||||
// intermediate storage in |in_data|, to save memory. The third, and final, cascade
|
// input and make an intermediate storage in `in_data`, to save memory. The
|
||||||
// filter operation takes the |in_data| (which is the output from the previous cascade
|
// third, and final, cascade filter operation takes the `in_data` (which is
|
||||||
// filter) and store the output in |out_data|.
|
// the output from the previous cascade filter) and store the output in
|
||||||
// Note that the input vector values are changed during the process.
|
// `out_data`. Note that the input vector values are changed during the
|
||||||
|
// process.
|
||||||
size_t k;
|
size_t k;
|
||||||
int32_t diff;
|
int32_t diff;
|
||||||
// First all-pass cascade; filter from in_data to out_data.
|
// First all-pass cascade; filter from in_data to out_data.
|
||||||
|
|
||||||
// Let y_i[n] indicate the output of cascade filter i (with filter coefficient a_i) at
|
// Let y_i[n] indicate the output of cascade filter i (with filter
|
||||||
// vector position n. Then the final output will be y[n] = y_3[n]
|
// coefficient a_i) at vector position n. Then the final output will be
|
||||||
|
// y[n] = y_3[n]
|
||||||
|
|
||||||
// First loop, use the states stored in memory.
|
// First loop, use the states stored in memory.
|
||||||
// "diff" should be safe from wrap around since max values are 2^25
|
// "diff" should be safe from wrap around since max values are 2^25
|
||||||
|
|||||||
@ -23,12 +23,12 @@ SmoothingFilterImpl::SmoothingFilterImpl(int init_time_ms)
|
|||||||
: init_time_ms_(init_time_ms),
|
: init_time_ms_(init_time_ms),
|
||||||
// Duing the initalization time, we use an increasing alpha. Specifically,
|
// Duing the initalization time, we use an increasing alpha. Specifically,
|
||||||
// alpha(n) = exp(-powf(init_factor_, n)),
|
// alpha(n) = exp(-powf(init_factor_, n)),
|
||||||
// where |init_factor_| is chosen such that
|
// where `init_factor_` is chosen such that
|
||||||
// alpha(init_time_ms_) = exp(-1.0f / init_time_ms_),
|
// alpha(init_time_ms_) = exp(-1.0f / init_time_ms_),
|
||||||
init_factor_(init_time_ms_ == 0
|
init_factor_(init_time_ms_ == 0
|
||||||
? 0.0f
|
? 0.0f
|
||||||
: powf(init_time_ms_, -1.0f / init_time_ms_)),
|
: powf(init_time_ms_, -1.0f / init_time_ms_)),
|
||||||
// |init_const_| is to a factor to help the calculation during
|
// `init_const_` is to a factor to help the calculation during
|
||||||
// initialization phase.
|
// initialization phase.
|
||||||
init_const_(init_time_ms_ == 0
|
init_const_(init_time_ms_ == 0
|
||||||
? 0.0f
|
? 0.0f
|
||||||
@ -57,7 +57,7 @@ void SmoothingFilterImpl::AddSample(float sample) {
|
|||||||
|
|
||||||
absl::optional<float> SmoothingFilterImpl::GetAverage() {
|
absl::optional<float> SmoothingFilterImpl::GetAverage() {
|
||||||
if (!init_end_time_ms_) {
|
if (!init_end_time_ms_) {
|
||||||
// |init_end_time_ms_| undefined since we have not received any sample.
|
// `init_end_time_ms_` undefined since we have not received any sample.
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
ExtrapolateLastSample(rtc::TimeMillis());
|
ExtrapolateLastSample(rtc::TimeMillis());
|
||||||
@ -84,17 +84,17 @@ void SmoothingFilterImpl::ExtrapolateLastSample(int64_t time_ms) {
|
|||||||
|
|
||||||
if (time_ms <= *init_end_time_ms_) {
|
if (time_ms <= *init_end_time_ms_) {
|
||||||
// Current update is to be made during initialization phase.
|
// Current update is to be made during initialization phase.
|
||||||
// We update the state as if the |alpha| has been increased according
|
// We update the state as if the `alpha` has been increased according
|
||||||
// alpha(n) = exp(-powf(init_factor_, n)),
|
// alpha(n) = exp(-powf(init_factor_, n)),
|
||||||
// where n is the time (in millisecond) since the first sample received.
|
// where n is the time (in millisecond) since the first sample received.
|
||||||
// With algebraic derivation as shown in the Appendix, we can find that the
|
// With algebraic derivation as shown in the Appendix, we can find that the
|
||||||
// state can be updated in a similar manner as if alpha is a constant,
|
// state can be updated in a similar manner as if alpha is a constant,
|
||||||
// except for a different multiplier.
|
// except for a different multiplier.
|
||||||
if (init_time_ms_ == 0) {
|
if (init_time_ms_ == 0) {
|
||||||
// This means |init_factor_| = 0.
|
// This means `init_factor_` = 0.
|
||||||
multiplier = 0.0f;
|
multiplier = 0.0f;
|
||||||
} else if (init_time_ms_ == 1) {
|
} else if (init_time_ms_ == 1) {
|
||||||
// This means |init_factor_| = 1.
|
// This means `init_factor_` = 1.
|
||||||
multiplier = std::exp(last_state_time_ms_ - time_ms);
|
multiplier = std::exp(last_state_time_ms_ - time_ms);
|
||||||
} else {
|
} else {
|
||||||
multiplier = std::exp(
|
multiplier = std::exp(
|
||||||
|
|||||||
@ -33,13 +33,13 @@ class SmoothingFilter {
|
|||||||
// assumed to equal the last received sample.
|
// assumed to equal the last received sample.
|
||||||
class SmoothingFilterImpl final : public SmoothingFilter {
|
class SmoothingFilterImpl final : public SmoothingFilter {
|
||||||
public:
|
public:
|
||||||
// |init_time_ms| is initialization time. It defines a period starting from
|
// `init_time_ms` is initialization time. It defines a period starting from
|
||||||
// the arriving time of the first sample. During this period, the exponential
|
// the arriving time of the first sample. During this period, the exponential
|
||||||
// filter uses a varying time constant so that a smaller time constant will be
|
// filter uses a varying time constant so that a smaller time constant will be
|
||||||
// applied to the earlier samples. This is to allow the the filter to adapt to
|
// applied to the earlier samples. This is to allow the the filter to adapt to
|
||||||
// earlier samples quickly. After the initialization period, the time constant
|
// earlier samples quickly. After the initialization period, the time constant
|
||||||
// will be set to |init_time_ms| first and can be changed through
|
// will be set to `init_time_ms` first and can be changed through
|
||||||
// |SetTimeConstantMs|.
|
// `SetTimeConstantMs`.
|
||||||
explicit SmoothingFilterImpl(int init_time_ms);
|
explicit SmoothingFilterImpl(int init_time_ms);
|
||||||
|
|
||||||
SmoothingFilterImpl() = delete;
|
SmoothingFilterImpl() = delete;
|
||||||
|
|||||||
@ -34,7 +34,7 @@ struct SmoothingFilterStates {
|
|||||||
|
|
||||||
// This function does the following:
|
// This function does the following:
|
||||||
// 1. Add a sample to filter at current clock,
|
// 1. Add a sample to filter at current clock,
|
||||||
// 2. Advance the clock by |advance_time_ms|,
|
// 2. Advance the clock by `advance_time_ms`,
|
||||||
// 3. Get the output of both SmoothingFilter and verify that it equals to an
|
// 3. Get the output of both SmoothingFilter and verify that it equals to an
|
||||||
// expected value.
|
// expected value.
|
||||||
void CheckOutput(SmoothingFilterStates* states,
|
void CheckOutput(SmoothingFilterStates* states,
|
||||||
@ -141,7 +141,7 @@ TEST(SmoothingFilterTest, CannotChangeTimeConstantDuringInitialization) {
|
|||||||
SmoothingFilterStates states(kInitTimeMs);
|
SmoothingFilterStates states(kInitTimeMs);
|
||||||
states.smoothing_filter.AddSample(0.0);
|
states.smoothing_filter.AddSample(0.0);
|
||||||
|
|
||||||
// During initialization, |SetTimeConstantMs| does not take effect.
|
// During initialization, `SetTimeConstantMs` does not take effect.
|
||||||
states.fake_clock.AdvanceTime(TimeDelta::Millis(kInitTimeMs - 1));
|
states.fake_clock.AdvanceTime(TimeDelta::Millis(kInitTimeMs - 1));
|
||||||
states.smoothing_filter.AddSample(0.0);
|
states.smoothing_filter.AddSample(0.0);
|
||||||
|
|
||||||
@ -152,11 +152,11 @@ TEST(SmoothingFilterTest, CannotChangeTimeConstantDuringInitialization) {
|
|||||||
states.fake_clock.AdvanceTime(TimeDelta::Millis(1));
|
states.fake_clock.AdvanceTime(TimeDelta::Millis(1));
|
||||||
states.smoothing_filter.AddSample(0.0);
|
states.smoothing_filter.AddSample(0.0);
|
||||||
// When initialization finishes, the time constant should be come
|
// When initialization finishes, the time constant should be come
|
||||||
// |kInitTimeConstantMs|.
|
// `kInitTimeConstantMs`.
|
||||||
EXPECT_FLOAT_EQ(std::exp(-1.0f / kInitTimeMs),
|
EXPECT_FLOAT_EQ(std::exp(-1.0f / kInitTimeMs),
|
||||||
states.smoothing_filter.alpha());
|
states.smoothing_filter.alpha());
|
||||||
|
|
||||||
// After initialization, |SetTimeConstantMs| takes effect.
|
// After initialization, `SetTimeConstantMs` takes effect.
|
||||||
EXPECT_TRUE(states.smoothing_filter.SetTimeConstantMs(kInitTimeMs * 2));
|
EXPECT_TRUE(states.smoothing_filter.SetTimeConstantMs(kInitTimeMs * 2));
|
||||||
EXPECT_FLOAT_EQ(std::exp(-1.0f / (kInitTimeMs * 2)),
|
EXPECT_FLOAT_EQ(std::exp(-1.0f / (kInitTimeMs * 2)),
|
||||||
states.smoothing_filter.alpha());
|
states.smoothing_filter.alpha());
|
||||||
|
|||||||
@ -13,9 +13,9 @@
|
|||||||
//
|
//
|
||||||
// WebRtcSpl_SqrtFloor(...)
|
// WebRtcSpl_SqrtFloor(...)
|
||||||
//
|
//
|
||||||
// Returns the square root of the input value |value|. The precision of this
|
// Returns the square root of the input value `value`. The precision of this
|
||||||
// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
|
// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
|
||||||
// If |value| is a negative number then 0 is returned.
|
// If `value` is a negative number then 0 is returned.
|
||||||
//
|
//
|
||||||
// Algorithm:
|
// Algorithm:
|
||||||
//
|
//
|
||||||
|
|||||||
@ -54,7 +54,7 @@ int WebRtcVad_Init(VadInst* handle);
|
|||||||
// has not been initialized).
|
// has not been initialized).
|
||||||
int WebRtcVad_set_mode(VadInst* handle, int mode);
|
int WebRtcVad_set_mode(VadInst* handle, int mode);
|
||||||
|
|
||||||
// Calculates a VAD decision for the |audio_frame|. For valid sampling rates
|
// Calculates a VAD decision for the `audio_frame`. For valid sampling rates
|
||||||
// frame lengths, see the description of WebRtcVad_ValidRatesAndFrameLengths().
|
// frame lengths, see the description of WebRtcVad_ValidRatesAndFrameLengths().
|
||||||
//
|
//
|
||||||
// - handle [i/o] : VAD Instance. Needs to be initialized by
|
// - handle [i/o] : VAD Instance. Needs to be initialized by
|
||||||
@ -71,7 +71,7 @@ int WebRtcVad_Process(VadInst* handle,
|
|||||||
const int16_t* audio_frame,
|
const int16_t* audio_frame,
|
||||||
size_t frame_length);
|
size_t frame_length);
|
||||||
|
|
||||||
// Checks for valid combinations of |rate| and |frame_length|. We support 10,
|
// Checks for valid combinations of `rate` and `frame_length`. We support 10,
|
||||||
// 20 and 30 ms frames and the rates 8000, 16000 and 32000 Hz.
|
// 20 and 30 ms frames and the rates 8000, 16000 and 32000 Hz.
|
||||||
//
|
//
|
||||||
// - rate [i] : Sampling frequency (Hz).
|
// - rate [i] : Sampling frequency (Hz).
|
||||||
|
|||||||
@ -90,11 +90,11 @@ static const int16_t kOverHangMax2VAG[3] = { 9, 5, 3 };
|
|||||||
static const int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };
|
static const int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };
|
||||||
static const int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 };
|
static const int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 };
|
||||||
|
|
||||||
// Calculates the weighted average w.r.t. number of Gaussians. The |data| are
|
// Calculates the weighted average w.r.t. number of Gaussians. The `data` are
|
||||||
// updated with an |offset| before averaging.
|
// updated with an `offset` before averaging.
|
||||||
//
|
//
|
||||||
// - data [i/o] : Data to average.
|
// - data [i/o] : Data to average.
|
||||||
// - offset [i] : An offset added to |data|.
|
// - offset [i] : An offset added to `data`.
|
||||||
// - weights [i] : Weights used for averaging.
|
// - weights [i] : Weights used for averaging.
|
||||||
//
|
//
|
||||||
// returns : The weighted average.
|
// returns : The weighted average.
|
||||||
@ -124,7 +124,7 @@ static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
|
|||||||
// type of signal is most probable.
|
// type of signal is most probable.
|
||||||
//
|
//
|
||||||
// - self [i/o] : Pointer to VAD instance
|
// - self [i/o] : Pointer to VAD instance
|
||||||
// - features [i] : Feature vector of length |kNumChannels|
|
// - features [i] : Feature vector of length `kNumChannels`
|
||||||
// = log10(energy in frequency band)
|
// = log10(energy in frequency band)
|
||||||
// - total_power [i] : Total power in audio frame.
|
// - total_power [i] : Total power in audio frame.
|
||||||
// - frame_length [i] : Number of input samples
|
// - frame_length [i] : Number of input samples
|
||||||
@ -183,10 +183,10 @@ static int16_t GmmProbability(VadInstT* self, int16_t* features,
|
|||||||
// H1: Speech
|
// H1: Speech
|
||||||
//
|
//
|
||||||
// We combine a global LRT with local tests, for each frequency sub-band,
|
// We combine a global LRT with local tests, for each frequency sub-band,
|
||||||
// here defined as |channel|.
|
// here defined as `channel`.
|
||||||
for (channel = 0; channel < kNumChannels; channel++) {
|
for (channel = 0; channel < kNumChannels; channel++) {
|
||||||
// For each channel we model the probability with a GMM consisting of
|
// For each channel we model the probability with a GMM consisting of
|
||||||
// |kNumGaussians|, with different means and standard deviations depending
|
// `kNumGaussians`, with different means and standard deviations depending
|
||||||
// on H0 or H1.
|
// on H0 or H1.
|
||||||
h0_test = 0;
|
h0_test = 0;
|
||||||
h1_test = 0;
|
h1_test = 0;
|
||||||
@ -234,7 +234,7 @@ static int16_t GmmProbability(VadInstT* self, int16_t* features,
|
|||||||
}
|
}
|
||||||
log_likelihood_ratio = shifts_h0 - shifts_h1;
|
log_likelihood_ratio = shifts_h0 - shifts_h1;
|
||||||
|
|
||||||
// Update |sum_log_likelihood_ratios| with spectrum weighting. This is
|
// Update `sum_log_likelihood_ratios` with spectrum weighting. This is
|
||||||
// used for the global VAD decision.
|
// used for the global VAD decision.
|
||||||
sum_log_likelihood_ratios +=
|
sum_log_likelihood_ratios +=
|
||||||
(int32_t) (log_likelihood_ratio * kSpectrumWeight[channel]);
|
(int32_t) (log_likelihood_ratio * kSpectrumWeight[channel]);
|
||||||
@ -326,7 +326,7 @@ static int16_t GmmProbability(VadInstT* self, int16_t* features,
|
|||||||
|
|
||||||
if (vadflag) {
|
if (vadflag) {
|
||||||
// Update speech mean vector:
|
// Update speech mean vector:
|
||||||
// |deltaS| = (x-mu)/sigma^2
|
// `deltaS` = (x-mu)/sigma^2
|
||||||
// sgprvec[k] = |speech_probability[k]| /
|
// sgprvec[k] = |speech_probability[k]| /
|
||||||
// (|speech_probability[0]| + |speech_probability[1]|)
|
// (|speech_probability[0]| + |speech_probability[1]|)
|
||||||
|
|
||||||
@ -409,35 +409,35 @@ static int16_t GmmProbability(VadInstT* self, int16_t* features,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Separate models if they are too close.
|
// Separate models if they are too close.
|
||||||
// |noise_global_mean| in Q14 (= Q7 * Q7).
|
// `noise_global_mean` in Q14 (= Q7 * Q7).
|
||||||
noise_global_mean = WeightedAverage(&self->noise_means[channel], 0,
|
noise_global_mean = WeightedAverage(&self->noise_means[channel], 0,
|
||||||
&kNoiseDataWeights[channel]);
|
&kNoiseDataWeights[channel]);
|
||||||
|
|
||||||
// |speech_global_mean| in Q14 (= Q7 * Q7).
|
// `speech_global_mean` in Q14 (= Q7 * Q7).
|
||||||
speech_global_mean = WeightedAverage(&self->speech_means[channel], 0,
|
speech_global_mean = WeightedAverage(&self->speech_means[channel], 0,
|
||||||
&kSpeechDataWeights[channel]);
|
&kSpeechDataWeights[channel]);
|
||||||
|
|
||||||
// |diff| = "global" speech mean - "global" noise mean.
|
// `diff` = "global" speech mean - "global" noise mean.
|
||||||
// (Q14 >> 9) - (Q14 >> 9) = Q5.
|
// (Q14 >> 9) - (Q14 >> 9) = Q5.
|
||||||
diff = (int16_t) (speech_global_mean >> 9) -
|
diff = (int16_t) (speech_global_mean >> 9) -
|
||||||
(int16_t) (noise_global_mean >> 9);
|
(int16_t) (noise_global_mean >> 9);
|
||||||
if (diff < kMinimumDifference[channel]) {
|
if (diff < kMinimumDifference[channel]) {
|
||||||
tmp_s16 = kMinimumDifference[channel] - diff;
|
tmp_s16 = kMinimumDifference[channel] - diff;
|
||||||
|
|
||||||
// |tmp1_s16| = ~0.8 * (kMinimumDifference - diff) in Q7.
|
// `tmp1_s16` = ~0.8 * (kMinimumDifference - diff) in Q7.
|
||||||
// |tmp2_s16| = ~0.2 * (kMinimumDifference - diff) in Q7.
|
// `tmp2_s16` = ~0.2 * (kMinimumDifference - diff) in Q7.
|
||||||
tmp1_s16 = (int16_t)((13 * tmp_s16) >> 2);
|
tmp1_s16 = (int16_t)((13 * tmp_s16) >> 2);
|
||||||
tmp2_s16 = (int16_t)((3 * tmp_s16) >> 2);
|
tmp2_s16 = (int16_t)((3 * tmp_s16) >> 2);
|
||||||
|
|
||||||
// Move Gaussian means for speech model by |tmp1_s16| and update
|
// Move Gaussian means for speech model by `tmp1_s16` and update
|
||||||
// |speech_global_mean|. Note that |self->speech_means[channel]| is
|
// `speech_global_mean`. Note that |self->speech_means[channel]| is
|
||||||
// changed after the call.
|
// changed after the call.
|
||||||
speech_global_mean = WeightedAverage(&self->speech_means[channel],
|
speech_global_mean = WeightedAverage(&self->speech_means[channel],
|
||||||
tmp1_s16,
|
tmp1_s16,
|
||||||
&kSpeechDataWeights[channel]);
|
&kSpeechDataWeights[channel]);
|
||||||
|
|
||||||
// Move Gaussian means for noise model by -|tmp2_s16| and update
|
// Move Gaussian means for noise model by -`tmp2_s16` and update
|
||||||
// |noise_global_mean|. Note that |self->noise_means[channel]| is
|
// `noise_global_mean`. Note that |self->noise_means[channel]| is
|
||||||
// changed after the call.
|
// changed after the call.
|
||||||
noise_global_mean = WeightedAverage(&self->noise_means[channel],
|
noise_global_mean = WeightedAverage(&self->noise_means[channel],
|
||||||
-tmp2_s16,
|
-tmp2_s16,
|
||||||
@ -534,7 +534,7 @@ int WebRtcVad_InitCore(VadInstT* self) {
|
|||||||
self->mean_value[i] = 1600;
|
self->mean_value[i] = 1600;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set aggressiveness mode to default (=|kDefaultMode|).
|
// Set aggressiveness mode to default (=`kDefaultMode`).
|
||||||
if (WebRtcVad_set_mode_core(self, kDefaultMode) != 0) {
|
if (WebRtcVad_set_mode_core(self, kDefaultMode) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -609,7 +609,7 @@ int WebRtcVad_CalcVad48khz(VadInstT* inst, const int16_t* speech_frame,
|
|||||||
int vad;
|
int vad;
|
||||||
size_t i;
|
size_t i;
|
||||||
int16_t speech_nb[240]; // 30 ms in 8 kHz.
|
int16_t speech_nb[240]; // 30 ms in 8 kHz.
|
||||||
// |tmp_mem| is a temporary memory used by resample function, length is
|
// `tmp_mem` is a temporary memory used by resample function, length is
|
||||||
// frame length in 10 ms (480 samples) + 256 extra.
|
// frame length in 10 ms (480 samples) + 256 extra.
|
||||||
int32_t tmp_mem[480 + 256] = { 0 };
|
int32_t tmp_mem[480 + 256] = { 0 };
|
||||||
const size_t kFrameLen10ms48khz = 480;
|
const size_t kFrameLen10ms48khz = 480;
|
||||||
|
|||||||
@ -30,14 +30,14 @@ typedef struct VadInstT_ {
|
|||||||
int16_t speech_means[kTableSize];
|
int16_t speech_means[kTableSize];
|
||||||
int16_t noise_stds[kTableSize];
|
int16_t noise_stds[kTableSize];
|
||||||
int16_t speech_stds[kTableSize];
|
int16_t speech_stds[kTableSize];
|
||||||
// TODO(bjornv): Change to |frame_count|.
|
// TODO(bjornv): Change to `frame_count`.
|
||||||
int32_t frame_counter;
|
int32_t frame_counter;
|
||||||
int16_t over_hang; // Over Hang
|
int16_t over_hang; // Over Hang
|
||||||
int16_t num_of_speech;
|
int16_t num_of_speech;
|
||||||
// TODO(bjornv): Change to |age_vector|.
|
// TODO(bjornv): Change to `age_vector`.
|
||||||
int16_t index_vector[16 * kNumChannels];
|
int16_t index_vector[16 * kNumChannels];
|
||||||
int16_t low_value_vector[16 * kNumChannels];
|
int16_t low_value_vector[16 * kNumChannels];
|
||||||
// TODO(bjornv): Change to |median|.
|
// TODO(bjornv): Change to `median`.
|
||||||
int16_t mean_value[kNumChannels];
|
int16_t mean_value[kNumChannels];
|
||||||
int16_t upper_state[5];
|
int16_t upper_state[5];
|
||||||
int16_t lower_state[5];
|
int16_t lower_state[5];
|
||||||
@ -51,7 +51,7 @@ typedef struct VadInstT_ {
|
|||||||
} VadInstT;
|
} VadInstT;
|
||||||
|
|
||||||
// Initializes the core VAD component. The default aggressiveness mode is
|
// Initializes the core VAD component. The default aggressiveness mode is
|
||||||
// controlled by |kDefaultMode| in vad_core.c.
|
// controlled by `kDefaultMode` in vad_core.c.
|
||||||
//
|
//
|
||||||
// - self [i/o] : Instance that should be initialized
|
// - self [i/o] : Instance that should be initialized
|
||||||
//
|
//
|
||||||
|
|||||||
@ -28,7 +28,7 @@ static const int16_t kAllPassCoefsQ15[2] = { 20972, 5571 };
|
|||||||
// Adjustment for division with two in SplitFilter.
|
// Adjustment for division with two in SplitFilter.
|
||||||
static const int16_t kOffsetVector[6] = { 368, 368, 272, 176, 176, 176 };
|
static const int16_t kOffsetVector[6] = { 368, 368, 272, 176, 176, 176 };
|
||||||
|
|
||||||
// High pass filtering, with a cut-off frequency at 80 Hz, if the |data_in| is
|
// High pass filtering, with a cut-off frequency at 80 Hz, if the `data_in` is
|
||||||
// sampled at 500 Hz.
|
// sampled at 500 Hz.
|
||||||
//
|
//
|
||||||
// - data_in [i] : Input audio data sampled at 500 Hz.
|
// - data_in [i] : Input audio data sampled at 500 Hz.
|
||||||
@ -69,9 +69,9 @@ static void HighPassFilter(const int16_t* data_in, size_t data_length,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All pass filtering of |data_in|, used before splitting the signal into two
|
// All pass filtering of `data_in`, used before splitting the signal into two
|
||||||
// frequency bands (low pass vs high pass).
|
// frequency bands (low pass vs high pass).
|
||||||
// Note that |data_in| and |data_out| can NOT correspond to the same address.
|
// Note that `data_in` and `data_out` can NOT correspond to the same address.
|
||||||
//
|
//
|
||||||
// - data_in [i] : Input audio signal given in Q0.
|
// - data_in [i] : Input audio signal given in Q0.
|
||||||
// - data_length [i] : Length of input and output data.
|
// - data_length [i] : Length of input and output data.
|
||||||
@ -104,17 +104,17 @@ static void AllPassFilter(const int16_t* data_in, size_t data_length,
|
|||||||
*filter_state = (int16_t) (state32 >> 16); // Q(-1)
|
*filter_state = (int16_t) (state32 >> 16); // Q(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splits |data_in| into |hp_data_out| and |lp_data_out| corresponding to
|
// Splits `data_in` into `hp_data_out` and `lp_data_out` corresponding to
|
||||||
// an upper (high pass) part and a lower (low pass) part respectively.
|
// an upper (high pass) part and a lower (low pass) part respectively.
|
||||||
//
|
//
|
||||||
// - data_in [i] : Input audio data to be split into two frequency bands.
|
// - data_in [i] : Input audio data to be split into two frequency bands.
|
||||||
// - data_length [i] : Length of |data_in|.
|
// - data_length [i] : Length of `data_in`.
|
||||||
// - upper_state [i/o] : State of the upper filter, given in Q(-1).
|
// - upper_state [i/o] : State of the upper filter, given in Q(-1).
|
||||||
// - lower_state [i/o] : State of the lower filter, given in Q(-1).
|
// - lower_state [i/o] : State of the lower filter, given in Q(-1).
|
||||||
// - hp_data_out [o] : Output audio data of the upper half of the spectrum.
|
// - hp_data_out [o] : Output audio data of the upper half of the spectrum.
|
||||||
// The length is |data_length| / 2.
|
// The length is `data_length` / 2.
|
||||||
// - lp_data_out [o] : Output audio data of the lower half of the spectrum.
|
// - lp_data_out [o] : Output audio data of the lower half of the spectrum.
|
||||||
// The length is |data_length| / 2.
|
// The length is `data_length` / 2.
|
||||||
static void SplitFilter(const int16_t* data_in, size_t data_length,
|
static void SplitFilter(const int16_t* data_in, size_t data_length,
|
||||||
int16_t* upper_state, int16_t* lower_state,
|
int16_t* upper_state, int16_t* lower_state,
|
||||||
int16_t* hp_data_out, int16_t* lp_data_out) {
|
int16_t* hp_data_out, int16_t* lp_data_out) {
|
||||||
@ -138,23 +138,23 @@ static void SplitFilter(const int16_t* data_in, size_t data_length,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the energy of |data_in| in dB, and also updates an overall
|
// Calculates the energy of `data_in` in dB, and also updates an overall
|
||||||
// |total_energy| if necessary.
|
// `total_energy` if necessary.
|
||||||
//
|
//
|
||||||
// - data_in [i] : Input audio data for energy calculation.
|
// - data_in [i] : Input audio data for energy calculation.
|
||||||
// - data_length [i] : Length of input data.
|
// - data_length [i] : Length of input data.
|
||||||
// - offset [i] : Offset value added to |log_energy|.
|
// - offset [i] : Offset value added to `log_energy`.
|
||||||
// - total_energy [i/o] : An external energy updated with the energy of
|
// - total_energy [i/o] : An external energy updated with the energy of
|
||||||
// |data_in|.
|
// `data_in`.
|
||||||
// NOTE: |total_energy| is only updated if
|
// NOTE: `total_energy` is only updated if
|
||||||
// |total_energy| <= |kMinEnergy|.
|
// `total_energy` <= `kMinEnergy`.
|
||||||
// - log_energy [o] : 10 * log10("energy of |data_in|") given in Q4.
|
// - log_energy [o] : 10 * log10("energy of `data_in`") given in Q4.
|
||||||
static void LogOfEnergy(const int16_t* data_in, size_t data_length,
|
static void LogOfEnergy(const int16_t* data_in, size_t data_length,
|
||||||
int16_t offset, int16_t* total_energy,
|
int16_t offset, int16_t* total_energy,
|
||||||
int16_t* log_energy) {
|
int16_t* log_energy) {
|
||||||
// |tot_rshifts| accumulates the number of right shifts performed on |energy|.
|
// `tot_rshifts` accumulates the number of right shifts performed on `energy`.
|
||||||
int tot_rshifts = 0;
|
int tot_rshifts = 0;
|
||||||
// The |energy| will be normalized to 15 bits. We use unsigned integer because
|
// The `energy` will be normalized to 15 bits. We use unsigned integer because
|
||||||
// we eventually will mask out the fractional part.
|
// we eventually will mask out the fractional part.
|
||||||
uint32_t energy = 0;
|
uint32_t energy = 0;
|
||||||
|
|
||||||
@ -169,14 +169,14 @@ static void LogOfEnergy(const int16_t* data_in, size_t data_length,
|
|||||||
// zeros of an unsigned 32 bit value.
|
// zeros of an unsigned 32 bit value.
|
||||||
int normalizing_rshifts = 17 - WebRtcSpl_NormU32(energy);
|
int normalizing_rshifts = 17 - WebRtcSpl_NormU32(energy);
|
||||||
// In a 15 bit representation the leading bit is 2^14. log2(2^14) in Q10 is
|
// In a 15 bit representation the leading bit is 2^14. log2(2^14) in Q10 is
|
||||||
// (14 << 10), which is what we initialize |log2_energy| with. For a more
|
// (14 << 10), which is what we initialize `log2_energy` with. For a more
|
||||||
// detailed derivations, see below.
|
// detailed derivations, see below.
|
||||||
int16_t log2_energy = kLogEnergyIntPart;
|
int16_t log2_energy = kLogEnergyIntPart;
|
||||||
|
|
||||||
tot_rshifts += normalizing_rshifts;
|
tot_rshifts += normalizing_rshifts;
|
||||||
// Normalize |energy| to 15 bits.
|
// Normalize `energy` to 15 bits.
|
||||||
// |tot_rshifts| is now the total number of right shifts performed on
|
// `tot_rshifts` is now the total number of right shifts performed on
|
||||||
// |energy| after normalization. This means that |energy| is in
|
// `energy` after normalization. This means that `energy` is in
|
||||||
// Q(-tot_rshifts).
|
// Q(-tot_rshifts).
|
||||||
if (normalizing_rshifts < 0) {
|
if (normalizing_rshifts < 0) {
|
||||||
energy <<= -normalizing_rshifts;
|
energy <<= -normalizing_rshifts;
|
||||||
@ -184,30 +184,30 @@ static void LogOfEnergy(const int16_t* data_in, size_t data_length,
|
|||||||
energy >>= normalizing_rshifts;
|
energy >>= normalizing_rshifts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the energy of |data_in| in dB, in Q4.
|
// Calculate the energy of `data_in` in dB, in Q4.
|
||||||
//
|
//
|
||||||
// 10 * log10("true energy") in Q4 = 2^4 * 10 * log10("true energy") =
|
// 10 * log10("true energy") in Q4 = 2^4 * 10 * log10("true energy") =
|
||||||
// 160 * log10(|energy| * 2^|tot_rshifts|) =
|
// 160 * log10(`energy` * 2^`tot_rshifts`) =
|
||||||
// 160 * log10(2) * log2(|energy| * 2^|tot_rshifts|) =
|
// 160 * log10(2) * log2(`energy` * 2^`tot_rshifts`) =
|
||||||
// 160 * log10(2) * (log2(|energy|) + log2(2^|tot_rshifts|)) =
|
// 160 * log10(2) * (log2(`energy`) + log2(2^`tot_rshifts`)) =
|
||||||
// (160 * log10(2)) * (log2(|energy|) + |tot_rshifts|) =
|
// (160 * log10(2)) * (log2(`energy`) + `tot_rshifts`) =
|
||||||
// |kLogConst| * (|log2_energy| + |tot_rshifts|)
|
// `kLogConst` * (`log2_energy` + `tot_rshifts`)
|
||||||
//
|
//
|
||||||
// We know by construction that |energy| is normalized to 15 bits. Hence,
|
// We know by construction that `energy` is normalized to 15 bits. Hence,
|
||||||
// |energy| = 2^14 + frac_Q15, where frac_Q15 is a fractional part in Q15.
|
// `energy` = 2^14 + frac_Q15, where frac_Q15 is a fractional part in Q15.
|
||||||
// Further, we'd like |log2_energy| in Q10
|
// Further, we'd like `log2_energy` in Q10
|
||||||
// log2(|energy|) in Q10 = 2^10 * log2(2^14 + frac_Q15) =
|
// log2(`energy`) in Q10 = 2^10 * log2(2^14 + frac_Q15) =
|
||||||
// 2^10 * log2(2^14 * (1 + frac_Q15 * 2^-14)) =
|
// 2^10 * log2(2^14 * (1 + frac_Q15 * 2^-14)) =
|
||||||
// 2^10 * (14 + log2(1 + frac_Q15 * 2^-14)) ~=
|
// 2^10 * (14 + log2(1 + frac_Q15 * 2^-14)) ~=
|
||||||
// (14 << 10) + 2^10 * (frac_Q15 * 2^-14) =
|
// (14 << 10) + 2^10 * (frac_Q15 * 2^-14) =
|
||||||
// (14 << 10) + (frac_Q15 * 2^-4) = (14 << 10) + (frac_Q15 >> 4)
|
// (14 << 10) + (frac_Q15 * 2^-4) = (14 << 10) + (frac_Q15 >> 4)
|
||||||
//
|
//
|
||||||
// Note that frac_Q15 = (|energy| & 0x00003FFF)
|
// Note that frac_Q15 = (`energy` & 0x00003FFF)
|
||||||
|
|
||||||
// Calculate and add the fractional part to |log2_energy|.
|
// Calculate and add the fractional part to `log2_energy`.
|
||||||
log2_energy += (int16_t) ((energy & 0x00003FFF) >> 4);
|
log2_energy += (int16_t) ((energy & 0x00003FFF) >> 4);
|
||||||
|
|
||||||
// |kLogConst| is in Q9, |log2_energy| in Q10 and |tot_rshifts| in Q0.
|
// `kLogConst` is in Q9, `log2_energy` in Q10 and `tot_rshifts` in Q0.
|
||||||
// Note that we in our derivation above have accounted for an output in Q4.
|
// Note that we in our derivation above have accounted for an output in Q4.
|
||||||
*log_energy = (int16_t)(((kLogConst * log2_energy) >> 19) +
|
*log_energy = (int16_t)(((kLogConst * log2_energy) >> 19) +
|
||||||
((tot_rshifts * kLogConst) >> 9));
|
((tot_rshifts * kLogConst) >> 9));
|
||||||
@ -222,19 +222,19 @@ static void LogOfEnergy(const int16_t* data_in, size_t data_length,
|
|||||||
|
|
||||||
*log_energy += offset;
|
*log_energy += offset;
|
||||||
|
|
||||||
// Update the approximate |total_energy| with the energy of |data_in|, if
|
// Update the approximate `total_energy` with the energy of `data_in`, if
|
||||||
// |total_energy| has not exceeded |kMinEnergy|. |total_energy| is used as an
|
// `total_energy` has not exceeded `kMinEnergy`. `total_energy` is used as an
|
||||||
// energy indicator in WebRtcVad_GmmProbability() in vad_core.c.
|
// energy indicator in WebRtcVad_GmmProbability() in vad_core.c.
|
||||||
if (*total_energy <= kMinEnergy) {
|
if (*total_energy <= kMinEnergy) {
|
||||||
if (tot_rshifts >= 0) {
|
if (tot_rshifts >= 0) {
|
||||||
// We know by construction that the |energy| > |kMinEnergy| in Q0, so add
|
// We know by construction that the `energy` > `kMinEnergy` in Q0, so add
|
||||||
// an arbitrary value such that |total_energy| exceeds |kMinEnergy|.
|
// an arbitrary value such that `total_energy` exceeds `kMinEnergy`.
|
||||||
*total_energy += kMinEnergy + 1;
|
*total_energy += kMinEnergy + 1;
|
||||||
} else {
|
} else {
|
||||||
// By construction |energy| is represented by 15 bits, hence any number of
|
// By construction `energy` is represented by 15 bits, hence any number of
|
||||||
// right shifted |energy| will fit in an int16_t. In addition, adding the
|
// right shifted `energy` will fit in an int16_t. In addition, adding the
|
||||||
// value to |total_energy| is wrap around safe as long as
|
// value to `total_energy` is wrap around safe as long as
|
||||||
// |kMinEnergy| < 8192.
|
// `kMinEnergy` < 8192.
|
||||||
*total_energy += (int16_t) (energy >> -tot_rshifts); // Q0.
|
*total_energy += (int16_t) (energy >> -tot_rshifts); // Q0.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,14 +243,14 @@ static void LogOfEnergy(const int16_t* data_in, size_t data_length,
|
|||||||
int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
||||||
size_t data_length, int16_t* features) {
|
size_t data_length, int16_t* features) {
|
||||||
int16_t total_energy = 0;
|
int16_t total_energy = 0;
|
||||||
// We expect |data_length| to be 80, 160 or 240 samples, which corresponds to
|
// We expect `data_length` to be 80, 160 or 240 samples, which corresponds to
|
||||||
// 10, 20 or 30 ms in 8 kHz. Therefore, the intermediate downsampled data will
|
// 10, 20 or 30 ms in 8 kHz. Therefore, the intermediate downsampled data will
|
||||||
// have at most 120 samples after the first split and at most 60 samples after
|
// have at most 120 samples after the first split and at most 60 samples after
|
||||||
// the second split.
|
// the second split.
|
||||||
int16_t hp_120[120], lp_120[120];
|
int16_t hp_120[120], lp_120[120];
|
||||||
int16_t hp_60[60], lp_60[60];
|
int16_t hp_60[60], lp_60[60];
|
||||||
const size_t half_data_length = data_length >> 1;
|
const size_t half_data_length = data_length >> 1;
|
||||||
size_t length = half_data_length; // |data_length| / 2, corresponds to
|
size_t length = half_data_length; // `data_length` / 2, corresponds to
|
||||||
// bandwidth = 2000 Hz after downsampling.
|
// bandwidth = 2000 Hz after downsampling.
|
||||||
|
|
||||||
// Initialize variables for the first SplitFilter().
|
// Initialize variables for the first SplitFilter().
|
||||||
@ -260,7 +260,7 @@ int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
|||||||
int16_t* lp_out_ptr = lp_120; // [0 - 2000] Hz.
|
int16_t* lp_out_ptr = lp_120; // [0 - 2000] Hz.
|
||||||
|
|
||||||
RTC_DCHECK_LE(data_length, 240);
|
RTC_DCHECK_LE(data_length, 240);
|
||||||
RTC_DCHECK_LT(4, kNumChannels - 1); // Checking maximum |frequency_band|.
|
RTC_DCHECK_LT(4, kNumChannels - 1); // Checking maximum `frequency_band`.
|
||||||
|
|
||||||
// Split at 2000 Hz and downsample.
|
// Split at 2000 Hz and downsample.
|
||||||
SplitFilter(in_ptr, data_length, &self->upper_state[frequency_band],
|
SplitFilter(in_ptr, data_length, &self->upper_state[frequency_band],
|
||||||
@ -275,7 +275,7 @@ int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
|||||||
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
||||||
|
|
||||||
// Energy in 3000 Hz - 4000 Hz.
|
// Energy in 3000 Hz - 4000 Hz.
|
||||||
length >>= 1; // |data_length| / 4 <=> bandwidth = 1000 Hz.
|
length >>= 1; // `data_length` / 4 <=> bandwidth = 1000 Hz.
|
||||||
|
|
||||||
LogOfEnergy(hp_60, length, kOffsetVector[5], &total_energy, &features[5]);
|
LogOfEnergy(hp_60, length, kOffsetVector[5], &total_energy, &features[5]);
|
||||||
|
|
||||||
@ -287,12 +287,12 @@ int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
|||||||
in_ptr = lp_120; // [0 - 2000] Hz.
|
in_ptr = lp_120; // [0 - 2000] Hz.
|
||||||
hp_out_ptr = hp_60; // [1000 - 2000] Hz.
|
hp_out_ptr = hp_60; // [1000 - 2000] Hz.
|
||||||
lp_out_ptr = lp_60; // [0 - 1000] Hz.
|
lp_out_ptr = lp_60; // [0 - 1000] Hz.
|
||||||
length = half_data_length; // |data_length| / 2 <=> bandwidth = 2000 Hz.
|
length = half_data_length; // `data_length` / 2 <=> bandwidth = 2000 Hz.
|
||||||
SplitFilter(in_ptr, length, &self->upper_state[frequency_band],
|
SplitFilter(in_ptr, length, &self->upper_state[frequency_band],
|
||||||
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
||||||
|
|
||||||
// Energy in 1000 Hz - 2000 Hz.
|
// Energy in 1000 Hz - 2000 Hz.
|
||||||
length >>= 1; // |data_length| / 4 <=> bandwidth = 1000 Hz.
|
length >>= 1; // `data_length` / 4 <=> bandwidth = 1000 Hz.
|
||||||
LogOfEnergy(hp_60, length, kOffsetVector[3], &total_energy, &features[3]);
|
LogOfEnergy(hp_60, length, kOffsetVector[3], &total_energy, &features[3]);
|
||||||
|
|
||||||
// For the lower band (0 Hz - 1000 Hz) split at 500 Hz and downsample.
|
// For the lower band (0 Hz - 1000 Hz) split at 500 Hz and downsample.
|
||||||
@ -304,7 +304,7 @@ int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
|||||||
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
||||||
|
|
||||||
// Energy in 500 Hz - 1000 Hz.
|
// Energy in 500 Hz - 1000 Hz.
|
||||||
length >>= 1; // |data_length| / 8 <=> bandwidth = 500 Hz.
|
length >>= 1; // `data_length` / 8 <=> bandwidth = 500 Hz.
|
||||||
LogOfEnergy(hp_120, length, kOffsetVector[2], &total_energy, &features[2]);
|
LogOfEnergy(hp_120, length, kOffsetVector[2], &total_energy, &features[2]);
|
||||||
|
|
||||||
// For the lower band (0 Hz - 500 Hz) split at 250 Hz and downsample.
|
// For the lower band (0 Hz - 500 Hz) split at 250 Hz and downsample.
|
||||||
@ -316,7 +316,7 @@ int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
|
|||||||
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
&self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
|
||||||
|
|
||||||
// Energy in 250 Hz - 500 Hz.
|
// Energy in 250 Hz - 500 Hz.
|
||||||
length >>= 1; // |data_length| / 16 <=> bandwidth = 250 Hz.
|
length >>= 1; // `data_length` / 16 <=> bandwidth = 250 Hz.
|
||||||
LogOfEnergy(hp_60, length, kOffsetVector[1], &total_energy, &features[1]);
|
LogOfEnergy(hp_60, length, kOffsetVector[1], &total_energy, &features[1]);
|
||||||
|
|
||||||
// Remove 0 Hz - 80 Hz, by high pass filtering the lower band.
|
// Remove 0 Hz - 80 Hz, by high pass filtering the lower band.
|
||||||
|
|||||||
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
#include "common_audio/vad/vad_core.h"
|
#include "common_audio/vad/vad_core.h"
|
||||||
|
|
||||||
// Takes |data_length| samples of |data_in| and calculates the logarithm of the
|
// Takes `data_length` samples of `data_in` and calculates the logarithm of the
|
||||||
// energy of each of the |kNumChannels| = 6 frequency bands used by the VAD:
|
// energy of each of the `kNumChannels` = 6 frequency bands used by the VAD:
|
||||||
// 80 Hz - 250 Hz
|
// 80 Hz - 250 Hz
|
||||||
// 250 Hz - 500 Hz
|
// 250 Hz - 500 Hz
|
||||||
// 500 Hz - 1000 Hz
|
// 500 Hz - 1000 Hz
|
||||||
@ -26,10 +26,10 @@
|
|||||||
// 2000 Hz - 3000 Hz
|
// 2000 Hz - 3000 Hz
|
||||||
// 3000 Hz - 4000 Hz
|
// 3000 Hz - 4000 Hz
|
||||||
//
|
//
|
||||||
// The values are given in Q4 and written to |features|. Further, an approximate
|
// The values are given in Q4 and written to `features`. Further, an approximate
|
||||||
// overall energy is returned. The return value is used in
|
// overall energy is returned. The return value is used in
|
||||||
// WebRtcVad_GmmProbability() as a signal indicator, hence it is arbitrary above
|
// WebRtcVad_GmmProbability() as a signal indicator, hence it is arbitrary above
|
||||||
// the threshold |kMinEnergy|.
|
// the threshold `kMinEnergy`.
|
||||||
//
|
//
|
||||||
// - self [i/o] : State information of the VAD.
|
// - self [i/o] : State information of the VAD.
|
||||||
// - data_in [i] : Input audio data, for feature extraction.
|
// - data_in [i] : Input audio data, for feature extraction.
|
||||||
|
|||||||
@ -15,16 +15,16 @@
|
|||||||
static const int32_t kCompVar = 22005;
|
static const int32_t kCompVar = 22005;
|
||||||
static const int16_t kLog2Exp = 5909; // log2(exp(1)) in Q12.
|
static const int16_t kLog2Exp = 5909; // log2(exp(1)) in Q12.
|
||||||
|
|
||||||
// For a normal distribution, the probability of |input| is calculated and
|
// For a normal distribution, the probability of `input` is calculated and
|
||||||
// returned (in Q20). The formula for normal distributed probability is
|
// returned (in Q20). The formula for normal distributed probability is
|
||||||
//
|
//
|
||||||
// 1 / s * exp(-(x - m)^2 / (2 * s^2))
|
// 1 / s * exp(-(x - m)^2 / (2 * s^2))
|
||||||
//
|
//
|
||||||
// where the parameters are given in the following Q domains:
|
// where the parameters are given in the following Q domains:
|
||||||
// m = |mean| (Q7)
|
// m = `mean` (Q7)
|
||||||
// s = |std| (Q7)
|
// s = `std` (Q7)
|
||||||
// x = |input| (Q4)
|
// x = `input` (Q4)
|
||||||
// in addition to the probability we output |delta| (in Q11) used when updating
|
// in addition to the probability we output `delta` (in Q11) used when updating
|
||||||
// the noise/speech model.
|
// the noise/speech model.
|
||||||
int32_t WebRtcVad_GaussianProbability(int16_t input,
|
int32_t WebRtcVad_GaussianProbability(int16_t input,
|
||||||
int16_t mean,
|
int16_t mean,
|
||||||
@ -33,13 +33,13 @@ int32_t WebRtcVad_GaussianProbability(int16_t input,
|
|||||||
int16_t tmp16, inv_std, inv_std2, exp_value = 0;
|
int16_t tmp16, inv_std, inv_std2, exp_value = 0;
|
||||||
int32_t tmp32;
|
int32_t tmp32;
|
||||||
|
|
||||||
// Calculate |inv_std| = 1 / s, in Q10.
|
// Calculate `inv_std` = 1 / s, in Q10.
|
||||||
// 131072 = 1 in Q17, and (|std| >> 1) is for rounding instead of truncation.
|
// 131072 = 1 in Q17, and (`std` >> 1) is for rounding instead of truncation.
|
||||||
// Q-domain: Q17 / Q7 = Q10.
|
// Q-domain: Q17 / Q7 = Q10.
|
||||||
tmp32 = (int32_t) 131072 + (int32_t) (std >> 1);
|
tmp32 = (int32_t) 131072 + (int32_t) (std >> 1);
|
||||||
inv_std = (int16_t) WebRtcSpl_DivW32W16(tmp32, std);
|
inv_std = (int16_t) WebRtcSpl_DivW32W16(tmp32, std);
|
||||||
|
|
||||||
// Calculate |inv_std2| = 1 / s^2, in Q14.
|
// Calculate `inv_std2` = 1 / s^2, in Q14.
|
||||||
tmp16 = (inv_std >> 2); // Q10 -> Q8.
|
tmp16 = (inv_std >> 2); // Q10 -> Q8.
|
||||||
// Q-domain: (Q8 * Q8) >> 2 = Q14.
|
// Q-domain: (Q8 * Q8) >> 2 = Q14.
|
||||||
inv_std2 = (int16_t)((tmp16 * tmp16) >> 2);
|
inv_std2 = (int16_t)((tmp16 * tmp16) >> 2);
|
||||||
@ -51,20 +51,20 @@ int32_t WebRtcVad_GaussianProbability(int16_t input,
|
|||||||
tmp16 = tmp16 - mean; // Q7 - Q7 = Q7
|
tmp16 = tmp16 - mean; // Q7 - Q7 = Q7
|
||||||
|
|
||||||
// To be used later, when updating noise/speech model.
|
// To be used later, when updating noise/speech model.
|
||||||
// |delta| = (x - m) / s^2, in Q11.
|
// `delta` = (x - m) / s^2, in Q11.
|
||||||
// Q-domain: (Q14 * Q7) >> 10 = Q11.
|
// Q-domain: (Q14 * Q7) >> 10 = Q11.
|
||||||
*delta = (int16_t)((inv_std2 * tmp16) >> 10);
|
*delta = (int16_t)((inv_std2 * tmp16) >> 10);
|
||||||
|
|
||||||
// Calculate the exponent |tmp32| = (x - m)^2 / (2 * s^2), in Q10. Replacing
|
// Calculate the exponent `tmp32` = (x - m)^2 / (2 * s^2), in Q10. Replacing
|
||||||
// division by two with one shift.
|
// division by two with one shift.
|
||||||
// Q-domain: (Q11 * Q7) >> 8 = Q10.
|
// Q-domain: (Q11 * Q7) >> 8 = Q10.
|
||||||
tmp32 = (*delta * tmp16) >> 9;
|
tmp32 = (*delta * tmp16) >> 9;
|
||||||
|
|
||||||
// If the exponent is small enough to give a non-zero probability we calculate
|
// If the exponent is small enough to give a non-zero probability we calculate
|
||||||
// |exp_value| ~= exp(-(x - m)^2 / (2 * s^2))
|
// `exp_value` ~= exp(-(x - m)^2 / (2 * s^2))
|
||||||
// ~= exp2(-log2(exp(1)) * |tmp32|).
|
// ~= exp2(-log2(exp(1)) * `tmp32`).
|
||||||
if (tmp32 < kCompVar) {
|
if (tmp32 < kCompVar) {
|
||||||
// Calculate |tmp16| = log2(exp(1)) * |tmp32|, in Q10.
|
// Calculate `tmp16` = log2(exp(1)) * `tmp32`, in Q10.
|
||||||
// Q-domain: (Q12 * Q10) >> 12 = Q10.
|
// Q-domain: (Q12 * Q10) >> 12 = Q10.
|
||||||
tmp16 = (int16_t)((kLog2Exp * tmp32) >> 12);
|
tmp16 = (int16_t)((kLog2Exp * tmp32) >> 12);
|
||||||
tmp16 = -tmp16;
|
tmp16 = -tmp16;
|
||||||
@ -72,7 +72,7 @@ int32_t WebRtcVad_GaussianProbability(int16_t input,
|
|||||||
tmp16 ^= 0xFFFF;
|
tmp16 ^= 0xFFFF;
|
||||||
tmp16 >>= 10;
|
tmp16 >>= 10;
|
||||||
tmp16 += 1;
|
tmp16 += 1;
|
||||||
// Get |exp_value| = exp(-|tmp32|) in Q10.
|
// Get `exp_value` = exp(-`tmp32`) in Q10.
|
||||||
exp_value >>= tmp16;
|
exp_value >>= tmp16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// Calculates the probability for |input|, given that |input| comes from a
|
// Calculates the probability for `input`, given that `input` comes from a
|
||||||
// normal distribution with mean and standard deviation (|mean|, |std|).
|
// normal distribution with mean and standard deviation (`mean`, `std`).
|
||||||
//
|
//
|
||||||
// Inputs:
|
// Inputs:
|
||||||
// - input : input sample in Q4.
|
// - input : input sample in Q4.
|
||||||
@ -26,11 +26,11 @@
|
|||||||
// Output:
|
// Output:
|
||||||
//
|
//
|
||||||
// - delta : input used when updating the model, Q11.
|
// - delta : input used when updating the model, Q11.
|
||||||
// |delta| = (|input| - |mean|) / |std|^2.
|
// `delta` = (`input` - `mean`) / `std`^2.
|
||||||
//
|
//
|
||||||
// Return:
|
// Return:
|
||||||
// (probability for |input|) =
|
// (probability for `input`) =
|
||||||
// 1 / |std| * exp(-(|input| - |mean|)^2 / (2 * |std|^2));
|
// 1 / `std` * exp(-(`input` - `mean`)^2 / (2 * `std`^2));
|
||||||
int32_t WebRtcVad_GaussianProbability(int16_t input,
|
int32_t WebRtcVad_GaussianProbability(int16_t input,
|
||||||
int16_t mean,
|
int16_t mean,
|
||||||
int16_t std,
|
int16_t std,
|
||||||
|
|||||||
@ -52,7 +52,7 @@ void WebRtcVad_Downsampling(const int16_t* signal_in,
|
|||||||
filter_state[1] = tmp32_2;
|
filter_state[1] = tmp32_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserts |feature_value| into |low_value_vector|, if it is one of the 16
|
// Inserts `feature_value` into `low_value_vector`, if it is one of the 16
|
||||||
// smallest values the last 100 frames. Then calculates and returns the median
|
// smallest values the last 100 frames. Then calculates and returns the median
|
||||||
// of the five smallest values.
|
// of the five smallest values.
|
||||||
int16_t WebRtcVad_FindMinimum(VadInstT* self,
|
int16_t WebRtcVad_FindMinimum(VadInstT* self,
|
||||||
@ -66,13 +66,13 @@ int16_t WebRtcVad_FindMinimum(VadInstT* self,
|
|||||||
int16_t alpha = 0;
|
int16_t alpha = 0;
|
||||||
int32_t tmp32 = 0;
|
int32_t tmp32 = 0;
|
||||||
// Pointer to memory for the 16 minimum values and the age of each value of
|
// Pointer to memory for the 16 minimum values and the age of each value of
|
||||||
// the |channel|.
|
// the `channel`.
|
||||||
int16_t* age = &self->index_vector[offset];
|
int16_t* age = &self->index_vector[offset];
|
||||||
int16_t* smallest_values = &self->low_value_vector[offset];
|
int16_t* smallest_values = &self->low_value_vector[offset];
|
||||||
|
|
||||||
RTC_DCHECK_LT(channel, kNumChannels);
|
RTC_DCHECK_LT(channel, kNumChannels);
|
||||||
|
|
||||||
// Each value in |smallest_values| is getting 1 loop older. Update |age|, and
|
// Each value in `smallest_values` is getting 1 loop older. Update `age`, and
|
||||||
// remove old values.
|
// remove old values.
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
if (age[i] != 100) {
|
if (age[i] != 100) {
|
||||||
@ -88,9 +88,9 @@ int16_t WebRtcVad_FindMinimum(VadInstT* self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if |feature_value| is smaller than any of the values in
|
// Check if `feature_value` is smaller than any of the values in
|
||||||
// |smallest_values|. If so, find the |position| where to insert the new value
|
// `smallest_values`. If so, find the `position` where to insert the new value
|
||||||
// (|feature_value|).
|
// (`feature_value`).
|
||||||
if (feature_value < smallest_values[7]) {
|
if (feature_value < smallest_values[7]) {
|
||||||
if (feature_value < smallest_values[3]) {
|
if (feature_value < smallest_values[3]) {
|
||||||
if (feature_value < smallest_values[1]) {
|
if (feature_value < smallest_values[1]) {
|
||||||
@ -152,7 +152,7 @@ int16_t WebRtcVad_FindMinimum(VadInstT* self,
|
|||||||
age[position] = 1;
|
age[position] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get |current_median|.
|
// Get `current_median`.
|
||||||
if (self->frame_counter > 2) {
|
if (self->frame_counter > 2) {
|
||||||
current_median = smallest_values[2];
|
current_median = smallest_values[2];
|
||||||
} else if (self->frame_counter > 0) {
|
} else if (self->frame_counter > 0) {
|
||||||
|
|||||||
@ -23,11 +23,11 @@
|
|||||||
//
|
//
|
||||||
// Input & Output:
|
// Input & Output:
|
||||||
// - filter_state : Current filter states of the two all-pass filters. The
|
// - filter_state : Current filter states of the two all-pass filters. The
|
||||||
// |filter_state| is updated after all samples have been
|
// `filter_state` is updated after all samples have been
|
||||||
// processed.
|
// processed.
|
||||||
//
|
//
|
||||||
// Output:
|
// Output:
|
||||||
// - signal_out : Downsampled signal (of length |in_length| / 2).
|
// - signal_out : Downsampled signal (of length `in_length` / 2).
|
||||||
void WebRtcVad_Downsampling(const int16_t* signal_in,
|
void WebRtcVad_Downsampling(const int16_t* signal_in,
|
||||||
int16_t* signal_out,
|
int16_t* signal_out,
|
||||||
int32_t* filter_state,
|
int32_t* filter_state,
|
||||||
|
|||||||
@ -29,7 +29,7 @@ TEST_F(VadTest, vad_sp) {
|
|||||||
int16_t data_in[kMaxFrameLenSp];
|
int16_t data_in[kMaxFrameLenSp];
|
||||||
int16_t data_out[kMaxFrameLenSp];
|
int16_t data_out[kMaxFrameLenSp];
|
||||||
|
|
||||||
// We expect the first value to be 1600 as long as |frame_counter| is zero,
|
// We expect the first value to be 1600 as long as `frame_counter` is zero,
|
||||||
// which is true for the first iteration.
|
// which is true for the first iteration.
|
||||||
static const int16_t kReferenceMin[32] = {
|
static const int16_t kReferenceMin[32] = {
|
||||||
1600, 720, 509, 512, 532, 552, 570, 588, 606, 624, 642,
|
1600, 720, 509, 512, 532, 552, 570, 588, 606, 624, 642,
|
||||||
|
|||||||
@ -161,7 +161,7 @@ uint16_t BlockAlign(size_t num_channels, size_t bytes_per_sample) {
|
|||||||
return static_cast<uint16_t>(num_channels * bytes_per_sample);
|
return static_cast<uint16_t>(num_channels * bytes_per_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds a chunk having the sought ID. If found, then |readable| points to the
|
// Finds a chunk having the sought ID. If found, then `readable` points to the
|
||||||
// first byte of the sought chunk data. If not found, the end of the file is
|
// first byte of the sought chunk data. If not found, the end of the file is
|
||||||
// reached.
|
// reached.
|
||||||
bool FindWaveChunk(ChunkHeader* chunk_header,
|
bool FindWaveChunk(ChunkHeader* chunk_header,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user