align symbol naming on omnivoice convention
This commit is contained in:
+22
-22
@@ -23,7 +23,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static const uint32_t QWEN_RVQ_CODE_MASK = (1u << QWEN_TOKENIZER_CODE_BITS) - 1u;
|
||||
static const uint32_t RVQ_CODE_MASK = (1u << TOKENIZER_CODE_BITS) - 1u;
|
||||
|
||||
static void print_usage(const char * prog) {
|
||||
fprintf(stderr, "qwentts.cpp %s\n\n", QWEN_VERSION);
|
||||
@@ -46,13 +46,13 @@ static std::vector<int32_t> unpack_codes(const std::vector<uint8_t> & in, size_t
|
||||
int bits_in_acc = 0;
|
||||
size_t in_pos = 0;
|
||||
for (size_t i = 0; i < n_codes; i++) {
|
||||
while (bits_in_acc < QWEN_TOKENIZER_CODE_BITS && in_pos < in.size()) {
|
||||
while (bits_in_acc < TOKENIZER_CODE_BITS && in_pos < in.size()) {
|
||||
acc |= ((uint64_t) in[in_pos++]) << bits_in_acc;
|
||||
bits_in_acc += 8;
|
||||
}
|
||||
out[i] = (int32_t) (acc & QWEN_RVQ_CODE_MASK);
|
||||
acc >>= QWEN_TOKENIZER_CODE_BITS;
|
||||
bits_in_acc -= QWEN_TOKENIZER_CODE_BITS;
|
||||
out[i] = (int32_t) (acc & RVQ_CODE_MASK);
|
||||
acc >>= TOKENIZER_CODE_BITS;
|
||||
bits_in_acc -= TOKENIZER_CODE_BITS;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -60,14 +60,14 @@ static std::vector<int32_t> unpack_codes(const std::vector<uint8_t> & in, size_t
|
||||
// Pack flat int32 codes into 11-bit LSB-first packed bytes. Output size is
|
||||
// ceil(N * 11 / 8) bytes.
|
||||
static std::vector<uint8_t> pack_codes(const std::vector<int32_t> & codes) {
|
||||
const size_t total_bits = codes.size() * (size_t) QWEN_TOKENIZER_CODE_BITS;
|
||||
const size_t total_bits = codes.size() * (size_t) TOKENIZER_CODE_BITS;
|
||||
std::vector<uint8_t> out((total_bits + 7) / 8, 0);
|
||||
uint64_t acc = 0;
|
||||
int bits_in_acc = 0;
|
||||
size_t out_pos = 0;
|
||||
for (size_t i = 0; i < codes.size(); i++) {
|
||||
acc |= ((uint64_t) ((uint32_t) codes[i] & QWEN_RVQ_CODE_MASK)) << bits_in_acc;
|
||||
bits_in_acc += QWEN_TOKENIZER_CODE_BITS;
|
||||
acc |= ((uint64_t) ((uint32_t) codes[i] & RVQ_CODE_MASK)) << bits_in_acc;
|
||||
bits_in_acc += TOKENIZER_CODE_BITS;
|
||||
while (bits_in_acc >= 8) {
|
||||
out[out_pos++] = (uint8_t) (acc & 0xFF);
|
||||
acc >>= 8;
|
||||
@@ -81,7 +81,7 @@ static std::vector<uint8_t> pack_codes(const std::vector<int32_t> & codes) {
|
||||
}
|
||||
|
||||
// Read a .rvq file and unpack it into K*T codes. T is inferred from the
|
||||
// file size: T = (filesize * 8) / (K * QWEN_TOKENIZER_CODE_BITS).
|
||||
// file size: T = (filesize * 8) / (K * TOKENIZER_CODE_BITS).
|
||||
static bool read_rvq(const char * path, int K, std::vector<int32_t> & codes, int * n_frames) {
|
||||
FILE * f = utf8_fopen(path, "rb");
|
||||
if (!f) {
|
||||
@@ -105,7 +105,7 @@ static bool read_rvq(const char * path, int K, std::vector<int32_t> & codes, int
|
||||
fclose(f);
|
||||
|
||||
const size_t total_bits = (size_t) sz * 8;
|
||||
const size_t n_codes = total_bits / (size_t) QWEN_TOKENIZER_CODE_BITS;
|
||||
const size_t n_codes = total_bits / (size_t) TOKENIZER_CODE_BITS;
|
||||
if (n_codes == 0 || (n_codes % (size_t) K) != 0) {
|
||||
fprintf(stderr, "[Codec] FATAL: %s yields %zu codes, not a multiple of K=%d\n", path, n_codes, K);
|
||||
return false;
|
||||
@@ -221,14 +221,14 @@ int main(int argc, char ** argv) {
|
||||
const std::string out_str = swap_ext(input_path, ".rvq");
|
||||
|
||||
int T_in = 0;
|
||||
float * audio_in = audio_read_mono(input_path, QWEN_TOKENIZER_SAMPLE_RATE, &T_in);
|
||||
float * audio_in = audio_read_mono(input_path, TOKENIZER_SAMPLE_RATE, &T_in);
|
||||
if (!audio_in || T_in <= 0) {
|
||||
fprintf(stderr, "[Codec] FATAL: cannot read %s\n", input_path);
|
||||
free(audio_in);
|
||||
rc = 1;
|
||||
} else {
|
||||
// Pad to a multiple of HOP_LENGTH so the RVQ frame count is integral.
|
||||
int hop = QWEN_TOKENIZER_HOP_LENGTH;
|
||||
int hop = TOKENIZER_HOP_LENGTH;
|
||||
int T_padded = ((T_in + hop - 1) / hop) * hop;
|
||||
int T_frames = T_padded / hop;
|
||||
|
||||
@@ -237,8 +237,8 @@ int main(int argc, char ** argv) {
|
||||
free(audio_in);
|
||||
|
||||
fprintf(stderr, "[Codec] Encode: %s, %d samples @ %d Hz, padded to %d (%d frames @ 12.5 Hz, %.2f s)\n",
|
||||
input_path, T_in, QWEN_TOKENIZER_SAMPLE_RATE, T_padded, T_frames,
|
||||
(double) T_padded / (double) QWEN_TOKENIZER_SAMPLE_RATE);
|
||||
input_path, T_in, TOKENIZER_SAMPLE_RATE, T_padded, T_frames,
|
||||
(double) T_padded / (double) TOKENIZER_SAMPLE_RATE);
|
||||
|
||||
std::vector<int32_t> codes = pipeline_codec_encode(&pc, audio_buf.data(), T_padded);
|
||||
if (codes.empty()) {
|
||||
@@ -248,8 +248,8 @@ int main(int argc, char ** argv) {
|
||||
rc = 1;
|
||||
} else {
|
||||
fprintf(stderr, "[Codec] Wrote %s: K=%d T=%d, %zu codes -> %zu packed bytes\n", out_str.c_str(),
|
||||
QWEN_TOKENIZER_NUM_CODEBOOKS, T_frames, codes.size(),
|
||||
(codes.size() * (size_t) QWEN_TOKENIZER_CODE_BITS + 7) / 8);
|
||||
TOKENIZER_NUM_CODEBOOKS, T_frames, codes.size(),
|
||||
(codes.size() * (size_t) TOKENIZER_CODE_BITS + 7) / 8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -258,23 +258,23 @@ int main(int argc, char ** argv) {
|
||||
|
||||
std::vector<int32_t> codes;
|
||||
int T = 0;
|
||||
if (!read_rvq(input_path, QWEN_TOKENIZER_NUM_CODEBOOKS, codes, &T)) {
|
||||
if (!read_rvq(input_path, TOKENIZER_NUM_CODEBOOKS, codes, &T)) {
|
||||
rc = 1;
|
||||
} else {
|
||||
fprintf(stderr, "[Codec] Decode: %s, K=%d T=%d (%.2f s)\n", input_path, QWEN_TOKENIZER_NUM_CODEBOOKS, T,
|
||||
(double) (T * QWEN_TOKENIZER_HOP_LENGTH) / (double) QWEN_TOKENIZER_SAMPLE_RATE);
|
||||
fprintf(stderr, "[Codec] Decode: %s, K=%d T=%d (%.2f s)\n", input_path, TOKENIZER_NUM_CODEBOOKS, T,
|
||||
(double) (T * TOKENIZER_HOP_LENGTH) / (double) TOKENIZER_SAMPLE_RATE);
|
||||
|
||||
std::vector<float> audio = pipeline_codec_decode(&pc, codes.data(), QWEN_TOKENIZER_NUM_CODEBOOKS, T);
|
||||
std::vector<float> audio = pipeline_codec_decode(&pc, codes.data(), TOKENIZER_NUM_CODEBOOKS, T);
|
||||
if (audio.empty()) {
|
||||
fprintf(stderr, "[Codec] FATAL: decode failed\n");
|
||||
rc = 1;
|
||||
} else if (!audio_write_wav(out_str.c_str(), audio.data(), (int) audio.size(), QWEN_TOKENIZER_SAMPLE_RATE,
|
||||
} else if (!audio_write_wav(out_str.c_str(), audio.data(), (int) audio.size(), TOKENIZER_SAMPLE_RATE,
|
||||
wav_fmt)) {
|
||||
fprintf(stderr, "[Codec] FATAL: cannot write %s\n", out_str.c_str());
|
||||
rc = 1;
|
||||
} else {
|
||||
fprintf(stderr, "[Codec] Wrote %s: %d samples @ %d Hz, %.2f s\n", out_str.c_str(), (int) audio.size(),
|
||||
QWEN_TOKENIZER_SAMPLE_RATE, (double) audio.size() / (double) QWEN_TOKENIZER_SAMPLE_RATE);
|
||||
TOKENIZER_SAMPLE_RATE, (double) audio.size() / (double) TOKENIZER_SAMPLE_RATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-39
@@ -1,18 +1,19 @@
|
||||
// qwen-tts.cpp: thin CLI wrapper around the qwentts.cpp public ABI.
|
||||
// Parses arguments, reads the optional reference WAV plus transcript,
|
||||
// hands off to qwen_synthesize and writes the resulting waveform as a
|
||||
// hands off to qt_synthesize and writes the resulting waveform as a
|
||||
// WAV file. All synthesis logic, mode validation and seed resolution
|
||||
// live behind the qwen_* facade declared in qwen.h.
|
||||
//
|
||||
// Talker variants: 0.6B-Base / 0.6B-CustomVoice / 1.7B-Base /
|
||||
// 1.7B-CustomVoice / 1.7B-VoiceDesign. The decoder path is selected
|
||||
// from GGUF metadata at qwen_init time. The CLI surface mirrors the
|
||||
// from GGUF metadata at qt_init time. The CLI surface mirrors the
|
||||
// omnivoice.cpp tooling: kebab-case flags, --format wav16/wav24/wav32,
|
||||
// -o '-' streams to stdout, --seed -1 means non deterministic
|
||||
// (resolved inside qwen_synthesize), the utterance text comes from
|
||||
// (resolved inside qt_synthesize), the utterance text comes from
|
||||
// --text or stdin if --text is absent.
|
||||
|
||||
#include "audio-io.h"
|
||||
#include "pipeline-codec.h"
|
||||
#include "qwen.h"
|
||||
|
||||
#include <cstdio>
|
||||
@@ -23,14 +24,8 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
// Tokenizer sample rate for the 12 Hz Qwen3-TTS codec: 24 kHz. Used
|
||||
// by audio_read_mono to resample the optional --ref-wav file before
|
||||
// handing it to the facade. The output sample rate is reported by
|
||||
// qwen_audio.sample_rate after a successful synthesis.
|
||||
static const int QWEN_TTS_SAMPLE_RATE = 24000;
|
||||
|
||||
static void print_usage(const char * prog) {
|
||||
fprintf(stderr, "qwentts.cpp %s\n\n", qwen_version());
|
||||
fprintf(stderr, "qwentts.cpp %s\n\n", qt_version());
|
||||
fprintf(stderr,
|
||||
"Usage: %s --model <gguf> --codec <gguf> [options] -o <out.wav>\n\n"
|
||||
"Required:\n"
|
||||
@@ -212,16 +207,16 @@ static bool parse_args(int argc, char ** argv, Args & a) {
|
||||
static int run(const Args & a) {
|
||||
// Init the facade. The seven mode validations
|
||||
// (base / custom_voice / voice_design rules) and the BPE tokenizer
|
||||
// load live inside qwen_init / qwen_synthesize; the CLI just hands
|
||||
// off the two GGUF paths and reports qwen_last_error on failure.
|
||||
qwen_init_params iparams;
|
||||
qwen_init_default_params(&iparams);
|
||||
// load live inside qt_init / qt_synthesize; the CLI just hands
|
||||
// off the two GGUF paths and reports qt_last_error on failure.
|
||||
qt_init_params iparams;
|
||||
qt_init_default_params(&iparams);
|
||||
iparams.talker_path = a.model;
|
||||
iparams.codec_path = a.codec;
|
||||
|
||||
qwen_context * q = qwen_init(&iparams);
|
||||
qt_context * q = qt_init(&iparams);
|
||||
if (!q) {
|
||||
fprintf(stderr, "[CLI] ERROR: %s\n", qwen_last_error());
|
||||
fprintf(stderr, "[CLI] ERROR: %s\n", qt_last_error());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -231,12 +226,12 @@ static int run(const Args & a) {
|
||||
const char * ref_text = NULL;
|
||||
if (a.ref_text_path) {
|
||||
if (!read_text_file(a.ref_text_path, ref_text_buf)) {
|
||||
qwen_free(q);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
if (ref_text_buf.empty()) {
|
||||
fprintf(stderr, "[CLI] ERROR: --ref-text file '%s' is empty\n", a.ref_text_path);
|
||||
qwen_free(q);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
ref_text = ref_text_buf.c_str();
|
||||
@@ -251,13 +246,13 @@ static int run(const Args & a) {
|
||||
int ref_n_samples = 0;
|
||||
if (a.ref_wav) {
|
||||
int T_in = 0;
|
||||
float * raw = audio_read_mono(a.ref_wav, QWEN_TTS_SAMPLE_RATE, &T_in);
|
||||
float * raw = audio_read_mono(a.ref_wav, TOKENIZER_SAMPLE_RATE, &T_in);
|
||||
if (!raw || T_in <= 0) {
|
||||
fprintf(stderr, "[CLI] ERROR: cannot read --ref-wav '%s'\n", a.ref_wav);
|
||||
if (raw) {
|
||||
std::free(raw);
|
||||
}
|
||||
qwen_free(q);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
raw_holder.reset(raw);
|
||||
@@ -270,7 +265,7 @@ static int run(const Args & a) {
|
||||
WavFormat wav_fmt;
|
||||
if (!audio_parse_format(a.format, wav_fmt)) {
|
||||
fprintf(stderr, "[CLI] ERROR: invalid --format '%s' (expected wav16, wav24, wav32)\n", a.format);
|
||||
qwen_free(q);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -282,16 +277,16 @@ static int run(const Args & a) {
|
||||
text_buf = read_stdin_text();
|
||||
if (text_buf.empty()) {
|
||||
fprintf(stderr, "[CLI] ERROR: no --text and stdin is empty\n");
|
||||
qwen_free(q);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
text = text_buf.c_str();
|
||||
}
|
||||
|
||||
// Translate CLI args into the facade params. Seed -1 is forwarded
|
||||
// verbatim and resolved by qwen_synthesize via std::random_device.
|
||||
qwen_tts_params params;
|
||||
qwen_tts_default_params(¶ms);
|
||||
// verbatim and resolved by qt_synthesize via std::random_device.
|
||||
qt_tts_params params;
|
||||
qt_tts_default_params(¶ms);
|
||||
params.text = text;
|
||||
params.lang = a.lang;
|
||||
params.instruct = a.instruct;
|
||||
@@ -312,12 +307,12 @@ static int run(const Args & a) {
|
||||
params.subtalker_top_p = a.subtalker_top_p;
|
||||
params.dump_dir = a.dump_dir;
|
||||
|
||||
qwen_audio audio = {};
|
||||
qwen_status status = qwen_synthesize(q, ¶ms, &audio);
|
||||
if (status != QWEN_STATUS_OK) {
|
||||
fprintf(stderr, "[CLI] ERROR: %s\n", qwen_last_error());
|
||||
qwen_audio_free(&audio);
|
||||
qwen_free(q);
|
||||
qt_audio audio = {};
|
||||
qt_status status = qt_synthesize(q, ¶ms, &audio);
|
||||
if (status != QT_STATUS_OK) {
|
||||
fprintf(stderr, "[CLI] ERROR: %s\n", qt_last_error());
|
||||
qt_audio_free(&audio);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -325,16 +320,16 @@ static int run(const Args & a) {
|
||||
const char * out_path = a.out_wav ? a.out_wav : "out.wav";
|
||||
if (!audio_write_wav(out_path, audio.samples, audio.n_samples, audio.sample_rate, wav_fmt)) {
|
||||
fprintf(stderr, "[Pipeline] FATAL: WAV write failed for %s\n", out_path);
|
||||
qwen_audio_free(&audio);
|
||||
qwen_free(q);
|
||||
qt_audio_free(&audio);
|
||||
qt_free(q);
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "[Pipeline] Wrote %d samples (%.2f s) -> %s\n", audio.n_samples,
|
||||
(double) audio.n_samples / (double) audio.sample_rate, out_path);
|
||||
}
|
||||
|
||||
qwen_audio_free(&audio);
|
||||
qwen_free(q);
|
||||
qt_audio_free(&audio);
|
||||
qt_free(q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -345,9 +340,9 @@ int main(int argc, char ** argv) {
|
||||
return 1;
|
||||
}
|
||||
// The facade absorbs every std::exception thrown deep in the load
|
||||
// and synthesis chains, converting them into qwen_status + a
|
||||
// qwen_last_error message. No top-level try / catch needed here :
|
||||
// the CLI just reads the status returned by qwen_init /
|
||||
// qwen_synthesize and renders qwen_last_error to stderr.
|
||||
// and synthesis chains, converting them into qt_status + a
|
||||
// qt_last_error message. No top-level try / catch needed here :
|
||||
// the CLI just reads the status returned by qt_init /
|
||||
// qt_synthesize and renders qt_last_error to stderr.
|
||||
return run(a);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user