Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/modules/audio_coding/neteq/preemptive_expand.h"
12 :
13 : #include <algorithm> // min, max
14 :
15 : #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
16 :
17 : namespace webrtc {
18 :
19 0 : PreemptiveExpand::ReturnCodes PreemptiveExpand::Process(
20 : const int16_t* input,
21 : size_t input_length,
22 : size_t old_data_length,
23 : AudioMultiVector* output,
24 : size_t* length_change_samples) {
25 0 : old_data_length_per_channel_ = old_data_length;
26 : // Input length must be (almost) 30 ms.
27 : // Also, the new part must be at least |overlap_samples_| elements.
28 : static const size_t k15ms = 120; // 15 ms = 120 samples at 8 kHz sample rate.
29 0 : if (num_channels_ == 0 ||
30 0 : input_length / num_channels_ < (2 * k15ms - 1) * fs_mult_ ||
31 0 : old_data_length >= input_length / num_channels_ - overlap_samples_) {
32 : // Length of input data too short to do preemptive expand. Simply move all
33 : // data from input to output.
34 0 : output->PushBackInterleaved(input, input_length);
35 0 : return kError;
36 : }
37 0 : const bool kFastMode = false; // Fast mode is not available for PE Expand.
38 0 : return TimeStretch::Process(input, input_length, kFastMode, output,
39 0 : length_change_samples);
40 : }
41 :
42 0 : void PreemptiveExpand::SetParametersForPassiveSpeech(size_t len,
43 : int16_t* best_correlation,
44 : size_t* peak_index) const {
45 : // When the signal does not contain any active speech, the correlation does
46 : // not matter. Simply set it to zero.
47 0 : *best_correlation = 0;
48 :
49 : // For low energy expansion, the new data can be less than 15 ms,
50 : // but we must ensure that best_correlation is not larger than the length of
51 : // the new data.
52 : // but we must ensure that best_correlation is not larger than the new data.
53 0 : *peak_index = std::min(*peak_index,
54 0 : len - old_data_length_per_channel_);
55 0 : }
56 :
57 0 : PreemptiveExpand::ReturnCodes PreemptiveExpand::CheckCriteriaAndStretch(
58 : const int16_t* input,
59 : size_t input_length,
60 : size_t peak_index,
61 : int16_t best_correlation,
62 : bool active_speech,
63 : bool /*fast_mode*/,
64 : AudioMultiVector* output) const {
65 : // Pre-calculate common multiplication with |fs_mult_|.
66 : // 120 corresponds to 15 ms.
67 0 : size_t fs_mult_120 = static_cast<size_t>(fs_mult_ * 120);
68 : // Check for strong correlation (>0.9 in Q14) and at least 15 ms new data,
69 : // or passive speech.
70 0 : if (((best_correlation > kCorrelationThreshold) &&
71 0 : (old_data_length_per_channel_ <= fs_mult_120)) ||
72 0 : !active_speech) {
73 : // Do accelerate operation by overlap add.
74 :
75 : // Set length of the first part, not to be modified.
76 : size_t unmodified_length = std::max(old_data_length_per_channel_,
77 0 : fs_mult_120);
78 : // Copy first part, including cross-fade region.
79 0 : output->PushBackInterleaved(
80 0 : input, (unmodified_length + peak_index) * num_channels_);
81 : // Copy the last |peak_index| samples up to 15 ms to |temp_vector|.
82 0 : AudioMultiVector temp_vector(num_channels_);
83 0 : temp_vector.PushBackInterleaved(
84 0 : &input[(unmodified_length - peak_index) * num_channels_],
85 0 : peak_index * num_channels_);
86 : // Cross-fade |temp_vector| onto the end of |output|.
87 0 : output->CrossFade(temp_vector, peak_index);
88 : // Copy the last unmodified part, 15 ms + pitch period until the end.
89 0 : output->PushBackInterleaved(
90 0 : &input[unmodified_length * num_channels_],
91 0 : input_length - unmodified_length * num_channels_);
92 :
93 0 : if (active_speech) {
94 0 : return kSuccess;
95 : } else {
96 0 : return kSuccessLowEnergy;
97 : }
98 : } else {
99 : // Accelerate not allowed. Simply move all data from decoded to outData.
100 0 : output->PushBackInterleaved(input, input_length);
101 0 : return kNoStretch;
102 : }
103 : }
104 :
105 0 : PreemptiveExpand* PreemptiveExpandFactory::Create(
106 : int sample_rate_hz,
107 : size_t num_channels,
108 : const BackgroundNoise& background_noise,
109 : size_t overlap_samples) const {
110 : return new PreemptiveExpand(
111 0 : sample_rate_hz, num_channels, background_noise, overlap_samples);
112 : }
113 :
114 : } // namespace webrtc
|