1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// transcribe-model.cpp - out-of-line definitions for the model and
// context base classes.
//
// Why an out-of-line .cpp at all when both bases are short:
//
// 1. Anchors the virtual destructors in one TU. Otherwise every TU
// that includes transcribe-model.h would emit a vtable + RTTI
// copy, which clang and gcc both warn about (-Wweak-vtables).
// 2. Holds set_languages(), which is non-trivial enough that inlining
// it in the header would force the <vector>/<string> includes on
// every consumer for no benefit.
#include "transcribe-model.h"
#include "transcribe-session.h"
#include <utility>
// Anchor for the model base vtable. The default destructor is correct;
// we just need it defined in exactly one TU.
transcribe_model::~transcribe_model() = default;
// Same anchoring trick for the context base.
transcribe_session::~transcribe_session() = default;
void transcribe_session::clear_result() {
tokens.clear();
words.clear();
segments.clear();
full_text.clear();
detected_language.clear();
result_kind = TRANSCRIBE_TIMESTAMPS_NONE;
has_result = false;
// Stream snapshot — lifecycle (stream_state) is NOT touched here;
// the streaming dispatcher manages IDLE/ACTIVE/FINISHED/FAILED
// explicitly. Everything else is per-utterance bookkeeping that
// belongs with the result it describes.
stream_revision = 0;
n_committed_segments = 0;
n_committed_words = 0;
n_committed_tokens = 0;
stream_last_status = TRANSCRIBE_OK;
stream_audio_input_us = 0;
stream_audio_committed_us = 0;
stream_commit_policy = TRANSCRIBE_STREAM_COMMIT_AUTO;
stream_stable_prefix_agreement_n = 0;
stream_committed_text.clear();
stream_tentative_text.clear();
stream_raw_tentative_start_bytes = 0;
stream_raw_history.clear();
}
void transcribe_model::set_languages(std::vector<std::string> langs) {
// Move the strings into the model so their c_str() pointers stay
// valid for the model's lifetime. Anything that previously lived in
// language_storage_ is dropped (and the corresponding entries in
// language_ptrs_ become dangling, which is why we rebuild the
// pointer vector below before exposing it through caps).
language_storage_ = std::move(langs);
language_ptrs_.clear();
language_ptrs_.reserve(language_storage_.size());
for (const auto & s : language_storage_) {
language_ptrs_.push_back(s.c_str());
}
// Publish to the capability struct atomically from the caller's
// perspective: count and pointer match the same backing storage.
// An empty vector exposes (0, nullptr) instead of (0, &empty[0])
// because some callers reasonably treat a non-null pointer as a
// claim that there is at least one element.
caps.n_languages = static_cast<int>(language_storage_.size());
caps.languages = language_ptrs_.empty() ? nullptr : language_ptrs_.data();
}