process method

Ingests a new TranscriptionResult from the ASR recognizer, updates filtered tokens and recomputes continuous acoustic durations.

Implementation

ProcessedAudioStream process(TranscriptionResult result) {
  final int maxCount = min(result.tokens.length, result.timestamps.length);

  int commonLen = 0;
  final int minLen = min(_lastRawTokens.length, maxCount);
  for (int i = 0; i < minLen; i++) {
    if (_lastRawTokens[i] == result.tokens[i]) {
      commonLen++;
    } else {
      break;
    }
  }

  if (commonLen < _lastRawTokens.length) {
    reset();
    commonLen = 0;
  }

  _lastRawTokens = result.tokens.sublist(0, maxCount);

  final bool hasNewTokens = commonLen < maxCount;

  // Ingest newly arrived non-blank tokens into filtered arrays
  for (int i = commonLen; i < maxCount; i++) {
    final String tok = result.tokens[i];
    final double rawTs = result.timestamps[i];

    // Defensively filter empty or special CTC blank / epsilon tokens.
    if (tok.isEmpty ||
        tok == '<blank>' ||
        tok == '<blk>' ||
        tok == '<eps>' ||
        tok == 'eps') {
      continue;
    }

    _filteredTokens.add(tok);
    _filteredSpikeTimes.add(rawTs);
  }

  // Recompute accurate acoustic durations across all filtered tokens
  _recomputeDurations();

  // Debug prints:
  if (hasNewTokens && _filteredTokens.isNotEmpty) {
    final int startPrint = max(0, _filteredTokens.length - (maxCount - commonLen + 1));
    for (int i = startPrint; i < _filteredTokens.length; i++) {
      // ignore: avoid_print
      print(
        '⏱️ [SHERPA TOKEN] #$i "${_filteredTokens[i]}" | Pure Sherpa Ts: ${_filteredSpikeTimes[i].toStringAsFixed(3)}s | Grading Dur: ${_tokenDurations[i].toStringAsFixed(3)}s [start: ${_tokenStarts[i].toStringAsFixed(3)}s -> end: ${_tokenEnds[i].toStringAsFixed(3)}s]',
      );
    }
  }

  return ProcessedAudioStream(
    tokens: _filteredTokens,
    durations: _tokenDurations,
    starts: _tokenStarts,
    ends: _tokenEnds,
    spikeTimes: _filteredSpikeTimes,
  );
}