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

# tpl-spot-sequential

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
in sequence. Use this to listen for a trigger phrase followed by a command,
for example: "Voice genie, play music."

`tpl-spot-sequential` 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-sequential-1.5.0.snsr](https://doc.sensory.com/tnl/7.8/models/index.md#tpl-spot-concurrent)

## Operation

```mermaid
flowchart TD
  start((start))
  loop0{loop == 2?}
  start --> loop0
  loop0 -->|no| start0
  loop0 -->|yes| start1

  subgraph slot0[<b>slot 0</b> &lpar;phrasespot&rpar;]
    start0((start))
    fetch0[/samples from ->audio-pcm/]
    audio0(^sample-count)
    process0[process]
    stop0((stop))
    start0 --> fetch0
    fetch0 --> audio0
    audio0 --> process0
    process0 --> fetch0
    process0 -->|recognize| stop0
  end

  listenBegin(^listen-begin)
  stop0 --> listenBegin
  listenBegin --> start1

  subgraph slot1[<b>slot 1</b> &lpar;phrasespot&rpar;]
    start1((start))
    fetch1[/samples from ->audio-pcm/]
    audio1(^sample-count)
    process1[process]
    result1(^result)
    stop1((stop))
    loop{loop == 0?}
    loop2{loop == 2?}
    start1 --> fetch1
    fetch1 --> audio1
    audio1 --> process1
    process1 --> fetch1
    process1 --->|recognize| result1
    process1 -->|timeout| loop2
    loop2 -->|no| stop1
    loop2 -->|yes| fetch1
    result1 --> loop
    loop -->|no| fetch1
    loop -->|yes| stop1
  end

  listenEnd(^listen-end)
  stop1 --> listenEnd
  listenEnd --> start0
```

Operation flow.

1. If [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `== 2` skip to step 6.
2. Read audio data from [->audio-pcm](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#-audio-pcm).
3. Invoke [^sample-count](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#sample-count-event).
4. Invoke [^result](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#result) if processing detects a vocabulary phrase, else continue at step 2.
5. Invoke [^listen-begin](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-begin), then start the wake word in slot 1.
6. Read audio data from [->audio-pcm](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#-audio-pcm).
7. Invoke [^sample-count](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#sample-count-event).
8. If [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `!= 2` and processing does not detect a wake word within
   [listen-window](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#listen-window), invoke [^listen-end](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-end) and restart the slot 0 wake word at step 2.
9. Invoke [^result](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#result) if processing detects a vocabulary phrase, else continue at step 6.
10. If [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `== 0` invoke [^listen-end](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-end) and continue at step 2.
11. If [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `!= 0` reset the listen-window timeout and continue processing
    at step 6.
12. 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:** [^listen-begin](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-begin), [^listen-end](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-end), [^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:** [operating-point-iterator](https://doc.sensory.com/tnl/7.8/api/setting-keys/iterators.md#operating-point-iterator), [vocab-iterator](https://doc.sensory.com/tnl/7.8/api/setting-keys/iterators.md#vocab-iterator)

**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), [dsp-acmodel-stream](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#dsp-acmodel-stream), [dsp-header-stream](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#dsp-header-stream), [dsp-search-stream](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#dsp-search-stream)

**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), [delay](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#delay), [dsp-target](https://doc.sensory.com/tnl/7.8/api/setting-keys/runtime.md#dsp-target), [duration-ms](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#duration-ms), [listen-window](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#listen-window), [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop), [low-fr-operating-point](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#low-fr-operating-point), [operating-point](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#operating-point), [samples-per-second](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#samples-per-second), [sv-threshold](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#sv-threshold)

**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

With [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `== 0` (the default): This template
runs the spotter in slot `0` until it spots, then runs slot `1`
until it spots, or the [listen-window](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#listen-window) timeout expires, then
returns to the spotter in slot `0`.

With [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `== 1`: This
runs the spotter in slot `0` until it spots, then runs slot `1`
until the [listen-window](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#listen-window) timeout expires, then returns to
the spotter in slot `0`. It resets the expiration timer every time
slot `1` recognizes.

 With [loop](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#loop) `== 2`: The template runs only slot `1`.
If your application needs to listen for a wake word but also support
an external trigger, such as a push-to-talk button, set `loop=2`
when the event occurs.

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 those without code changes.

Combined model settings refer to the model in slot `1`,
so [operating-point](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#operating-point) refers to `1.operating-point`.
You can change settings for the wake word in slot `0`
by prefixing the setting name with [0](https://doc.sensory.com/tnl/7.8/api/setting-keys/configuration.md#0), for example:
`0.operating-point`.

The model invokes [^listen-begin](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-begin) just before audio focus switches
to slot 1, and [^listen-end](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#listen-end) before audio focus switches back to
slot 0. If there's no [^result](https://doc.sensory.com/tnl/7.8/api/setting-keys/events.md#result) between `^listen-begin` and `^listen-end`
it is because the recognizer in slot 1 timed out.

## Examples

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

% bin/snsr-edit -o vg-music.snsr\
    -t model/tpl-spot-sequential-1.5.0.snsr\
    -f 0 model/spot-voicegenie-enUS-6.5.1-m.snsr\
    -f 1 model/spot-music-enUS-1.2.0-m.snsr

# say "voice genie, play music"
% bin/snsr-eval -vvt vg-music.snsr
Using live audio from default capture device. ^C to stop.
Using operating point 17.
Available operating points: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20.
Available vocabulary:
  1: "play_music"
  2: "previous_song"
  3: "stop_music"
  4: "next_song"
  5: "pause_music"
  3180 [^listen-begin]
phrase:
  3630   4410 (1 sv) play_music
words:
  3630   3900 (1 sv)
  3900   4410 (1 sv) play_music

  4635 [^listen-end]
^C
```

<!-- Abbreviation definitions from includes/abbreviations.md -->
*[API]: Application Programming Interface
*[FR]: False Reject: the recognizer did not trigger when the target phrase was spoken
*[TNL]: TrulyNatural, Sensory's large-vocabulary speech recognition technology
