^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SpanDSP - a series of DSP components for telephony
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * ec_disable_detector.h - A detector which should eventually meet the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * G.164/G.165 requirements for detecting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * 2100Hz echo cancellor disable tone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Written by Steve Underwood <steveu@coppice.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2001 Steve Underwood
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "dsp_biquad.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct ec_disable_detector_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct biquad2_state notch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int notch_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int channel_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int tone_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int tone_cycle_duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int good_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define FALSE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define TRUE (!FALSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) echo_can_disable_detector_init(struct ec_disable_detector_state *det)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Elliptic notch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* This is actually centred at 2095Hz, but gets the balance we want, due
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) to the asymmetric walls of the notch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) biquad2_init(&det->notch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) (int32_t)(-0.7600000 * 32768.0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) (int32_t)(-0.1183852 * 32768.0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) (int32_t)(-0.5104039 * 32768.0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) (int32_t)(0.1567596 * 32768.0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) (int32_t)(1.0000000 * 32768.0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) det->channel_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) det->notch_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) det->tone_present = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) det->tone_cycle_duration = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) det->good_cycles = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) det->hit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*- End of function --------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) echo_can_disable_detector_update(struct ec_disable_detector_state *det,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int16_t amp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int16_t notched;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) notched = biquad2(&det->notch, amp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Estimate the overall energy in the channel, and the energy in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) the notch (i.e. overall channel energy - tone energy => noise).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) Use abs instead of multiply for speed (is it really faster?).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) Damp the overall energy a little more for a stable result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) Damp the notch energy a little less, so we don't damp out the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) blip every time the phase reverses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) det->channel_level += ((abs(amp) - det->channel_level) >> 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) det->notch_level += ((abs(notched) - det->notch_level) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (det->channel_level > 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* There is adequate energy in the channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) Is it mostly at 2100Hz? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (det->notch_level * 6 < det->channel_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* The notch says yes, so we have the tone. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!det->tone_present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Do we get a kick every 450+-25ms? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (det->tone_cycle_duration >= 425 * 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) && det->tone_cycle_duration <= 475 * 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) det->good_cycles++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (det->good_cycles > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) det->hit = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) det->tone_cycle_duration = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) det->tone_present = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) det->tone_present = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) det->tone_cycle_duration++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) det->tone_present = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) det->tone_cycle_duration = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) det->good_cycles = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return det->hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*- End of function --------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*- End of file ------------------------------------------------------------*/