---
source_path: "models/tpl/tpl-spot-concurrent.md"
canonical_url: "https://doc.sensory.com/tnl/7.8/models/tpl/tpl-spot-concurrent/"
---

# tpl-spot-concurrent

This [template](https://doc.sensory.com/tnl/7.8/models/tpl/index.md#template-type) runs two [wake word](https://doc.sensory.com/tnl/7.8/models/types/wake-word.md#wake-word-type) models at
the same time. It provides a convenient way to create a single wake word model
that has the combined vocabulary of two other models.

`tpl-spot-concurrent` has [task-type](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#task-type)` == `[phrasespot](https://doc.sensory.com/tnl/7.8/api/setting-keys/values.md#phrasespot).

Expected [task types](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#task-type):

* **Slot 0:** [phrasespot](https://doc.sensory.com/tnl/7.8/api/setting-keys/values.md#phrasespot)
* **Slot 1:** [phrasespot](https://doc.sensory.com/tnl/7.8/api/setting-keys/values.md#phrasespot)

**Also see these related items:** [tpl-spot-concurrent-1.5.0.snsr](https://doc.sensory.com/tnl/7.8/models/index.md#tpl-spot-concurrent)

## Operation

```mermaid
flowchart TD
    start((start))
    fetch[/samples from ->audio-pcm/]
    audio(^sample-count)
    split@{ shape: f-circ }
    join@{ shape: f-circ }

    start --> fetch
    fetch --> audio
    audio --> split
    split --> start0
    split --> start1

    end0 --> join
    end1 --> join
    join ----> fetch

    subgraph slot0[<b>slot 0</b> &lpar;phrasespot&rpar;]
      start0((start))
      process0[process]
      result0(^result)
      end0((stop))
      start0 --> process0
      process0 --> end0
      process0 -->|recognize| result0
      result0 --> end0
    end

    subgraph slot1[<b>slot 1</b> &lpar;phrasespot&rpar;]
      start1((start))
      process1[process]
      result1(^result)
      end1((stop))
      start1 --> process1
      process1 --> end1
      process1 -->|recognize| result1
      result1 --> end1
    end
```

Operation flow.

1. Read audio data from [->audio-pcm](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#-audio-pcm).
2. Invoke [^sample-count](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#sample-count-event).
3. Send audio samples to recognizers in slot 0 and slot 1.
4. Invoke [^result](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#result) if processing detects a vocabulary phrase.
5. Continue processing until [STREAM_END](https://doc.sensory.com/tnl/7.8/api/inference.md#rc_stream_end) occurs on [->audio-pcm](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#-audio-pcm),
   or one of the event handlers returns a code other than [OK](https://doc.sensory.com/tnl/7.8/api/inference.md#rc_ok).

Register callback handlers with [setHandler](https://doc.sensory.com/tnl/7.8/api/inference.md#sethandler) only for those events you're interested in.

## Settings

**Available events:** [^result](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#result), [^sample-count](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#sample-count-event)

**Available iterators:** _none_

**Available results:** [audio-stream](https://doc.sensory.com/tnl/7.8/api/setting-keys/results.md#audio-stream), [audio-stream-first](https://doc.sensory.com/tnl/7.8/api/setting-keys/results.md#audio-stream-first), [audio-stream-last](https://doc.sensory.com/tnl/7.8/api/setting-keys/results.md#audio-stream-last)

**Available runtime settings:** [->audio-pcm](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#-audio-pcm), [audio-stream-from](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#audio-stream-from), [audio-stream-to](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#audio-stream-to)

**Available configuration settings:** [0](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#0), [1](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#1), [audio-stream-size](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#audio-stream-size), [samples-per-second](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#samples-per-second)

**Available values:** [phrasespot](https://doc.sensory.com/tnl/7.8/api/setting-keys/values.md#phrasespot)

**Also see these related items:** [live-spot.c](https://doc.sensory.com/tnl/7.8/api/sample/c/live-spot.md#live-spot-code), [snsr-eval.c](https://doc.sensory.com/tnl/7.8/api/sample/c/snsr-eval.md#snsr-eval-code), [PhraseSpot.java](https://doc.sensory.com/tnl/7.8/api/sample/android/enroll-trigger.md#et-code), [segmentSpottedAudio.java](https://doc.sensory.com/tnl/7.8/api/sample/java/segmentSpottedAudio.md#segmentspottedaudio-code)

## Notes

Runs the wake word models in slot [0](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#0) and slot [1](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#1) at the same
time, in the same thread.

The two recognizers are entirely independent, and can produce
results that overlap in time. For production use Sensory recommends
custom multi-phrase wake word recognizers instead. These have improved
false reject / false accept performance.

The combined model is a [wake word](https://doc.sensory.com/tnl/7.8/models/types/wake-word.md#wake-word-type), and can be used
in any application that expects such a model without API changes.

Configuration settings and iterators are not available in the
combined model. You can access these for the individual models
by prefixing the setting path with the slot. For example,
use `0.operating-point` to read or change the [operating-point](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#operating-point) of the first spotter
and use `1.operating-point` to read or change the [operating-point](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#operating-point) of the second spotter.

Attempting to set [operating-point](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#operating-point) without a slot prefix will result in an error.

```console
% cd $HOME/Sensory/TrulyNaturalSDK/7.9.0-pre.0

% bin/snsr-edit -o vg-hbg.snsr\
    -t model/tpl-spot-concurrent-1.5.0.snsr\
    -f 0 model/spot-voicegenie-enUS-6.5.1-m.snsr\
    -f 1 model/spot-hbg-enUS-1.4.0-m.snsr

% bin/snsr-edit \
    -t vg-hbg.snsr \
    -s operating-point=5
Setting "operating-point" not found, did you mean "0.operating-point" or "1.operating-point"?
```

Change individual settings at runtime by prefixing the
setting name with the slot:

<!-- tab: c -->

**C/C++**

```c
/* Set the operating point for spotter 0 only. */
snsrSetInt(session, SNSR_SLOT_0 SNSR_OPERATING_POINT, 7);
```
<!-- /tab -->

<!-- tab: java -->

**Java**

```java
/* Set the operating point for spotter 0 only. */
session.setInt(Snsr.SLOT_0 + Snsr.OPERATING_POINT, 7);
```
<!-- /tab -->

<!-- tab: py -->

**Python**

```python
# Set the operating point for spotter 0 only.
session.set_int(snsr.SLOT_0 + snsr.OPERATING_POINT, 7)
```
<!-- /tab -->

You can recombine combined models and nest them to an arbitrary depth to
run any number[^1] of wake word recognizers at the same time:

[^1]: Limited only by available RAM and CPU.

```console
% cd $HOME/Sensory/TrulyNaturalSDK/7.9.0-pre.0

% bin/snsr-edit -o models1-4.snsr\
    -t model/tpl-spot-concurrent-1.5.0.snsr\
    -f 0 model/tpl-spot-concurrent-1.5.0.snsr\
    -f 0.0 model-1.snsr\
    -f 0.1 model-2.snsr\
    -f 1 model/tpl-spot-concurrent-1.5.0.snsr\
    -f 1.0 model-1.snsr\
    -f 1.1 model-2.snsr
```

In this example, the four wake word models are located in the `0.0`, `0.1`,
`1.0` and `1.1` slots

## Examples

```console
% cd $HOME/Sensory/TrulyNaturalSDK/7.9.0-pre.0

% bin/snsr-edit -o vg-hbg.snsr\
    -t model/tpl-spot-concurrent-1.5.0.snsr\
    -f 0 model/spot-voicegenie-enUS-6.5.1-m.snsr\
    -f 1 model/spot-hbg-enUS-1.4.0-m.snsr

% bin/snsr-eval -t vg-hbg.snsr
  2370   2940 voicegenie
  5805   6420 voicegenie
  7740   8640 hello blue genie
 10440  11100 voicegenie
 12060  12870 hello blue genie
^C
```

<!-- Abbreviation definitions from includes/abbreviations.md -->
*[API]: Application Programming Interface
*[RAM]: Random Access Memory
*[TNL]: TrulyNatural, Sensory's large-vocabulary speech recognition technology
