Skip to content

Fix the issue where detection is not possible only when freq1 is used. - #123

Open
cdevelop wants to merge 1 commit into
freeswitch:masterfrom
cdevelop:master
Open

cdevelop wants to merge 1 commit into
freeswitch:masterfrom
cdevelop:master

Conversation

@cdevelop

@cdevelop cdevelop commented Jun 18, 2026

Copy link
Copy Markdown

When only freq1 is configured and freq2 is set to zero, detection cannot be performed.
for example

<descriptors debug-level="0">
    <descriptor name="cn">
        <tone name="BUSY_TONE">
            <element freq1="450" min="300" max="400" freq2="0"/>
            <element freq1="0" min="300" max="400" freq2="0"/>
            <element freq1="450" min="300" max="400" freq2="0"/>
            <element freq1="0" min="300" max="400" freq2="0"/>
            <element freq1="450" min="300" max="400" freq2="0"/>
        </tone>
    </descriptor>
</descriptors>

@vcc-core

Copy link
Copy Markdown

With only one monitored frequency, super_tone_chunk() short-circuited to
k1 = k2 = 0 without ever looking at the Goertzel result. That had three
consequences:

  • goertzel_result() was never called, and since it is what terminates
    the block and resets the filter, the accumulator kept running across
    block boundaries.

  • The tone-to-total-energy test applied on the multi frequency path was
    skipped, so any signal above detection_threshold was treated as the
    monitored frequency, regardless of its spectrum.

  • k2 was reported as 0, but descriptor segments for single frequency
    tones carry f2 == -1, because add_super_tone_freq() returns -1 for a
    frequency of 0. A k2 of 0 therefore never matched such a segment and
    the tone was in fact never reported at all.

Read state[0], apply the same tone-to-total-energy test as the multi
frequency path, and report k1 = 0, k2 = -1 when it passes.

Also handle monitored_frequencies == 0, which happens for a descriptor
built purely from silence elements. state[] is a flexible array member
sized by monitored_frequencies, so state[0] must not be touched there;
report k1 = k2 = -1 instead.

    else
    {
        if (s->desc->monitored_frequencies < 1)
        {
            k1 = -1;
            k2 = -1;
        }
        else if (s->desc->monitored_frequencies < 2)
        {
            res[0] = goertzel_result(&s->state[0]);
            if (res[0] < tone_to_total_energy*s->energy)
            {
                k1 = -1;
                k2 = -1;
            }
            else
            {
                k1 = 0;
                k2 = -1;
            }
            /*endif*/
        }
        else
        {
            /* Find our two best monitored frequencies, which also have adequate energy. */
            ...
        }
        /*endif*/
    }

@cdevelop

Copy link
Copy Markdown
Author

With only one monitored frequency, super_tone_chunk() short-circuited to k1 = k2 = 0 without ever looking at the Goertzel result. That had three consequences:

* goertzel_result() was never called, and since it is what terminates
  the block and resets the filter, the accumulator kept running across
  block boundaries.

* The tone-to-total-energy test applied on the multi frequency path was
  skipped, so any signal above detection_threshold was treated as the
  monitored frequency, regardless of its spectrum.

* k2 was reported as 0, but descriptor segments for single frequency
  tones carry f2 == -1, because add_super_tone_freq() returns -1 for a
  frequency of 0. A k2 of 0 therefore never matched such a segment and
  the tone was in fact never reported at all.

Read state[0], apply the same tone-to-total-energy test as the multi frequency path, and report k1 = 0, k2 = -1 when it passes.

Also handle monitored_frequencies == 0, which happens for a descriptor built purely from silence elements. state[] is a flexible array member sized by monitored_frequencies, so state[0] must not be touched there; report k1 = k2 = -1 instead.

    else
    {
        if (s->desc->monitored_frequencies < 1)
        {
            k1 = -1;
            k2 = -1;
        }
        else if (s->desc->monitored_frequencies < 2)
        {
            res[0] = goertzel_result(&s->state[0]);
            if (res[0] < tone_to_total_energy*s->energy)
            {
                k1 = -1;
                k2 = -1;
            }
            else
            {
                k1 = 0;
                k2 = -1;
            }
            /*endif*/
        }
        else
        {
            /* Find our two best monitored frequencies, which also have adequate energy. */
            ...
        }
        /*endif*/
    }

I have already made the changes and submitted them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants