This commit is contained in:
Pascal
2026-05-14 16:47:45 +02:00
parent b1e864cb8d
commit e8f1c2a053
40 changed files with 337 additions and 340 deletions
+15 -1
View File
@@ -12,6 +12,11 @@
#include <cstring>
#include <string>
#if defined(_WIN32)
# include <fcntl.h>
# include <io.h>
#endif
// wav.h: WAV reader (returns interleaved, we deinterleave below)
#include "wav.h"
@@ -323,7 +328,8 @@ static std::string audio_encode_wav(const float * audio, int T_audio, int sr, Wa
case WAV_F32:
return audio_encode_wav_f32(audio, T_audio, sr);
}
return audio_encode_wav_s16(audio, T_audio, sr);
fprintf(stderr, "[WAV] unknown format %d\n", (int) fmt);
return {};
}
// Write mono float audio to WAV file in the requested format. path "-"
@@ -341,6 +347,14 @@ static bool audio_write_wav(const char * path, const float * audio, int T_audio,
fprintf(stderr, "[WAV] Cannot open %s for writing\n", path);
return false;
}
#if defined(_WIN32)
// stdout defaults to text mode on Windows; binary mode is mandatory
// for WAV bytes to survive without CRLF translation. The mode is set
// once per process and is harmless on the second call.
if (to_stdout) {
_setmode(_fileno(stdout), _O_BINARY);
}
#endif
if (fwrite(wav.data(), 1, wav.size(), fp) != wav.size()) {
fprintf(stderr, "[WAV] Failed to write %s\n", path);
if (!to_stdout) {
+3 -5
View File
@@ -17,6 +17,7 @@
#include "ggml.h"
#include "gguf-weights.h"
#include "qt-error.h"
#include "weight-ctx.h"
#include <cstdio>
@@ -33,8 +34,7 @@
static struct ggml_tensor * qwen_load_ctw_f32(WeightCtx * wctx, const GGUFModel & gf, const std::string & name) {
struct ggml_tensor * src = ggml_get_tensor(gf.meta, name.c_str());
if (!src) {
fprintf(stderr, "[CausalTransConv] FATAL: tensor '%s' not found\n", name.c_str());
exit(1);
qt_throw("[CausalTransConv] tensor '%s' not found", name.c_str());
}
// Source dtype follows the GGUF norm (pure llama.cpp policy). The F32
// master keeps tensors in F32, the BF16 variant keeps them in their
@@ -43,9 +43,7 @@ static struct ggml_tensor * qwen_load_ctw_f32(WeightCtx * wctx, const GGUFModel
// block size). All three are widened to F32 here; the K*OC*IC
// permutation always lands in a freshly allocated F32 buffer anyway.
if (src->type != GGML_TYPE_F32 && src->type != GGML_TYPE_F16 && src->type != GGML_TYPE_BF16) {
fprintf(stderr, "[CausalTransConv] FATAL: '%s' expected F32, F16 or BF16, got type %d\n", name.c_str(),
(int) src->type);
exit(1);
qt_throw("[CausalTransConv] '%s' expected F32, F16 or BF16, got type %d", name.c_str(), (int) src->type);
}
int K = (int) src->ne[0];
int OC = (int) src->ne[1];
+4 -6
View File
@@ -20,6 +20,7 @@
#include "ggml-alloc.h"
#include "ggml-backend.h"
#include "ggml.h"
#include "qt-error.h"
#include <cmath>
#include <cstdio>
@@ -231,12 +232,10 @@ static bool code_predictor_run(const CodePredictorWeights * cw,
// dispatched through ggml_get_type_traits so quants are accepted.
static void embed_row_from_backend(struct ggml_tensor * t, int row_id, int dim, float * dst) {
if (t->ne[0] != dim) {
fprintf(stderr, "[CodePredictor] FATAL: embed dim mismatch %lld vs %d\n", (long long) t->ne[0], dim);
std::exit(1);
qt_throw("[CodePredictor] embed dim mismatch %lld vs %d", (long long) t->ne[0], dim);
}
if (row_id < 0 || row_id >= (int) t->ne[1]) {
fprintf(stderr, "[CodePredictor] FATAL: row %d out of range (vocab=%lld)\n", row_id, (long long) t->ne[1]);
std::exit(1);
qt_throw("[CodePredictor] row %d out of range (vocab=%lld)", row_id, (long long) t->ne[1]);
}
const size_t row_bytes = ggml_row_size(t->type, dim);
if (t->type == GGML_TYPE_F32) {
@@ -245,8 +244,7 @@ static void embed_row_from_backend(struct ggml_tensor * t, int row_id, int dim,
}
const struct ggml_type_traits * tt = ggml_get_type_traits(t->type);
if (!tt || !tt->to_float) {
fprintf(stderr, "[CodePredictor] FATAL: unsupported embed dtype %d\n", (int) t->type);
std::exit(1);
qt_throw("[CodePredictor] unsupported embed dtype %d", (int) t->type);
}
std::vector<uint8_t> tmp(row_bytes);
ggml_backend_tensor_get(t, tmp.data(), (size_t) row_id * row_bytes, row_bytes);
+4 -7
View File
@@ -26,6 +26,7 @@
#include "ggml-backend.h"
#include "ggml.h"
#include "gguf-weights.h"
#include "qt-error.h"
#include "weight-ctx.h"
#include <cmath>
@@ -100,18 +101,14 @@ static void qwen_dac_load_snakebeta(WeightCtx * wctx,
struct ggml_tensor * alpha_meta = ggml_get_tensor(gf.meta, alpha_name.c_str());
struct ggml_tensor * beta_meta = ggml_get_tensor(gf.meta, beta_name.c_str());
if (!alpha_meta || !beta_meta) {
fprintf(stderr, "[DAC] FATAL: snake tensor '%s' or '%s' not found\n", alpha_name.c_str(), beta_name.c_str());
exit(1);
qt_throw("[DAC] snake tensor '%s' or '%s' not found", alpha_name.c_str(), beta_name.c_str());
}
if (alpha_meta->type != GGML_TYPE_F32 || beta_meta->type != GGML_TYPE_F32) {
fprintf(stderr, "[DAC] FATAL: snake '%s' expects F32 alpha/beta\n", alpha_name.c_str());
exit(1);
qt_throw("[DAC] snake '%s' expects F32 alpha/beta", alpha_name.c_str());
}
int C = (int) alpha_meta->ne[0];
if ((int) beta_meta->ne[0] != C) {
fprintf(stderr, "[DAC] FATAL: snake '%s' alpha/beta size mismatch (%d vs %d)\n", alpha_name.c_str(), C,
(int) beta_meta->ne[0]);
exit(1);
qt_throw("[DAC] snake '%s' alpha/beta size mismatch (%d vs %d)", alpha_name.c_str(), C, (int) beta_meta->ne[0]);
}
s->a = ggml_new_tensor_2d(wctx->ctx, GGML_TYPE_F32, 1, C);
+8 -16
View File
@@ -14,6 +14,7 @@
// gf_close(&gf); // safe after wctx_alloc copied data to GPU
#include "gguf.h"
#include "qt-error.h"
#include "weight-ctx.h"
#include <cstdio>
@@ -167,15 +168,13 @@ static struct ggml_tensor * gf_load_tensor(WeightCtx * wctx,
int n_dims_override = 0) {
int64_t idx = gguf_find_tensor(gf.gguf, name.c_str());
if (idx < 0) {
fprintf(stderr, "[GGUF] FATAL: tensor '%s' not found\n", name.c_str());
exit(1);
qt_throw("[GGUF] tensor '%s' not found", name.c_str());
}
// Get metadata from the context populated by gguf_init_from_file
struct ggml_tensor * src = ggml_get_tensor(gf.meta, name.c_str());
if (!src) {
fprintf(stderr, "[GGUF] FATAL: tensor '%s' not in meta context\n", name.c_str());
exit(1);
qt_throw("[GGUF] tensor '%s' not in meta context", name.c_str());
}
int n_dims;
@@ -218,8 +217,7 @@ static struct ggml_tensor * gf_try_load_tensor(WeightCtx * wctx, const GGUFModel
static struct ggml_tensor * gf_load_tensor_f32(WeightCtx * wctx, const GGUFModel & gf, const std::string & name) {
int64_t idx = gguf_find_tensor(gf.gguf, name.c_str());
if (idx < 0) {
fprintf(stderr, "[GGUF] FATAL: tensor '%s' not found\n", name.c_str());
exit(1);
qt_throw("[GGUF] tensor '%s' not found (f32 load)", name.c_str());
}
struct ggml_tensor * src = ggml_get_tensor(gf.meta, name.c_str());
int n_dims = ggml_n_dims(src);
@@ -296,8 +294,7 @@ static struct ggml_tensor * gf_load_tensor_f32(WeightCtx * wctx, const GGUFModel
static struct ggml_tensor * gf_load_conv(WeightCtx * wctx, const GGUFModel & gf, const std::string & name) {
int64_t idx = gguf_find_tensor(gf.gguf, name.c_str());
if (idx < 0) {
fprintf(stderr, "[GGUF] FATAL: tensor '%s' not found\n", name.c_str());
exit(1);
qt_throw("[GGUF] tensor '%s' not found (conv load)", name.c_str());
}
struct ggml_tensor * src = ggml_get_tensor(gf.meta, name.c_str());
int n_dims = ggml_n_dims(src);
@@ -311,9 +308,7 @@ static struct ggml_tensor * gf_load_conv(WeightCtx * wctx, const GGUFModel & gf,
return gf_load_tensor(wctx, gf, name);
}
if (src->type != GGML_TYPE_F32 && src->type != GGML_TYPE_BF16) {
fprintf(stderr, "[GGUF] FATAL: gf_load_conv unsupported source type %s for '%s'\n", ggml_type_name(src->type),
name.c_str());
exit(1);
qt_throw("[GGUF] gf_load_conv unsupported source type %s for '%s'", ggml_type_name(src->type), name.c_str());
}
// Allocate F16 backend tensor in the WeightCtx graph.
@@ -370,8 +365,7 @@ static const void * gf_get_data(const GGUFModel & gf, const char * name) {
static enum ggml_type gf_get_type(const GGUFModel & gf, const std::string & name) {
struct ggml_tensor * src = ggml_get_tensor(gf.meta, name.c_str());
if (!src) {
fprintf(stderr, "[GGUF] FATAL: tensor '%s' not in meta context\n", name.c_str());
exit(1);
qt_throw("[GGUF] tensor '%s' not in meta context", name.c_str());
}
return src->type;
}
@@ -388,9 +382,7 @@ static struct ggml_tensor * gf_load_qkv_fused(WeightCtx * wctx,
struct ggml_tensor * k_src = ggml_get_tensor(gf.meta, k_name.c_str());
struct ggml_tensor * v_src = ggml_get_tensor(gf.meta, v_name.c_str());
if (!q_src || !k_src || !v_src) {
fprintf(stderr, "[GGUF] FATAL: QKV tensor not found: %s / %s / %s\n", q_name.c_str(), k_name.c_str(),
v_name.c_str());
exit(1);
qt_throw("[GGUF] QKV tensor not found: %s / %s / %s", q_name.c_str(), k_name.c_str(), v_name.c_str());
}
// All must share ne[0] (input dim) and type - otherwise can't fuse
GGML_ASSERT(q_src->ne[0] == k_src->ne[0] && k_src->ne[0] == v_src->ne[0]);
+18 -10
View File
@@ -47,7 +47,7 @@ static void parse_languages(const GGUFModel & gf, std::vector<LanguageEntry> & o
size_t n_names = gguf_get_arr_n(gf.gguf, name_idx);
size_t n_ids = gguf_get_arr_n(gf.gguf, id_idx);
if (n_names != n_ids) {
fprintf(stderr, "[Pipeline] WARNING: language arrays size mismatch (names=%zu, ids=%zu)\n", n_names, n_ids);
qt_log(QT_LOG_WARN, "[Pipeline] language arrays size mismatch (names=%zu, ids=%zu)", n_names, n_ids);
return;
}
const uint32_t * ids = (const uint32_t *) gguf_get_arr_data(gf.gguf, id_idx);
@@ -75,8 +75,8 @@ static void parse_speakers(const GGUFModel & gf, std::vector<SpeakerEntry> & out
size_t n_ids = gguf_get_arr_n(gf.gguf, id_idx);
size_t n_dialects = gguf_get_arr_n(gf.gguf, dialect_idx);
if (n_names != n_ids || n_names != n_dialects) {
fprintf(stderr, "[Pipeline] WARNING: speaker arrays size mismatch (names=%zu, ids=%zu, dialects=%zu)\n",
n_names, n_ids, n_dialects);
qt_log(QT_LOG_WARN, "[Pipeline] speaker arrays size mismatch (names=%zu, ids=%zu, dialects=%zu)", n_names,
n_ids, n_dialects);
return;
}
const uint32_t * ids = (const uint32_t *) gguf_get_arr_data(gf.gguf, id_idx);
@@ -288,7 +288,9 @@ bool pipeline_tts_synthesize(PipelineTTS * pt,
const float * ref_spk_emb_ptr = NULL;
if (has_ref_audio) {
if (!pt->has_speaker_encoder) {
fprintf(stderr, "[Pipeline] FATAL: --ref-wav requires a model with a loaded speaker encoder (Base only)\n");
qt_set_error(
"pipeline_tts_synthesize: --ref-wav requires a model with a loaded speaker encoder (Base only)");
qt_log(QT_LOG_ERROR, "[Pipeline] --ref-wav requires a model with a loaded speaker encoder (Base only)");
return false;
}
if (!speaker_encoder_extract(&pt->speaker_encoder, pt->sched, params.ref_audio_24k, params.ref_n_samples,
@@ -296,7 +298,9 @@ bool pipeline_tts_synthesize(PipelineTTS * pt,
return false;
}
if ((int) ref_spk_emb.size() != pt->talker.hidden_size) {
fprintf(stderr, "[Pipeline] FATAL: speaker embedding size %zu mismatches talker hidden %d\n",
qt_set_error("pipeline_tts_synthesize: speaker embedding size %zu mismatches talker hidden %d",
ref_spk_emb.size(), pt->talker.hidden_size);
qt_log(QT_LOG_ERROR, "[Pipeline] speaker embedding size %zu mismatches talker hidden %d",
ref_spk_emb.size(), pt->talker.hidden_size);
return false;
}
@@ -312,23 +316,27 @@ bool pipeline_tts_synthesize(PipelineTTS * pt,
int ref_codes_T = 0;
if (!ref_text.empty()) {
if (!has_ref_audio) {
fprintf(stderr, "[Pipeline] FATAL: --ref-text requires --ref-wav\n");
qt_set_error("pipeline_tts_synthesize: --ref-text requires --ref-wav");
qt_log(QT_LOG_ERROR, "[Pipeline] --ref-text requires --ref-wav");
return false;
}
// The codec hop is 1920 samples at 24 kHz so n_samples must be
// a multiple of 1920. Truncate to the nearest hop boundary.
if (params.ref_n_samples < QWEN_TOKENIZER_HOP_LENGTH) {
fprintf(stderr, "[Pipeline] FATAL: ref_wav too short for ICL (%d samples)\n", params.ref_n_samples);
qt_set_error("pipeline_tts_synthesize: ref_wav too short for ICL (%d samples)", params.ref_n_samples);
qt_log(QT_LOG_ERROR, "[Pipeline] ref_wav too short for ICL (%d samples)", params.ref_n_samples);
return false;
}
int aligned_T = (params.ref_n_samples / QWEN_TOKENIZER_HOP_LENGTH) * QWEN_TOKENIZER_HOP_LENGTH;
ref_codes = pipeline_codec_encode(&pt->codec, params.ref_audio_24k, aligned_T, params.dump_dir);
if (ref_codes.empty()) {
fprintf(stderr, "[Pipeline] FATAL: pipeline_codec_encode returned empty codes\n");
qt_set_error("pipeline_tts_synthesize: pipeline_codec_encode returned empty codes");
qt_log(QT_LOG_ERROR, "[Pipeline] pipeline_codec_encode returned empty codes");
return false;
}
ref_codes_T = (int) ref_codes.size() / pt->num_code_groups;
fprintf(stderr, "[Pipeline] ICL ref_codes: %d frames at 12.5 Hz (%d audio samples)\n", ref_codes_T, aligned_T);
qt_log(QT_LOG_INFO, "[Pipeline] ICL ref_codes: %d frames at 12.5 Hz (%d audio samples)", ref_codes_T,
aligned_T);
}
if (!prompt_builder_build(pt, tok, params.text, params.lang, instruct, speaker, ref_spk_emb_ptr, ref_text,
@@ -435,7 +443,7 @@ bool pipeline_tts_synthesize(PipelineTTS * pt,
// up with [Sample-PY] / [Sample-CP] across the 16 codes of step
// 0 and step 1 the Python harness emits.
if ((subseq_counter - 1) < 32) {
fprintf(stderr, "[Sample] step=%d c0=%d u=%.10f subseq=%lld\n", step, c0, (double) u_c0,
qt_log(QT_LOG_DEBUG, "[Sample] step=%d c0=%d u=%.10f subseq=%lld", step, c0, (double) u_c0,
(long long) (subseq_counter - 1));
}
+8 -16
View File
@@ -31,6 +31,7 @@
#include "prompt-builder.h"
#include "ggml.h"
#include "qt-error.h"
#include <cmath>
#include <cstdio>
@@ -46,24 +47,18 @@
static void embed_row_to_f32(const GGUFModel & gf, const char * tensor_name, int row_id, int dim, float * dst) {
struct ggml_tensor * src = ggml_get_tensor(gf.meta, tensor_name);
if (!src) {
fprintf(stderr, "[Prompt] FATAL: tensor '%s' not in meta context\n", tensor_name);
std::exit(1);
qt_throw("[Prompt] tensor '%s' not in meta context", tensor_name);
}
if (src->ne[0] != dim) {
fprintf(stderr, "[Prompt] FATAL: tensor '%s' dim mismatch %lld vs %d\n", tensor_name, (long long) src->ne[0],
dim);
std::exit(1);
qt_throw("[Prompt] tensor '%s' dim mismatch %lld vs %d", tensor_name, (long long) src->ne[0], dim);
}
if (row_id < 0 || row_id >= (int) src->ne[1]) {
fprintf(stderr, "[Prompt] FATAL: row %d out of range for '%s' (vocab=%lld)\n", row_id, tensor_name,
(long long) src->ne[1]);
std::exit(1);
qt_throw("[Prompt] row %d out of range for '%s' (vocab=%lld)", row_id, tensor_name, (long long) src->ne[1]);
}
const uint8_t * base = (const uint8_t *) gf_get_data(gf, tensor_name);
if (!base) {
fprintf(stderr, "[Prompt] FATAL: tensor '%s' has no data\n", tensor_name);
std::exit(1);
qt_throw("[Prompt] tensor '%s' has no data", tensor_name);
}
const size_t row_bytes = ggml_row_size(src->type, dim);
@@ -76,8 +71,7 @@ static void embed_row_to_f32(const GGUFModel & gf, const char * tensor_name, int
const struct ggml_type_traits * tt = ggml_get_type_traits(src->type);
if (!tt || !tt->to_float) {
fprintf(stderr, "[Prompt] FATAL: unsupported dtype %d for '%s'\n", (int) src->type, tensor_name);
std::exit(1);
qt_throw("[Prompt] unsupported dtype %d for '%s'", (int) src->type, tensor_name);
}
tt->to_float(row, dst, dim);
}
@@ -88,8 +82,7 @@ static void embed_row_to_f32(const GGUFModel & gf, const char * tensor_name, int
static void read_tensor_f32(const GGUFModel & gf, const char * tensor_name, std::vector<float> & dst) {
struct ggml_tensor * src = ggml_get_tensor(gf.meta, tensor_name);
if (!src) {
fprintf(stderr, "[Prompt] FATAL: tensor '%s' not in meta context\n", tensor_name);
std::exit(1);
qt_throw("[Prompt] tensor '%s' not in meta context", tensor_name);
}
int64_t n = ggml_nelements(src);
const uint8_t * base = (const uint8_t *) gf_get_data(gf, tensor_name);
@@ -102,8 +95,7 @@ static void read_tensor_f32(const GGUFModel & gf, const char * tensor_name, std:
const struct ggml_type_traits * tt = ggml_get_type_traits(src->type);
if (!tt || !tt->to_float) {
fprintf(stderr, "[Prompt] FATAL: unsupported dtype %d for '%s'\n", (int) src->type, tensor_name);
std::exit(1);
qt_throw("[Prompt] unsupported dtype %d for '%s'", (int) src->type, tensor_name);
}
tt->to_float(base, dst.data(), (int64_t) n);
}
+3 -5
View File
@@ -12,6 +12,7 @@
#include "ggml-backend.h"
#include "ggml.h"
#include "gguf-weights.h"
#include "qt-error.h"
#include "weight-ctx.h"
#include <cstdio>
@@ -46,13 +47,10 @@ struct QwenQuantizerDecoder {
static struct ggml_tensor * qwen_load_proj_1x1(WeightCtx * wctx, const GGUFModel & gf, const std::string & name) {
struct ggml_tensor * src = ggml_get_tensor(gf.meta, name.c_str());
if (!src) {
fprintf(stderr, "[Quantizer] FATAL: tensor '%s' not found\n", name.c_str());
exit(1);
qt_throw("[Quantizer] tensor '%s' not found", name.c_str());
}
if (src->ne[0] != 1) {
fprintf(stderr, "[Quantizer] FATAL: '%s' expected kernel=1 on ne[0], got %lld\n", name.c_str(),
(long long) src->ne[0]);
exit(1);
qt_throw("[Quantizer] '%s' expected kernel=1 on ne[0], got %lld", name.c_str(), (long long) src->ne[0]);
}
int64_t shape2d[2] = { src->ne[1], src->ne[2] }; // (in_dim, out_dim) in ggml row-major
return gf_load_tensor(wctx, gf, name, shape2d, 2);
+5 -5
View File
@@ -207,19 +207,19 @@ void qwen_tts_default_params(struct qwen_tts_params * p) {
struct qwen_context * qwen_init(const struct qwen_init_params * params) {
if (!params || !params->talker_path || !params->codec_path) {
qt_set_error("qwen_init: params, talker_path or codec_path is NULL");
qt_log(QT_LOG_ERROR, "[qwen] qwen_init requires talker_path and codec_path");
qt_log(QT_LOG_ERROR, "[Qwen] qwen_init requires talker_path and codec_path");
return nullptr;
}
if (params->abi_version > QWEN_ABI_VERSION) {
qt_set_error(
"qwen_init: params->abi_version %d > QWEN_ABI_VERSION %d (binding compiled against a newer header)",
params->abi_version, QWEN_ABI_VERSION);
qt_log(QT_LOG_ERROR, "[qwen] qwen_init params struct is from a newer ABI (%d > %d)", params->abi_version,
qt_log(QT_LOG_ERROR, "[Qwen] qwen_init params struct is from a newer ABI (%d > %d)", params->abi_version,
QWEN_ABI_VERSION);
return nullptr;
}
qt_log(QT_LOG_INFO, "[qwen] qwentts.cpp %s", qwen_version());
qt_log(QT_LOG_INFO, "[Qwen] qwentts.cpp %s", qwen_version());
// new qwen_context() value-initialises every field: POD aggregates
// (BackendPair, PipelineTTS) are zero-init, std containers in
@@ -255,7 +255,7 @@ struct qwen_context * qwen_init(const struct qwen_init_params * params) {
bpe_load_specials_from_keys(&q->tok, params->talker_path, specials_keys, 5);
} catch (const std::exception & e) {
qt_set_error("%s", e.what());
qt_log(QT_LOG_ERROR, "[qwen] %s", e.what());
qt_log(QT_LOG_ERROR, "[Qwen] %s", e.what());
qwen_free(q);
return nullptr;
}
@@ -403,7 +403,7 @@ enum qwen_status qwen_synthesize(struct qwen_context * q,
return QWEN_STATUS_OK;
} catch (const std::exception & e) {
qt_set_error("%s", e.what());
qt_log(QT_LOG_ERROR, "[qwen] %s", e.what());
qt_log(QT_LOG_ERROR, "[Qwen] %s", e.what());
qwen_audio_free(out);
return QWEN_STATUS_GENERATE_FAILED;
}
+11 -11
View File
@@ -46,7 +46,7 @@ static void stub_log(enum qwen_log_level level, const char * msg, void * user_da
int main(void) {
/* Static version string, always reachable. */
const char * version = qwen_version();
printf("qwen ABI probe : %s\n", version);
printf("[Probe] %s\n", version);
/* Default-initialise the public structs from C. */
struct qwen_init_params iparams;
@@ -57,11 +57,11 @@ int main(void) {
/* Sanity-check a few default values, including the abi_version. */
if (params.max_new_tokens != 2048 || params.temperature != 0.9f) {
fprintf(stderr, "ABI probe : default values do not match\n");
fprintf(stderr, "[Probe] default values do not match\n");
return 1;
}
if (iparams.abi_version != QWEN_ABI_VERSION || params.abi_version != QWEN_ABI_VERSION) {
fprintf(stderr, "ABI probe : abi_version not set by qwen_*_default_params\n");
fprintf(stderr, "[Probe] abi_version not set by qwen_*_default_params\n");
return 1;
}
@@ -80,7 +80,7 @@ int main(void) {
* but the linker must resolve every name to satisfy the call. */
struct qwen_context * dummy = qwen_init(NULL);
if (dummy != NULL) {
fprintf(stderr, "ABI probe : qwen_init(NULL) was supposed to return NULL\n");
fprintf(stderr, "[Probe] qwen_init(NULL) was supposed to return NULL\n");
qwen_free(dummy);
return 2;
}
@@ -91,23 +91,23 @@ int main(void) {
* check the first byte to confirm an error was actually recorded. */
const char * err = qwen_last_error();
if (err == NULL || err[0] == '\0') {
fprintf(stderr, "ABI probe : qwen_last_error() empty after a known failure\n");
fprintf(stderr, "[Probe] qwen_last_error() empty after a known failure\n");
return 5;
}
/* The same failure must have surfaced through the log callback at
* ERROR level. */
if (g_log_lines == 0) {
fprintf(stderr, "ABI probe : qwen_log_set callback never invoked\n");
fprintf(stderr, "[Probe] qwen_log_set callback never invoked\n");
return 6;
}
if (g_last_log_level != QWEN_LOG_ERROR) {
fprintf(stderr, "ABI probe : last log level was %d, expected %d\n", (int) g_last_log_level,
fprintf(stderr, "[Probe] last log level was %d, expected %d\n", (int) g_last_log_level,
(int) QWEN_LOG_ERROR);
return 7;
}
printf("qwen ABI probe : qwen_log_set routed %d line(s), last : '%s'\n", g_log_lines, g_last_log_msg);
printf("qwen ABI probe : qwen_last_error reads '%s'\n", err);
printf("[Probe] qwen_log_set routed %d line(s), last: '%s'\n", g_log_lines, g_last_log_msg);
printf("[Probe] qwen_last_error reads '%s'\n", err);
/* abi_version validation : a struct claiming a future ABI must be
* rejected up front, before any allocation. Both paths are filled
@@ -120,14 +120,14 @@ int main(void) {
future_iparams.abi_version = QWEN_ABI_VERSION + 1;
struct qwen_context * rejected = qwen_init(&future_iparams);
if (rejected != NULL) {
fprintf(stderr, "ABI probe : qwen_init accepted a future abi_version\n");
fprintf(stderr, "[Probe] qwen_init accepted a future abi_version\n");
qwen_free(rejected);
return 8;
}
enum qwen_status rc = qwen_synthesize(NULL, &params, &audio);
if (rc != QWEN_STATUS_INVALID_PARAMS) {
fprintf(stderr, "ABI probe : qwen_synthesize(NULL) returned %d, expected %d\n", (int) rc,
fprintf(stderr, "[Probe] qwen_synthesize(NULL) returned %d, expected %d\n", (int) rc,
(int) QWEN_STATUS_INVALID_PARAMS);
return 3;
}