@@ -156,41 +156,30 @@ void ComputeAutoCorrelation(
156
156
}
157
157
}
158
158
159
- int FindBestPitchPeriods24kHz (
159
+ int ComputePitchPeriod24kHz (
160
+ rtc::ArrayView<const float , kBufSize24kHz > pitch_buffer,
160
161
rtc::ArrayView<const float , kInitialNumLags24kHz > auto_correlation,
161
- rtc::ArrayView<const float , kBufSize24kHz > pitch_buffer ) {
162
+ rtc::ArrayView<const float , kRefineNumLags24kHz > y_energy ) {
162
163
static_assert (kMaxPitch24kHz > kInitialNumLags24kHz , " " );
163
164
static_assert (kMaxPitch24kHz < kBufSize24kHz , " " );
164
- // Initialize the sliding 20 ms frame energy.
165
- // TODO(bugs.webrtc.org/9076): Maybe optimize using vectorization.
166
- float denominator = std::inner_product (
167
- pitch_buffer.begin (), pitch_buffer.begin () + kFrameSize20ms24kHz + 1 ,
168
- pitch_buffer.begin (), 1 .f );
169
- // Search best pitch by looking at the scaled auto-correlation.
170
165
int best_inverted_lag = 0 ; // Pitch period.
171
166
float best_numerator = -1 .f ; // Pitch strength numerator.
172
167
float best_denominator = 0 .f ; // Pitch strength denominator.
173
168
for (int inverted_lag = 0 ; inverted_lag < kInitialNumLags24kHz ;
174
169
++inverted_lag) {
175
170
// A pitch candidate must have positive correlation.
176
171
if (auto_correlation[inverted_lag] > 0 .f ) {
172
+ // Auto-correlation energy normalized by frame energy.
177
173
const float numerator =
178
174
auto_correlation[inverted_lag] * auto_correlation[inverted_lag];
175
+ const float denominator = y_energy[kMaxPitch24kHz - inverted_lag];
179
176
// Compare numerator/denominator ratios without using divisions.
180
177
if (numerator * best_denominator > best_numerator * denominator) {
181
178
best_inverted_lag = inverted_lag;
182
179
best_numerator = numerator;
183
180
best_denominator = denominator;
184
181
}
185
182
}
186
- // Update |denominator| for the next inverted lag.
187
- static_assert (kInitialNumLags24kHz + kFrameSize20ms24kHz < kBufSize24kHz ,
188
- " " );
189
- const float y_old = pitch_buffer[inverted_lag];
190
- const float y_new = pitch_buffer[inverted_lag + kFrameSize20ms24kHz ];
191
- denominator -= y_old * y_old;
192
- denominator += y_new * y_new;
193
- denominator = std::max (0 .f , denominator);
194
183
}
195
184
return best_inverted_lag;
196
185
}
@@ -341,6 +330,7 @@ CandidatePitchPeriods ComputePitchPeriod12kHz(
341
330
342
331
int ComputePitchPeriod48kHz (
343
332
rtc::ArrayView<const float , kBufSize24kHz > pitch_buffer,
333
+ rtc::ArrayView<const float , kRefineNumLags24kHz > y_energy,
344
334
CandidatePitchPeriods pitch_candidates) {
345
335
// Compute the auto-correlation terms only for neighbors of the given pitch
346
336
// candidates (similar to what is done in ComputePitchAutoCorrelation(), but
@@ -369,14 +359,15 @@ int ComputePitchPeriod48kHz(
369
359
}
370
360
// Find best pitch at 24 kHz.
371
361
const int pitch_candidate_24kHz =
372
- FindBestPitchPeriods24kHz ( auto_correlation, pitch_buffer );
362
+ ComputePitchPeriod24kHz (pitch_buffer, auto_correlation, y_energy );
373
363
// Pseudo-interpolation.
374
364
return PitchPseudoInterpolationInvLagAutoCorr (pitch_candidate_24kHz,
375
365
auto_correlation);
376
366
}
377
367
378
368
PitchInfo ComputeExtendedPitchPeriod48kHz (
379
369
rtc::ArrayView<const float , kBufSize24kHz > pitch_buffer,
370
+ rtc::ArrayView<const float , kRefineNumLags24kHz > y_energy,
380
371
int initial_pitch_period_48kHz,
381
372
PitchInfo last_pitch_48kHz) {
382
373
RTC_DCHECK_LE (kMinPitch48kHz , initial_pitch_period_48kHz);
@@ -386,34 +377,30 @@ PitchInfo ComputeExtendedPitchPeriod48kHz(
386
377
struct RefinedPitchCandidate {
387
378
int period;
388
379
float strength;
389
- // Additional strength data used for the final estimation of the strength .
390
- float xy; // Cross -correlation.
391
- float yy ; // Auto-correlation .
380
+ // Additional strength data used for the final pitch estimation .
381
+ float xy; // Auto -correlation.
382
+ float y_energy ; // Energy of the sliding frame `y` .
392
383
};
393
384
394
- // Initialize.
395
- std::array<float , kRefineNumLags24kHz > yy_values;
396
- // TODO(bugs.webrtc.org/9076): Reuse values from FindBestPitchPeriods24kHz().
397
- ComputeSlidingFrameSquareEnergies24kHz (pitch_buffer, yy_values);
398
- const float xx = yy_values[0 ];
399
- const auto pitch_strength = [](float xy, float yy, float xx) {
400
- RTC_DCHECK_GE (xx * yy, 0 .f );
401
- return xy / std::sqrt (1 .f + xx * yy);
385
+ const float x_energy = y_energy[0 ];
386
+ const auto pitch_strength = [x_energy](float xy, float y_energy) {
387
+ RTC_DCHECK_GE (x_energy * y_energy, 0 .f );
388
+ return xy / std::sqrt (1 .f + x_energy * y_energy);
402
389
};
403
- // Initial pitch candidate.
390
+
391
+ // Initialize the best pitch candidate with `initial_pitch_period_48kHz`.
404
392
RefinedPitchCandidate best_pitch;
405
393
best_pitch.period =
406
394
std::min (initial_pitch_period_48kHz / 2 , kMaxPitch24kHz - 1 );
407
395
best_pitch.xy =
408
396
ComputeAutoCorrelation (kMaxPitch24kHz - best_pitch.period , pitch_buffer);
409
- best_pitch.yy = yy_values [best_pitch.period ];
410
- best_pitch.strength = pitch_strength (best_pitch.xy , best_pitch.yy , xx );
411
-
412
- // 24 kHz version of the last estimated pitch and copy of the initial
413
- // estimation .
397
+ best_pitch.y_energy = y_energy [best_pitch.period ];
398
+ best_pitch.strength = pitch_strength (best_pitch.xy , best_pitch.y_energy );
399
+ // Keep a copy of the initial pitch candidate.
400
+ const PitchInfo initial_pitch{best_pitch. period , best_pitch. strength };
401
+ // 24 kHz version of the last estimated pitch .
414
402
const PitchInfo last_pitch{last_pitch_48kHz.period / 2 ,
415
403
last_pitch_48kHz.strength };
416
- const PitchInfo initial_pitch{best_pitch.period , best_pitch.strength };
417
404
418
405
// Find `max_period_divisor` such that the result of
419
406
// `GetAlternativePitchPeriod(initial_pitch_period, 1, max_period_divisor)`
@@ -443,14 +430,14 @@ PitchInfo ComputeExtendedPitchPeriod48kHz(
443
430
// Compute an auto-correlation score for the primary pitch candidate
444
431
// |alternative_pitch.period| by also looking at its possible sub-harmonic
445
432
// |dual_alternative_period|.
446
- float xy_primary_period = ComputeAutoCorrelation (
433
+ const float xy_primary_period = ComputeAutoCorrelation (
447
434
kMaxPitch24kHz - alternative_pitch.period , pitch_buffer);
448
- float xy_secondary_period = ComputeAutoCorrelation (
435
+ const float xy_secondary_period = ComputeAutoCorrelation (
449
436
kMaxPitch24kHz - dual_alternative_period, pitch_buffer);
450
- float xy = 0 .5f * (xy_primary_period + xy_secondary_period);
451
- float yy = 0 .5f * (yy_values [alternative_pitch.period ] +
452
- yy_values [dual_alternative_period]);
453
- alternative_pitch.strength = pitch_strength (xy, yy, xx );
437
+ const float xy = 0 .5f * (xy_primary_period + xy_secondary_period);
438
+ const float yy = 0 .5f * (y_energy [alternative_pitch.period ] +
439
+ y_energy [dual_alternative_period]);
440
+ alternative_pitch.strength = pitch_strength (xy, yy);
454
441
455
442
// Maybe update best period.
456
443
if (IsAlternativePitchStrongerThanInitial (
@@ -462,10 +449,11 @@ PitchInfo ComputeExtendedPitchPeriod48kHz(
462
449
463
450
// Final pitch strength and period.
464
451
best_pitch.xy = std::max (0 .f , best_pitch.xy );
465
- RTC_DCHECK_LE (0 .f , best_pitch.yy );
466
- float final_pitch_strength = (best_pitch.yy <= best_pitch.xy )
467
- ? 1 .f
468
- : best_pitch.xy / (best_pitch.yy + 1 .f );
452
+ RTC_DCHECK_LE (0 .f , best_pitch.y_energy );
453
+ float final_pitch_strength =
454
+ (best_pitch.y_energy <= best_pitch.xy )
455
+ ? 1 .f
456
+ : best_pitch.xy / (best_pitch.y_energy + 1 .f );
469
457
final_pitch_strength = std::min (best_pitch.strength , final_pitch_strength);
470
458
int final_pitch_period_48kHz = std::max (
471
459
kMinPitch48kHz ,
0 commit comments