NetEq changes.
BUG=
R=henrik.lundin@webrtc.org, minyue@webrtc.org, tina.legrand@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/9859005
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5889 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/neteq4/audio_classifier.h b/webrtc/modules/audio_coding/neteq4/audio_classifier.h
index e64e110..1d041b3 100644
--- a/webrtc/modules/audio_coding/neteq4/audio_classifier.h
+++ b/webrtc/modules/audio_coding/neteq4/audio_classifier.h
@@ -41,7 +41,7 @@
bool Analysis(const int16_t* input, int input_length, int channels);
// Gets the current classification : true = music, false = speech.
- bool is_music() const { return is_music_; }
+ virtual bool is_music() const { return is_music_; }
// Gets the current music probability.
float music_probability() const { return music_probability_; }
diff --git a/webrtc/modules/audio_coding/neteq4/decision_logic.cc b/webrtc/modules/audio_coding/neteq4/decision_logic.cc
index 04b886a..85edbb4 100644
--- a/webrtc/modules/audio_coding/neteq4/decision_logic.cc
+++ b/webrtc/modules/audio_coding/neteq4/decision_logic.cc
@@ -145,8 +145,8 @@
reset_decoder);
}
-void DecisionLogic::ExpandDecision(bool is_expand_decision) {
- if (is_expand_decision) {
+void DecisionLogic::ExpandDecision(Operations operation) {
+ if (operation == kExpand) {
num_consecutive_expands_++;
} else {
num_consecutive_expands_ = 0;
diff --git a/webrtc/modules/audio_coding/neteq4/decision_logic.h b/webrtc/modules/audio_coding/neteq4/decision_logic.h
index aca5ca4..e187449 100644
--- a/webrtc/modules/audio_coding/neteq4/decision_logic.h
+++ b/webrtc/modules/audio_coding/neteq4/decision_logic.h
@@ -92,7 +92,7 @@
// not. Note that this is necessary, since an expand decision can be changed
// to kNormal in NetEqImpl::GetDecision if there is still enough data in the
// sync buffer.
- void ExpandDecision(bool is_expand_decision);
+ virtual void ExpandDecision(Operations operation);
// Adds |value| to |sample_memory_|.
void AddSampleMemory(int32_t value) {
diff --git a/webrtc/modules/audio_coding/neteq4/decision_logic_normal.h b/webrtc/modules/audio_coding/neteq4/decision_logic_normal.h
index 783b001..8ec6034 100644
--- a/webrtc/modules/audio_coding/neteq4/decision_logic_normal.h
+++ b/webrtc/modules/audio_coding/neteq4/decision_logic_normal.h
@@ -38,6 +38,10 @@
virtual ~DecisionLogicNormal() {}
protected:
+ static const int kAllowMergeWithoutExpandMs = 20; // 20 ms.
+ static const int kReinitAfterExpands = 100;
+ static const int kMaxWaitForPacket = 10;
+
// Returns the operation that should be done next. |sync_buffer| and |expand|
// are provided for reference. |decoder_frame_length| is the number of samples
// obtained from the last decoded frame. If there is a packet available, the
@@ -54,32 +58,29 @@
Modes prev_mode, bool play_dtmf,
bool* reset_decoder);
- private:
- static const int kAllowMergeWithoutExpandMs = 20; // 20 ms.
- static const int kReinitAfterExpands = 100;
- static const int kMaxWaitForPacket = 10;
+ // Returns the operation to do given that the expected packet is not
+ // available, but a packet further into the future is at hand.
+ virtual Operations FuturePacketAvailable(
+ const SyncBuffer& sync_buffer,
+ const Expand& expand,
+ int decoder_frame_length, Modes prev_mode,
+ uint32_t target_timestamp,
+ uint32_t available_timestamp,
+ bool play_dtmf);
+ // Returns the operation to do given that the expected packet is available.
+ virtual Operations ExpectedPacketAvailable(Modes prev_mode, bool play_dtmf);
+
+ // Returns the operation given that no packets are available (except maybe
+ // a DTMF event, flagged by setting |play_dtmf| true).
+ virtual Operations NoPacket(bool play_dtmf);
+
+ private:
// Returns the operation given that the next available packet is a comfort
// noise payload (RFC 3389 only, not codec-internal).
Operations CngOperation(Modes prev_mode, uint32_t target_timestamp,
uint32_t available_timestamp);
- // Returns the operation given that no packets are available (except maybe
- // a DTMF event, flagged by setting |play_dtmf| true).
- Operations NoPacket(bool play_dtmf);
-
- // Returns the operation to do given that the expected packet is available.
- Operations ExpectedPacketAvailable(Modes prev_mode, bool play_dtmf);
-
- // Returns the operation to do given that the expected packet is not
- // available, but a packet further into the future is at hand.
- Operations FuturePacketAvailable(const SyncBuffer& sync_buffer,
- const Expand& expand,
- int decoder_frame_length, Modes prev_mode,
- uint32_t target_timestamp,
- uint32_t available_timestamp,
- bool play_dtmf);
-
// Checks if enough time has elapsed since the last successful timescale
// operation was done (i.e., accelerate or preemptive expand).
bool TimescaleAllowed() const { return timescale_hold_off_ == 0; }
diff --git a/webrtc/modules/audio_coding/neteq4/expand.cc b/webrtc/modules/audio_coding/neteq4/expand.cc
index cba9924..9b08de1 100644
--- a/webrtc/modules/audio_coding/neteq4/expand.cc
+++ b/webrtc/modules/audio_coding/neteq4/expand.cc
@@ -56,20 +56,9 @@
// This is not the first expansion, parameters are already estimated.
// Extract a noise segment.
int16_t rand_length = max_lag_;
- // TODO(hlundin): This if-statement should not be needed. Should be just
- // as good to generate all of the vector in one call in either case.
- if (rand_length <= RandomVector::kRandomTableSize) {
- random_vector_->IncreaseSeedIncrement(2);
- random_vector_->Generate(rand_length, random_vector);
- } else {
- // This only applies to SWB where length could be larger than 256.
- assert(rand_length <= kMaxSampleRate / 8000 * 120 + 30);
- random_vector_->IncreaseSeedIncrement(2);
- random_vector_->Generate(RandomVector::kRandomTableSize, random_vector);
- random_vector_->IncreaseSeedIncrement(2);
- random_vector_->Generate(rand_length - RandomVector::kRandomTableSize,
- &random_vector[RandomVector::kRandomTableSize]);
- }
+ // This only applies to SWB where length could be larger than 256.
+ assert(rand_length <= kMaxSampleRate / 8000 * 120 + 30);
+ GenerateRandomVector(2, rand_length, random_vector);
}
@@ -262,82 +251,12 @@
}
// Background noise part.
- // TODO(hlundin): Move to separate method? In BackgroundNoise class?
- if (background_noise_->initialized()) {
- // Use background noise parameters.
- memcpy(noise_vector - kNoiseLpcOrder,
- background_noise_->FilterState(channel_ix),
- sizeof(int16_t) * kNoiseLpcOrder);
-
- if (background_noise_->ScaleShift(channel_ix) > 1) {
- add_constant = 1 << (background_noise_->ScaleShift(channel_ix) - 1);
- } else {
- add_constant = 0;
- }
-
- // Scale random vector to correct energy level.
- WebRtcSpl_AffineTransformVector(
- scaled_random_vector, random_vector,
- background_noise_->Scale(channel_ix), add_constant,
- background_noise_->ScaleShift(channel_ix),
- static_cast<int>(current_lag));
-
- WebRtcSpl_FilterARFastQ12(scaled_random_vector, noise_vector,
- background_noise_->Filter(channel_ix),
- kNoiseLpcOrder + 1,
- static_cast<int>(current_lag));
-
- background_noise_->SetFilterState(
- channel_ix,
- &(noise_vector[current_lag - kNoiseLpcOrder]),
- kNoiseLpcOrder);
-
- // Unmute the background noise.
- int16_t bgn_mute_factor = background_noise_->MuteFactor(channel_ix);
- NetEqBackgroundNoiseMode bgn_mode = background_noise_->mode();
- if (bgn_mode == kBgnFade &&
- consecutive_expands_ >= kMaxConsecutiveExpands &&
- bgn_mute_factor > 0) {
- // Fade BGN to zero.
- // Calculate muting slope, approximately -2^18 / fs_hz.
- int16_t mute_slope;
- if (fs_hz_ == 8000) {
- mute_slope = -32;
- } else if (fs_hz_ == 16000) {
- mute_slope = -16;
- } else if (fs_hz_ == 32000) {
- mute_slope = -8;
- } else {
- mute_slope = -5;
- }
- // Use UnmuteSignal function with negative slope.
- // |bgn_mute_factor| is in Q14. |mute_slope| is in Q20.
- DspHelper::UnmuteSignal(noise_vector, current_lag, &bgn_mute_factor,
- mute_slope, noise_vector);
- } else if (bgn_mute_factor < 16384) {
- // If mode is kBgnOff, or if kBgnFade has started fading,
- // Use regular |mute_slope|.
- if (!stop_muting_ && bgn_mode != kBgnOff &&
- !(bgn_mode == kBgnFade &&
- consecutive_expands_ >= kMaxConsecutiveExpands)) {
- DspHelper::UnmuteSignal(noise_vector, static_cast<int>(current_lag),
- &bgn_mute_factor, parameters.mute_slope,
- noise_vector);
- } else {
- // kBgnOn and stop muting, or
- // kBgnOff (mute factor is always 0), or
- // kBgnFade has reached 0.
- WebRtcSpl_AffineTransformVector(noise_vector, noise_vector,
- bgn_mute_factor, 8192, 14,
- static_cast<int>(current_lag));
- }
- }
- // Update mute_factor in BackgroundNoise class.
- background_noise_->SetMuteFactor(channel_ix, bgn_mute_factor);
- } else {
- // BGN parameters have not been initialized; use zero noise.
- memset(noise_vector, 0, sizeof(int16_t) * current_lag);
- }
+ GenerateBackgroundNoise(random_vector,
+ channel_ix,
+ channel_parameters_[channel_ix].mute_slope,
+ TooManyExpands(),
+ current_lag,
+ unvoiced_array_memory);
// Add background noise to the combined voiced-unvoiced signal.
for (size_t i = 0; i < current_lag; i++) {
@@ -353,11 +272,8 @@
}
// Increase call number and cap it.
- ++consecutive_expands_;
- if (consecutive_expands_ > kMaxConsecutiveExpands) {
- consecutive_expands_ = kMaxConsecutiveExpands;
- }
-
+ consecutive_expands_ = consecutive_expands_ >= kMaxConsecutiveExpands ?
+ kMaxConsecutiveExpands : consecutive_expands_ + 1;
return 0;
}
@@ -373,6 +289,24 @@
stop_muting_ = true;
}
+void Expand::InitializeForAnExpandPeriod() {
+ lag_index_direction_ = 1;
+ current_lag_index_ = -1;
+ stop_muting_ = false;
+ random_vector_->set_seed_increment(1);
+ consecutive_expands_ = 0;
+ for (size_t ix = 0; ix < num_channels_; ++ix) {
+ channel_parameters_[ix].current_voice_mix_factor = 16384; // 1.0 in Q14.
+ channel_parameters_[ix].mute_factor = 16384; // 1.0 in Q14.
+ // Start with 0 gain for background noise.
+ background_noise_->SetMuteFactor(ix, 0);
+ }
+}
+
+bool Expand::TooManyExpands() {
+ return consecutive_expands_ >= kMaxConsecutiveExpands;
+}
+
void Expand::AnalyzeSignal(int16_t* random_vector) {
int32_t auto_correlation[kUnvoicedLpcOrder + 1];
int16_t reflection_coeff[kUnvoicedLpcOrder];
@@ -400,18 +334,8 @@
const int16_t* audio_history =
&(*sync_buffer_)[0][sync_buffer_->Size() - signal_length];
- // Initialize some member variables.
- lag_index_direction_ = 1;
- current_lag_index_ = -1;
- stop_muting_ = false;
- random_vector_->set_seed_increment(1);
- consecutive_expands_ = 0;
- for (size_t ix = 0; ix < num_channels_; ++ix) {
- channel_parameters_[ix].current_voice_mix_factor = 16384; // 1.0 in Q14.
- channel_parameters_[ix].mute_factor = 16384; // 1.0 in Q14.
- // Start with 0 gain for background noise.
- background_noise_->SetMuteFactor(ix, 0);
- }
+ // Initialize.
+ InitializeForAnExpandPeriod();
// Calculate correlation in downsampled domain (4 kHz sample rate).
int16_t correlation_scale;
@@ -873,5 +797,108 @@
num_channels);
}
+// TODO(turajs): This can be moved to BackgroundNoise class.
+void Expand::GenerateBackgroundNoise(int16_t* random_vector,
+ size_t channel,
+ int16_t mute_slope,
+ bool too_many_expands,
+ size_t num_noise_samples,
+ int16_t* buffer) {
+ static const int kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder;
+ int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125];
+ assert(kMaxSampleRate / 8000 * 125 >= (int)num_noise_samples);
+ int16_t* noise_samples = &buffer[kNoiseLpcOrder];
+ if (background_noise_->initialized()) {
+ // Use background noise parameters.
+ memcpy(noise_samples - kNoiseLpcOrder,
+ background_noise_->FilterState(channel),
+ sizeof(int16_t) * kNoiseLpcOrder);
+
+ int dc_offset = 0;
+ if (background_noise_->ScaleShift(channel) > 1) {
+ dc_offset = 1 << (background_noise_->ScaleShift(channel) - 1);
+ }
+
+ // Scale random vector to correct energy level.
+ WebRtcSpl_AffineTransformVector(
+ scaled_random_vector, random_vector,
+ background_noise_->Scale(channel), dc_offset,
+ background_noise_->ScaleShift(channel),
+ static_cast<int>(num_noise_samples));
+
+ WebRtcSpl_FilterARFastQ12(scaled_random_vector, noise_samples,
+ background_noise_->Filter(channel),
+ kNoiseLpcOrder + 1,
+ static_cast<int>(num_noise_samples));
+
+ background_noise_->SetFilterState(
+ channel,
+ &(noise_samples[num_noise_samples - kNoiseLpcOrder]),
+ kNoiseLpcOrder);
+
+ // Unmute the background noise.
+ int16_t bgn_mute_factor = background_noise_->MuteFactor(channel);
+ NetEqBackgroundNoiseMode bgn_mode = background_noise_->mode();
+ if (bgn_mode == kBgnFade && too_many_expands && bgn_mute_factor > 0) {
+ // Fade BGN to zero.
+ // Calculate muting slope, approximately -2^18 / fs_hz.
+ int16_t mute_slope;
+ if (fs_hz_ == 8000) {
+ mute_slope = -32;
+ } else if (fs_hz_ == 16000) {
+ mute_slope = -16;
+ } else if (fs_hz_ == 32000) {
+ mute_slope = -8;
+ } else {
+ mute_slope = -5;
+ }
+ // Use UnmuteSignal function with negative slope.
+ // |bgn_mute_factor| is in Q14. |mute_slope| is in Q20.
+ DspHelper::UnmuteSignal(noise_samples,
+ num_noise_samples,
+ &bgn_mute_factor,
+ mute_slope,
+ noise_samples);
+ } else if (bgn_mute_factor < 16384) {
+ // If mode is kBgnOff, or if kBgnFade has started fading,
+ // Use regular |mute_slope|.
+ if (!stop_muting_ && bgn_mode != kBgnOff &&
+ !(bgn_mode == kBgnFade && too_many_expands)) {
+ DspHelper::UnmuteSignal(noise_samples,
+ static_cast<int>(num_noise_samples),
+ &bgn_mute_factor,
+ mute_slope,
+ noise_samples);
+ } else {
+ // kBgnOn and stop muting, or
+ // kBgnOff (mute factor is always 0), or
+ // kBgnFade has reached 0.
+ WebRtcSpl_AffineTransformVector(noise_samples, noise_samples,
+ bgn_mute_factor, 8192, 14,
+ static_cast<int>(num_noise_samples));
+ }
+ }
+ // Update mute_factor in BackgroundNoise class.
+ background_noise_->SetMuteFactor(channel, bgn_mute_factor);
+ } else {
+ // BGN parameters have not been initialized; use zero noise.
+ memset(noise_samples, 0, sizeof(int16_t) * num_noise_samples);
+ }
+}
+
+void Expand::GenerateRandomVector(int seed_increment,
+ size_t length,
+ int16_t* random_vector) {
+ // TODO(turajs): According to hlundin The loop should not be needed. Should be
+ // just as good to generate all of the vector in one call.
+ size_t samples_generated = 0;
+ const size_t kMaxRandSamples = RandomVector::kRandomTableSize;
+ while(samples_generated < length) {
+ size_t rand_length = std::min(length - samples_generated, kMaxRandSamples);
+ random_vector_->IncreaseSeedIncrement(seed_increment);
+ random_vector_->Generate(rand_length, &random_vector[samples_generated]);
+ samples_generated += rand_length;
+ }
+}
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/neteq4/expand.h b/webrtc/modules/audio_coding/neteq4/expand.h
index 4de8d7c..aec1cd9 100644
--- a/webrtc/modules/audio_coding/neteq4/expand.h
+++ b/webrtc/modules/audio_coding/neteq4/expand.h
@@ -36,12 +36,13 @@
RandomVector* random_vector,
int fs,
size_t num_channels)
- : background_noise_(background_noise),
+ : random_vector_(random_vector),
sync_buffer_(sync_buffer),
- random_vector_(random_vector),
first_expand_(true),
fs_hz_(fs),
num_channels_(num_channels),
+ consecutive_expands_(0),
+ background_noise_(background_noise),
overlap_length_(5 * fs / 8000),
lag_index_direction_(0),
current_lag_index_(0),
@@ -57,19 +58,19 @@
virtual ~Expand() {}
// Resets the object.
- void Reset();
+ virtual void Reset();
// The main method to produce concealment data. The data is appended to the
// end of |output|.
- int Process(AudioMultiVector* output);
+ virtual int Process(AudioMultiVector* output);
// Prepare the object to do extra expansion during normal operation following
// a period of expands.
- void SetParametersForNormalAfterExpand();
+ virtual void SetParametersForNormalAfterExpand();
// Prepare the object to do extra expansion during merge operation following
// a period of expands.
- void SetParametersForMergeAfterExpand();
+ virtual void SetParametersForMergeAfterExpand();
// Sets the mute factor for |channel| to |value|.
void SetMuteFactor(int16_t value, size_t channel) {
@@ -84,9 +85,38 @@
}
// Accessors and mutators.
- size_t overlap_length() const { return overlap_length_; }
+ virtual size_t overlap_length() const { return overlap_length_; }
int16_t max_lag() const { return max_lag_; }
+ protected:
+ static const int kMaxConsecutiveExpands = 200;
+ void GenerateRandomVector(int seed_increment,
+ size_t length,
+ int16_t* random_vector);
+
+ void GenerateBackgroundNoise(int16_t* random_vector,
+ size_t channel,
+ int16_t mute_slope,
+ bool too_many_expands,
+ size_t num_noise_samples,
+ int16_t* buffer);
+
+ // Initializes member variables at the beginning of an expand period.
+ void InitializeForAnExpandPeriod();
+
+ bool TooManyExpands();
+
+ // Analyzes the signal history in |sync_buffer_|, and set up all parameters
+ // necessary to produce concealment data.
+ void AnalyzeSignal(int16_t* random_vector);
+
+ RandomVector* random_vector_;
+ SyncBuffer* sync_buffer_;
+ bool first_expand_;
+ const int fs_hz_;
+ const size_t num_channels_;
+ int consecutive_expands_;
+
private:
static const int kUnvoicedLpcOrder = 6;
static const int kNumCorrelationCandidates = 3;
@@ -94,7 +124,6 @@
static const int kLpcAnalysisLength = 160;
static const int kMaxSampleRate = 48000;
static const int kNumLags = 3;
- static const int kMaxConsecutiveExpands = 200;
struct ChannelParameters {
// Constructor.
@@ -122,10 +151,6 @@
int16_t mute_slope; /* Q20 */
};
- // Analyze the signal history in |sync_buffer_|, and set up all parameters
- // necessary to produce concealment data.
- void AnalyzeSignal(int16_t* random_vector);
-
// Calculate the auto-correlation of |input|, with length |input_length|
// samples. The correlation is calculated from a downsampled version of
// |input|, and is written to |output|. The scale factor is written to
@@ -136,13 +161,7 @@
void UpdateLagIndex();
BackgroundNoise* background_noise_;
- SyncBuffer* sync_buffer_;
- RandomVector* random_vector_;
- bool first_expand_;
- const int fs_hz_;
- const size_t num_channels_;
const size_t overlap_length_;
- int consecutive_expands_;
int16_t max_lag_;
size_t expand_lags_[kNumLags];
int lag_index_direction_;
diff --git a/webrtc/modules/audio_coding/neteq4/interface/neteq.h b/webrtc/modules/audio_coding/neteq4/interface/neteq.h
index 466882a..c0f7fd6 100644
--- a/webrtc/modules/audio_coding/neteq4/interface/neteq.h
+++ b/webrtc/modules/audio_coding/neteq4/interface/neteq.h
@@ -108,7 +108,8 @@
// Creates a new NetEq object, starting at the sample rate |sample_rate_hz|.
// (Note that it will still change the sample rate depending on what payloads
// are being inserted; |sample_rate_hz| is just for startup configuration.)
- static NetEq* Create(int sample_rate_hz);
+ static NetEq* Create(int sample_rate_hz,
+ bool enable_audio_classifier = false);
virtual ~NetEq() {}
diff --git a/webrtc/modules/audio_coding/neteq4/merge.cc b/webrtc/modules/audio_coding/neteq4/merge.cc
index 4b56016..90068bb 100644
--- a/webrtc/modules/audio_coding/neteq4/merge.cc
+++ b/webrtc/modules/audio_coding/neteq4/merge.cc
@@ -20,6 +20,7 @@
#include "webrtc/modules/audio_coding/neteq4/dsp_helper.h"
#include "webrtc/modules/audio_coding/neteq4/expand.h"
#include "webrtc/modules/audio_coding/neteq4/sync_buffer.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
namespace webrtc {
@@ -307,9 +308,11 @@
stop_position_downsamp, correlation_shift, 1);
// Normalize correlation to 14 bits and copy to a 16-bit array.
- static const int kPadLength = 4;
- int16_t correlation16[kPadLength + kMaxCorrelationLength + kPadLength] = {0};
- int16_t* correlation_ptr = &correlation16[kPadLength];
+ const int pad_length = static_cast<int>(expand_->overlap_length() - 1);
+ const int correlation_buffer_size = 2 * pad_length + kMaxCorrelationLength;
+ scoped_ptr<int16_t[]> correlation16(new int16_t[correlation_buffer_size]);
+ memset(correlation16.get(), 0, correlation_buffer_size * sizeof(int16_t));
+ int16_t* correlation_ptr = &correlation16[pad_length];
int32_t max_correlation = WebRtcSpl_MaxAbsValueW32(correlation,
stop_position_downsamp);
int16_t norm_shift = std::max(0, 17 - WebRtcSpl_NormW32(max_correlation));
@@ -332,7 +335,7 @@
// start index |start_index_downsamp| and the effective array length.
int modified_stop_pos =
std::min(stop_position_downsamp,
- kMaxCorrelationLength + kPadLength - start_index_downsamp);
+ kMaxCorrelationLength + pad_length - start_index_downsamp);
int best_correlation_index;
int16_t best_correlation;
static const int kNumCorrelationCandidates = 1;
@@ -355,4 +358,9 @@
return best_correlation_index;
}
+int Merge::RequiredFutureSamples() {
+ return static_cast<int>(fs_hz_ / 100 * num_channels_); // 10 ms.
+}
+
+
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/neteq4/merge.h b/webrtc/modules/audio_coding/neteq4/merge.h
index f1f64e6c..213b487 100644
--- a/webrtc/modules/audio_coding/neteq4/merge.h
+++ b/webrtc/modules/audio_coding/neteq4/merge.h
@@ -35,8 +35,8 @@
public:
Merge(int fs_hz, size_t num_channels, Expand* expand, SyncBuffer* sync_buffer)
: fs_hz_(fs_hz),
- fs_mult_(fs_hz_ / 8000),
num_channels_(num_channels),
+ fs_mult_(fs_hz_ / 8000),
timestamps_per_call_(fs_hz_ / 100),
expand_(expand),
sync_buffer_(sync_buffer),
@@ -44,6 +44,8 @@
assert(num_channels_ > 0);
}
+ virtual ~Merge() {}
+
// The main method to produce the audio data. The decoded data is supplied in
// |input|, having |input_length| samples in total for all channels
// (interleaved). The result is written to |output|. The number of channels
@@ -51,9 +53,15 @@
// de-interleaving |input|. The values in |external_mute_factor_array| (Q14)
// will be used to scale the audio, and is updated in the process. The array
// must have |num_channels_| elements.
- int Process(int16_t* input, size_t input_length,
- int16_t* external_mute_factor_array,
- AudioMultiVector* output);
+ virtual int Process(int16_t* input, size_t input_length,
+ int16_t* external_mute_factor_array,
+ AudioMultiVector* output);
+
+ virtual int RequiredFutureSamples();
+
+ protected:
+ const int fs_hz_;
+ const size_t num_channels_;
private:
static const int kMaxSampleRate = 48000;
@@ -87,9 +95,7 @@
int start_position, int input_length,
int expand_period) const;
- const int fs_hz_;
const int fs_mult_; // fs_hz_ / 8000.
- const size_t num_channels_;
const int timestamps_per_call_;
Expand* expand_;
SyncBuffer* sync_buffer_;
diff --git a/webrtc/modules/audio_coding/neteq4/neteq.cc b/webrtc/modules/audio_coding/neteq4/neteq.cc
index a64f01b..9f36a96 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq.cc
+++ b/webrtc/modules/audio_coding/neteq4/neteq.cc
@@ -28,7 +28,7 @@
// Creates all classes needed and inject them into a new NetEqImpl object.
// Return the new object.
-NetEq* NetEq::Create(int sample_rate_hz) {
+NetEq* NetEq::Create(int sample_rate_hz, bool enable_audio_classifier) {
BufferLevelFilter* buffer_level_filter = new BufferLevelFilter;
DecoderDatabase* decoder_database = new DecoderDatabase;
DelayPeakDetector* delay_peak_detector = new DelayPeakDetector;
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_impl.cc b/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
index 8ab6205..e407ee8 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
@@ -61,7 +61,8 @@
TimestampScaler* timestamp_scaler,
AccelerateFactory* accelerate_factory,
ExpandFactory* expand_factory,
- PreemptiveExpandFactory* preemptive_expand_factory)
+ PreemptiveExpandFactory* preemptive_expand_factory,
+ bool create_components)
: buffer_level_filter_(buffer_level_filter),
decoder_database_(decoder_database),
delay_manager_(delay_manager),
@@ -103,13 +104,9 @@
output_size_samples_ = kOutputSizeMs * 8 * fs_mult_;
decoder_frame_length_ = 3 * output_size_samples_;
WebRtcSpl_Init();
- decision_logic_.reset(DecisionLogic::Create(fs_hz_, output_size_samples_,
- kPlayoutOn,
- decoder_database_.get(),
- *packet_buffer_.get(),
- delay_manager_.get(),
- buffer_level_filter_.get()));
- SetSampleRateAndChannels(fs, 1); // Default is 1 channel.
+ if (create_components) {
+ SetSampleRateAndChannels(fs, 1); // Default is 1 channel.
+ }
}
NetEqImpl::~NetEqImpl() {
@@ -284,12 +281,7 @@
CriticalSectionScoped lock(crit_sect_.get());
if (!decision_logic_.get() || mode != decision_logic_->playout_mode()) {
// The reset() method calls delete for the old object.
- decision_logic_.reset(DecisionLogic::Create(fs_hz_, output_size_samples_,
- mode,
- decoder_database_.get(),
- *packet_buffer_.get(),
- delay_manager_.get(),
- buffer_level_filter_.get()));
+ CreateDecisionLogic(mode);
}
}
@@ -948,7 +940,7 @@
return 0;
}
- decision_logic_->ExpandDecision(*operation == kExpand);
+ decision_logic_->ExpandDecision(*operation);
// Check conditions for reset.
if (new_codec_ || *operation == kUndefined) {
@@ -1067,6 +1059,11 @@
// Move on with the preemptive expand decision.
break;
}
+ case kMerge: {
+ required_samples =
+ std::max(merge_->RequiredFutureSamples(), required_samples);
+ break;
+ }
default: {
// Do nothing.
}
@@ -1834,6 +1831,14 @@
return extracted_samples;
}
+void NetEqImpl::UpdatePlcComponents(int fs_hz, size_t channels) {
+ // Delete objects and create new ones.
+ expand_.reset(expand_factory_->Create(background_noise_.get(),
+ sync_buffer_.get(), &random_vector_,
+ fs_hz, channels));
+ merge_.reset(new Merge(fs_hz, channels, expand_.get(), sync_buffer_.get()));
+}
+
void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) {
LOG_API2(fs_hz, channels);
// TODO(hlundin): Change to an enumerator and skip assert.
@@ -1881,21 +1886,20 @@
// Reset random vector.
random_vector_.Reset();
- // Delete Expand object and create a new one.
- expand_.reset(expand_factory_->Create(background_noise_.get(),
- sync_buffer_.get(), &random_vector_,
- fs_hz, channels));
+ UpdatePlcComponents(fs_hz, channels);
+
// Move index so that we create a small set of future samples (all 0).
sync_buffer_->set_next_index(sync_buffer_->next_index() -
- expand_->overlap_length());
+ expand_->overlap_length());
normal_.reset(new Normal(fs_hz, decoder_database_.get(), *background_noise_,
expand_.get()));
- merge_.reset(new Merge(fs_hz, channels, expand_.get(), sync_buffer_.get()));
accelerate_.reset(
accelerate_factory_->Create(fs_hz, channels, *background_noise_));
- preemptive_expand_.reset(
- preemptive_expand_factory_->Create(fs_hz, channels, *background_noise_));
+ preemptive_expand_.reset(preemptive_expand_factory_->Create(
+ fs_hz, channels,
+ *background_noise_,
+ static_cast<int>(expand_->overlap_length())));
// Delete ComfortNoise object and create a new one.
comfort_noise_.reset(new ComfortNoise(fs_hz, decoder_database_.get(),
@@ -1908,8 +1912,11 @@
decoded_buffer_.reset(new int16_t[decoded_buffer_length_]);
}
- // Communicate new sample rate and output size to DecisionLogic object.
- assert(decision_logic_.get());
+ // Create DecisionLogic if it is not created yet, then communicate new sample
+ // rate and output size to DecisionLogic object.
+ if (!decision_logic_.get()) {
+ CreateDecisionLogic(kPlayoutOn);
+ }
decision_logic_->SetSampleRate(fs_hz_, output_size_samples_);
}
@@ -1930,4 +1937,12 @@
}
}
+void NetEqImpl::CreateDecisionLogic(NetEqPlayoutMode mode) {
+ decision_logic_.reset(DecisionLogic::Create(fs_hz_, output_size_samples_,
+ mode,
+ decoder_database_.get(),
+ *packet_buffer_.get(),
+ delay_manager_.get(),
+ buffer_level_filter_.get()));
+}
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_impl.h b/webrtc/modules/audio_coding/neteq4/neteq_impl.h
index dabf2d6..3d883a0 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_impl.h
+++ b/webrtc/modules/audio_coding/neteq4/neteq_impl.h
@@ -70,7 +70,8 @@
TimestampScaler* timestamp_scaler,
AccelerateFactory* accelerate_factory,
ExpandFactory* expand_factory,
- PreemptiveExpandFactory* preemptive_expand_factory);
+ PreemptiveExpandFactory* preemptive_expand_factory,
+ bool create_components = true);
virtual ~NetEqImpl();
@@ -203,7 +204,7 @@
// This accessor method is only intended for testing purposes.
virtual const SyncBuffer* sync_buffer_for_test() const;
- private:
+ protected:
static const int kOutputSizeMs = 10;
static const int kMaxFrameSize = 2880; // 60 ms @ 48 kHz.
// TODO(hlundin): Provide a better value for kSyncBufferSize.
@@ -331,6 +332,14 @@
// GetAudio().
NetEqOutputType LastOutputType() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // Updates Expand and Merge.
+ virtual void UpdatePlcComponents(int fs_hz, size_t channels)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // Creates DecisionLogic object for the given mode.
+ void CreateDecisionLogic(NetEqPlayoutMode mode)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
const scoped_ptr<BufferLevelFilter> buffer_level_filter_;
const scoped_ptr<DecoderDatabase> decoder_database_;
const scoped_ptr<DelayManager> delay_manager_;
@@ -388,6 +397,7 @@
int decoded_packet_sequence_number_ GUARDED_BY(crit_sect_);
uint32_t decoded_packet_timestamp_ GUARDED_BY(crit_sect_);
+ private:
DISALLOW_COPY_AND_ASSIGN(NetEqImpl);
};
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi b/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi
index 9d0aa42..dda2a1c 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi
+++ b/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi
@@ -49,6 +49,7 @@
'CODEC_PCM16B_WB',
'CODEC_ISAC_SWB',
'CODEC_PCM16B_32KHZ',
+ 'CODEC_PCM16B_48KHZ',
'CODEC_CNGCODEC8',
'CODEC_CNGCODEC16',
'CODEC_CNGCODEC32',
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq4/neteq_unittest.cc
index 365e233..1e8c128 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq4/neteq_unittest.cc
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <string.h> // memset
+#include <algorithm>
#include <set>
#include <string>
#include <vector>
@@ -232,6 +233,7 @@
unsigned int sim_clock_;
int16_t out_data_[kMaxBlockSize];
int output_sample_rate_;
+ int algorithmic_delay_ms_;
};
// Allocating the static const so that it can be passed by reference.
@@ -246,12 +248,16 @@
: neteq_(NULL),
rtp_fp_(NULL),
sim_clock_(0),
- output_sample_rate_(kInitSampleRateHz) {
+ output_sample_rate_(kInitSampleRateHz),
+ algorithmic_delay_ms_(0) {
memset(out_data_, 0, sizeof(out_data_));
}
void NetEqDecodingTest::SetUp() {
neteq_ = NetEq::Create(kInitSampleRateHz);
+ NetEqNetworkStatistics stat;
+ ASSERT_EQ(0, neteq_->NetworkStatistics(&stat));
+ algorithmic_delay_ms_ = stat.current_buffer_size_ms;
ASSERT_TRUE(neteq_);
LoadDecoders();
}
@@ -483,8 +489,8 @@
ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
// To be able to test the fading of background noise we need at lease to pull
- // 610 frames.
- const int kFadingThreshold = 610;
+ // 611 frames.
+ const int kFadingThreshold = 611;
// Test several CNG-to-PLC packet for the expected behavior. The number 20 is
// arbitrary, but sufficiently large to test enough number of frames.
@@ -1110,12 +1116,16 @@
// First insert several noise like packets, then sync-packets. Decoding all
// packets should not produce error, statistics should not show any packet loss
// and sync-packets should decode to zero.
+// TODO(turajs) we will have a better test if we have a referece NetEq, and
+// when Sync packets are inserted in "test" NetEq we insert all-zero payload
+// in reference NetEq and compare the output of those two.
TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(SyncPacketDecode)) {
WebRtcRTPHeader rtp_info;
PopulateRtpInfo(0, 0, &rtp_info);
const int kPayloadBytes = kBlockSize16kHz * sizeof(int16_t);
uint8_t payload[kPayloadBytes];
int16_t decoded[kBlockSize16kHz];
+ int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1;
for (int n = 0; n < kPayloadBytes; ++n) {
payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence.
}
@@ -1125,7 +1135,6 @@
int num_channels;
int samples_per_channel;
uint32_t receive_timestamp = 0;
- int delay_samples = 0;
for (int n = 0; n < 100; ++n) {
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
receive_timestamp));
@@ -1135,16 +1144,15 @@
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
ASSERT_EQ(1, num_channels);
- // Even if there is RTP packet in NetEq's buffer, the first frame pulled
- // from NetEq starts with few zero samples. Here we measure this delay.
- if (n == 0) {
- while (decoded[delay_samples] == 0) delay_samples++;
- }
rtp_info.header.sequenceNumber++;
rtp_info.header.timestamp += kBlockSize16kHz;
receive_timestamp += kBlockSize16kHz;
}
const int kNumSyncPackets = 10;
+
+ // Make sure sufficient number of sync packets are inserted that we can
+ // conduct a test.
+ ASSERT_GT(kNumSyncPackets, algorithmic_frame_delay);
// Insert sync-packets, the decoded sequence should be all-zero.
for (int n = 0; n < kNumSyncPackets; ++n) {
ASSERT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
@@ -1153,30 +1161,37 @@
&output_type));
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
ASSERT_EQ(1, num_channels);
- EXPECT_TRUE(IsAllZero(&decoded[delay_samples],
- samples_per_channel * num_channels - delay_samples));
- delay_samples = 0; // Delay only matters in the first frame.
+ if (n > algorithmic_frame_delay) {
+ EXPECT_TRUE(IsAllZero(decoded, samples_per_channel * num_channels));
+ }
rtp_info.header.sequenceNumber++;
rtp_info.header.timestamp += kBlockSize16kHz;
receive_timestamp += kBlockSize16kHz;
}
- // We insert a regular packet, if sync packet are not correctly buffered then
+
+ // We insert regular packets, if sync packet are not correctly buffered then
// network statistics would show some packet loss.
- ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
- receive_timestamp));
- ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
- &samples_per_channel, &num_channels,
- &output_type));
- // Make sure the last inserted packet is decoded and there are non-zero
- // samples.
- EXPECT_FALSE(IsAllZero(decoded, samples_per_channel * num_channels));
+ for (int n = 0; n <= algorithmic_frame_delay + 10; ++n) {
+ ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
+ receive_timestamp));
+ ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
+ &samples_per_channel, &num_channels,
+ &output_type));
+ if (n >= algorithmic_frame_delay + 1) {
+ // Expect that this frame contain samples from regular RTP.
+ EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels));
+ }
+ rtp_info.header.sequenceNumber++;
+ rtp_info.header.timestamp += kBlockSize16kHz;
+ receive_timestamp += kBlockSize16kHz;
+ }
NetEqNetworkStatistics network_stats;
ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
// Expecting a "clean" network.
EXPECT_EQ(0, network_stats.packet_loss_rate);
EXPECT_EQ(0, network_stats.expand_rate);
EXPECT_EQ(0, network_stats.accelerate_rate);
- EXPECT_EQ(0, network_stats.preemptive_rate);
+ EXPECT_LE(network_stats.preemptive_rate, 150);
}
// Test if the size of the packet buffer reported correctly when containing
@@ -1199,7 +1214,8 @@
int num_channels;
int samples_per_channel;
uint32_t receive_timestamp = 0;
- for (int n = 0; n < 1; ++n) {
+ int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1;
+ for (int n = 0; n < algorithmic_frame_delay; ++n) {
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
receive_timestamp));
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
@@ -1225,7 +1241,8 @@
}
NetEqNetworkStatistics network_stats;
ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
- EXPECT_EQ(kNumSyncPackets * 10, network_stats.current_buffer_size_ms);
+ EXPECT_EQ(kNumSyncPackets * 10 + algorithmic_delay_ms_,
+ network_stats.current_buffer_size_ms);
// Rewind |rtp_info| to that of the first sync packet.
memcpy(&rtp_info, &first_sync_packet_rtp_info, sizeof(rtp_info));
@@ -1298,7 +1315,8 @@
if (packets_inserted > 4) {
// Expect preferred and actual buffer size to be no more than 2 frames.
EXPECT_LE(network_stats.preferred_buffer_size_ms, kFrameSizeMs * 2);
- EXPECT_LE(network_stats.current_buffer_size_ms, kFrameSizeMs * 2);
+ EXPECT_LE(network_stats.current_buffer_size_ms, kFrameSizeMs * 2 +
+ algorithmic_delay_ms_);
}
last_seq_no = seq_no;
last_timestamp = timestamp;
@@ -1362,6 +1380,8 @@
const int kSamples = kFrameSizeMs * kSampleRateKhz;
const int kPayloadBytes = kSamples * 2;
+ const int algorithmic_delay_samples = std::max(
+ algorithmic_delay_ms_ * kSampleRateKhz, 5 * kSampleRateKhz / 8);
// Insert three speech packet. Three are needed to get the frame length
// correct.
int out_len;
@@ -1398,7 +1418,7 @@
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
ASSERT_EQ(kBlockSize16kHz, out_len);
EXPECT_EQ(kOutputCNG, type);
- EXPECT_EQ(timestamp - 10, neteq_->PlayoutTimestamp());
+ EXPECT_EQ(timestamp - algorithmic_delay_samples, neteq_->PlayoutTimestamp());
// Insert the same CNG packet again. Note that at this point it is old, since
// we have already decoded the first copy of it.
@@ -1412,7 +1432,8 @@
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
ASSERT_EQ(kBlockSize16kHz, out_len);
EXPECT_EQ(kOutputCNG, type);
- EXPECT_EQ(timestamp - 10, neteq_->PlayoutTimestamp());
+ EXPECT_EQ(timestamp - algorithmic_delay_samples,
+ neteq_->PlayoutTimestamp());
}
// Insert speech again.
@@ -1427,7 +1448,8 @@
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
ASSERT_EQ(kBlockSize16kHz, out_len);
EXPECT_EQ(kOutputNormal, type);
- EXPECT_EQ(timestamp + kSamples - 10, neteq_->PlayoutTimestamp());
+ EXPECT_EQ(timestamp + kSamples - algorithmic_delay_samples,
+ neteq_->PlayoutTimestamp());
}
TEST_F(NetEqDecodingTest, DiscardDuplicateCng) { DuplicateCng(); }
diff --git a/webrtc/modules/audio_coding/neteq4/preemptive_expand.cc b/webrtc/modules/audio_coding/neteq4/preemptive_expand.cc
index c7ce310..dace45e 100644
--- a/webrtc/modules/audio_coding/neteq4/preemptive_expand.cc
+++ b/webrtc/modules/audio_coding/neteq4/preemptive_expand.cc
@@ -101,8 +101,10 @@
PreemptiveExpand* PreemptiveExpandFactory::Create(
int sample_rate_hz,
size_t num_channels,
- const BackgroundNoise& background_noise) const {
- return new PreemptiveExpand(sample_rate_hz, num_channels, background_noise);
+ const BackgroundNoise& background_noise,
+ int overlap_samples) const {
+ return new PreemptiveExpand(
+ sample_rate_hz, num_channels, background_noise, overlap_samples);
}
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/neteq4/preemptive_expand.h b/webrtc/modules/audio_coding/neteq4/preemptive_expand.h
index 241425e..983f64d 100644
--- a/webrtc/modules/audio_coding/neteq4/preemptive_expand.h
+++ b/webrtc/modules/audio_coding/neteq4/preemptive_expand.h
@@ -29,11 +29,13 @@
// PreemptiveExpand are implemented.
class PreemptiveExpand : public TimeStretch {
public:
- PreemptiveExpand(int sample_rate_hz, size_t num_channels,
- const BackgroundNoise& background_noise)
+ PreemptiveExpand(int sample_rate_hz,
+ size_t num_channels,
+ const BackgroundNoise& background_noise,
+ int overlap_samples)
: TimeStretch(sample_rate_hz, num_channels, background_noise),
old_data_length_per_channel_(-1),
- overlap_samples_(5 * sample_rate_hz / 8000) {
+ overlap_samples_(overlap_samples) {
}
virtual ~PreemptiveExpand() {}
@@ -77,7 +79,8 @@
virtual PreemptiveExpand* Create(
int sample_rate_hz,
size_t num_channels,
- const BackgroundNoise& background_noise) const;
+ const BackgroundNoise& background_noise,
+ int overlap_samples) const;
};
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/neteq4/sync_buffer.h b/webrtc/modules/audio_coding/neteq4/sync_buffer.h
index e1e5daf..0659f19 100644
--- a/webrtc/modules/audio_coding/neteq4/sync_buffer.h
+++ b/webrtc/modules/audio_coding/neteq4/sync_buffer.h
@@ -78,7 +78,8 @@
// created.
void Flush();
- const AudioVector& Channel(size_t n) { return *channels_[n]; }
+ const AudioVector& Channel(size_t n) const { return *channels_[n]; }
+ AudioVector& Channel(size_t n) { return *channels_[n]; }
// Accessors and mutators.
size_t next_index() const { return next_index_; }
diff --git a/webrtc/modules/audio_coding/neteq4/time_stretch_unittest.cc b/webrtc/modules/audio_coding/neteq4/time_stretch_unittest.cc
index 188c18b..529038a 100644
--- a/webrtc/modules/audio_coding/neteq4/time_stretch_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq4/time_stretch_unittest.cc
@@ -21,14 +21,17 @@
TEST(TimeStretch, CreateAndDestroy) {
const int kSampleRate = 8000;
const size_t kNumChannels = 1;
+ const int kOverlapSamples = 5 * kSampleRate / 8000;
BackgroundNoise bgn(kNumChannels);
Accelerate accelerate(kSampleRate, kNumChannels, bgn);
- PreemptiveExpand preemptive_expand(kSampleRate, kNumChannels, bgn);
+ PreemptiveExpand preemptive_expand(
+ kSampleRate, kNumChannels, bgn, kOverlapSamples);
}
TEST(TimeStretch, CreateUsingFactory) {
const int kSampleRate = 8000;
const size_t kNumChannels = 1;
+ const int kOverlapSamples = 5 * kSampleRate / 8000;
BackgroundNoise bgn(kNumChannels);
AccelerateFactory accelerate_factory;
@@ -38,8 +41,8 @@
delete accelerate;
PreemptiveExpandFactory preemptive_expand_factory;
- PreemptiveExpand* preemptive_expand =
- preemptive_expand_factory.Create(kSampleRate, kNumChannels, bgn);
+ PreemptiveExpand* preemptive_expand = preemptive_expand_factory.Create(
+ kSampleRate, kNumChannels, bgn, kOverlapSamples);
EXPECT_TRUE(preemptive_expand != NULL);
delete preemptive_expand;
}