---
source_path: "api/sample/c/spot-data-stream.md"
canonical_url: "https://doc.sensory.com/tnl/7.8/api/sample/c/spot-data-stream/"
---

# spot-data-stream.c

This example runs a wake word from code space with a
[custom audio stream](https://doc.sensory.com/tnl/7.8/api/sample/c/data-stream.md#data-streamc), using pull mode processing
with [run](https://doc.sensory.com/tnl/7.8/api/inference.md#run). It is a reasonable starting point for running on a
small device with an RTOS.

**Also see these related items:** [fromProvider](https://doc.sensory.com/tnl/7.8/api/io.md#fromprovider), [data-stream.c](https://doc.sensory.com/tnl/7.8/api/sample/c/data-stream.md#data-streamc)

For the Python custom-stream shape, see [custom_stream.py](https://doc.sensory.com/tnl/7.8/api/sample/python/custom_stream.md#custom_streampy).

## Instructions

[Build](https://doc.sensory.com/tnl/7.8/api/sample/c/index.md#examples-cmake) the sample code.
In the same terminal window type the command after the `%`:

```console
% ./bin/spot-data-stream

Spotted "hello blue genie" from sample 6720 to sample 18000
Done, found phrase.
```

## Code

Available in this TrulyNatural SDK installation
at _~/Sensory/TrulyNaturalSDK/7.9.0-pre.0/sample/c/src/spot-data-stream.c_

**spot-data-stream.c:**

```c
/* Sensory Confidential
 * Copyright (C)2018-2026 Sensory, Inc. https://sensory.com/
 *
 * TrulyHandsfree SDK example illustrating the use of the
 * sample custom data-stream (see data-stream.c)  This should
 * be easily adaptable to a custom live-audio stream
 * (in case of a custom audio driver for RTOS for example.)
 *
 * The spotter model is loaded from code space. On platforms where code is
 * read directly from ROM, this will reduce heap requirements.
 *-----------------------------------------------------------------------------
 */

#include <stdio.h>
#include <stdlib.h>

#include <snsr.h>

#include "data-stream.h"

/* See spot-hbg-enUS-1.4.0-m.c */
extern SnsrCodeModel spot_hbg_enUS;

/* NOTE: extern char * foo is NOT always the same as extern char foo[] */
extern unsigned char audioData[];
extern unsigned int audioDataLen;

/* Result callback function, see snsrSetHandler() below.
 * Print the result text and the start and end sample indices of
 * the first spotted phrase.
 */
static SnsrRC
resultEvent(SnsrSession s, const char *key, void *privateData)
{
  SnsrRC rc;
  const char *phrase;
  double begin, end;

  /* Retrieve the phrase text and alignments from the session handle */
  snsrGetDouble(s, SNSR_RES_BEGIN_SAMPLE, &begin);
  snsrGetDouble(s, SNSR_RES_END_SAMPLE, &end);
  rc = snsrGetString(s, SNSR_RES_TEXT, &phrase);
  /* Quit early if an error occurred. */
  if (rc != SNSR_RC_OK) return rc;
  printf("\nSpotted \"%s\" from sample %d to sample %d\n",
         phrase, (int)begin, (int)end);
  /* This return code from the event handler sets the
   * return code in the SnsrSession and causes the session
   * to stop
   */
  return SNSR_RC_STOP;
}

int
main(int argc, char **argv)
{
  SnsrRC rc;
  SnsrSession s = NULL;
  SnsrStream audioStream = NULL;

  rc = snsrNew(&s);
  if (rc != SNSR_RC_OK) {
    const char *err = s ? snsrErrorDetail(s) : snsrRCMessage(rc);
    fprintf(stderr, "Error on init: %d - %s\n", rc, err);
    return rc;
  }

  /* Load and validate the spotter model task from code space */
  snsrLoad(s, snsrStreamFromCode(spot_hbg_enUS));
  if (snsrRequire(s, SNSR_TASK_TYPE, SNSR_PHRASESPOT) != SNSR_RC_OK) {
    fprintf(stderr, "Error loading spotter: %s\n", snsrErrorDetail(s));
    return rc;
  }

  /* Register a result callback. Private data handle is not used. */
  snsrSetHandler(s, SNSR_RESULT_EVENT, snsrCallback(resultEvent, NULL, NULL));

  /* NOTE: Audio stream should be 16 KHz, 16 bits/sample, mono */

  /* NOTE: Directly casting char to short works on little-endian only */
  /* ARM and x86 are little-endian, MIPS may not be */
  audioStream = streamFromData(audioData, audioDataLen, SNSR_ST_MODE_READ);
  snsrSetStream(s, SNSR_SOURCE_AUDIO_PCM, audioStream);

  /* snsrRun won't return until stopped or interrupted or end of data */
  rc = snsrRun(s);

  switch (rc) {
    case SNSR_RC_OK:
      printf("Done, no error but no phrase.\n");
      break;
    case SNSR_RC_STOP:
      printf("Done, found phrase.\n");
      break;
    case SNSR_RC_STREAM_END:
      printf("Reached end of stream.\n");
      break;
    default:
      printf("Unexpected return: %d\n", rc);
      return rc;
  }
  printf("\n");
  if (s) snsrRelease(s);
  /* audioStream has already been released because session had
   * the only reference to it - so don't snsrRelease it again.
   */

  return 0;
}

```

<!-- Abbreviation definitions from includes/abbreviations.md -->
*[API]: Application Programming Interface
*[RTOS]: Real-Time Operating System
*[SDK]: Software Development Kit
*[TNL]: TrulyNatural, Sensory's large-vocabulary speech recognition technology
