feat: SDK 更新 — 韵律/时长/Postnet 走 NPU,PNCA 解码 CPU,postnet 分块修复
Browse files- sdk/include/kantts.hpp +2 -6
- sdk/src/kantts.cpp +175 -243
sdk/include/kantts.hpp
CHANGED
|
@@ -59,14 +59,10 @@ public:
|
|
| 59 |
std::vector<float> SynthesizeSymbols(const std::vector<std::string>& symbols);
|
| 60 |
|
| 61 |
private:
|
| 62 |
-
std::unique_ptr<ModelSession> enc_, voc_;
|
|
|
|
| 63 |
Weights w_;
|
| 64 |
std::unique_ptr<Frontend> frontend_;
|
| 65 |
};
|
| 66 |
|
| 67 |
-
// host 管线(供内部/测试使用)
|
| 68 |
-
std::vector<float> HostPredictors(const Weights& w, const std::vector<float>& text_hid,
|
| 69 |
-
const std::vector<float>& spk_hid,
|
| 70 |
-
const std::vector<float>& emo_hid, int T);
|
| 71 |
-
|
| 72 |
} // namespace kantts
|
|
|
|
| 59 |
std::vector<float> SynthesizeSymbols(const std::vector<std::string>& symbols);
|
| 60 |
|
| 61 |
private:
|
| 62 |
+
std::unique_ptr<ModelSession> enc_, voc_, pe_, dur_, post_, dec_;
|
| 63 |
+
std::string model_dir_;
|
| 64 |
Weights w_;
|
| 65 |
std::unique_ptr<Frontend> frontend_;
|
| 66 |
};
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
} // namespace kantts
|
sdk/src/kantts.cpp
CHANGED
|
@@ -109,21 +109,6 @@ void Conv1dSame(const std::vector<float>& x, const std::vector<float>& wgt,
|
|
| 109 |
}
|
| 110 |
}
|
| 111 |
|
| 112 |
-
void DepthwiseShift(const std::vector<float>& x, const std::vector<float>& wgt,
|
| 113 |
-
int T, int C, int K, int lp, int rp, std::vector<float>& y) {
|
| 114 |
-
y.assign(T * C, 0.0f);
|
| 115 |
-
for (int c = 0; c < C; ++c)
|
| 116 |
-
for (int t = 0; t < T; ++t) {
|
| 117 |
-
float acc = 0;
|
| 118 |
-
for (int k = 0; k < K; ++k) {
|
| 119 |
-
int tt = t - lp + k;
|
| 120 |
-
if (tt < 0 || tt >= T) continue;
|
| 121 |
-
acc += x[tt * C + c] * wgt[c * K + k];
|
| 122 |
-
}
|
| 123 |
-
y[t * C + c] = acc;
|
| 124 |
-
}
|
| 125 |
-
}
|
| 126 |
-
|
| 127 |
void LstmCell(const std::vector<float>& x, const std::vector<float>& w_ih,
|
| 128 |
const std::vector<float>& w_hh, const std::vector<float>& b_ih,
|
| 129 |
const std::vector<float>& b_hh, std::vector<float>& h, std::vector<float>& c,
|
|
@@ -146,109 +131,6 @@ void LstmCell(const std::vector<float>& x, const std::vector<float>& w_ih,
|
|
| 146 |
}
|
| 147 |
}
|
| 148 |
|
| 149 |
-
void Blstm(const std::vector<float>& x, const Weights& w, const std::string& pre,
|
| 150 |
-
int T, int in_d, int units, std::vector<float>& y) {
|
| 151 |
-
const auto& wih = w.Get(pre + "_blstm_w_ih");
|
| 152 |
-
const auto& whh = w.Get(pre + "_blstm_w_hh");
|
| 153 |
-
const auto& bih = w.Get(pre + "_blstm_b_ih");
|
| 154 |
-
const auto& bhh = w.Get(pre + "_blstm_b_hh");
|
| 155 |
-
const auto& wihr = w.Get(pre + "_blstm_w_ih_r");
|
| 156 |
-
const auto& whhr = w.Get(pre + "_blstm_w_hh_r");
|
| 157 |
-
const auto& bihr = w.Get(pre + "_blstm_b_ih_r");
|
| 158 |
-
const auto& bhhr = w.Get(pre + "_blstm_b_hh_r");
|
| 159 |
-
std::vector<float> hf(units, 0), cf(units, 0), hb(units, 0), cb(units, 0);
|
| 160 |
-
y.assign(T * 2 * units, 0.0f);
|
| 161 |
-
std::vector<float> xi(in_d);
|
| 162 |
-
for (int t = 0; t < T; ++t) {
|
| 163 |
-
std::copy(x.begin() + t * in_d, x.begin() + (t + 1) * in_d, xi.begin());
|
| 164 |
-
LstmCell(xi, wih, whh, bih, bhh, hf, cf, units);
|
| 165 |
-
std::copy(hf.begin(), hf.end(), y.begin() + t * 2 * units);
|
| 166 |
-
}
|
| 167 |
-
for (int t = T - 1; t >= 0; --t) {
|
| 168 |
-
std::copy(x.begin() + t * in_d, x.begin() + (t + 1) * in_d, xi.begin());
|
| 169 |
-
LstmCell(xi, wihr, whhr, bihr, bhhr, hb, cb, units);
|
| 170 |
-
std::copy(hb.begin(), hb.end(), y.begin() + t * 2 * units + units);
|
| 171 |
-
}
|
| 172 |
-
}
|
| 173 |
-
|
| 174 |
-
std::vector<float> FsmnEncoder(const std::vector<float>& x, const Weights& w,
|
| 175 |
-
const std::string& pre, int T, int C, const std::vector<int>& shift) {
|
| 176 |
-
std::vector<float> cur = x;
|
| 177 |
-
int layers = 0;
|
| 178 |
-
while (w.Has(pre + "_ffn" + std::to_string(layers) + "_w1")) ++layers;
|
| 179 |
-
for (int i = 0; i < layers; ++i) {
|
| 180 |
-
int mid = (int)w.Shape(pre + "_ffn" + std::to_string(i) + "_w1")[0];
|
| 181 |
-
std::vector<float> c1;
|
| 182 |
-
Conv1dSame(cur, w.Get(pre + "_ffn" + std::to_string(i) + "_w1"),
|
| 183 |
-
w.Get(pre + "_ffn" + std::to_string(i) + "_b1"), T, C, mid, 1, c1);
|
| 184 |
-
for (auto& v : c1) v = std::max(v, 0.0f);
|
| 185 |
-
int out_c = (int)w.Shape(pre + "_ffn" + std::to_string(i) + "_w2")[0];
|
| 186 |
-
std::vector<float> c2;
|
| 187 |
-
Conv1dSame(c1, w.Get(pre + "_ffn" + std::to_string(i) + "_w2"),
|
| 188 |
-
w.Get(pre + "_ffn" + std::to_string(i) + "_b2"), T, mid, out_c, 1, c2);
|
| 189 |
-
int fsize = (int)w.Shape(pre + "_mem" + std::to_string(i) + "_conv")[2];
|
| 190 |
-
int sh = shift.empty() ? 0 : shift[i];
|
| 191 |
-
int lp = (fsize - 1) / 2 + (sh > 0 ? sh : 0);
|
| 192 |
-
int rp = (fsize - 1) / 2 - (sh > 0 ? sh : 0);
|
| 193 |
-
std::vector<float> mem;
|
| 194 |
-
DepthwiseShift(c2, w.Get(pre + "_mem" + std::to_string(i) + "_conv"), T, out_c, fsize,
|
| 195 |
-
lp, rp, mem);
|
| 196 |
-
for (int t = 0; t < T; ++t)
|
| 197 |
-
for (int c = 0; c < out_c; ++c) mem[t * out_c + c] += c2[t * out_c + c];
|
| 198 |
-
if (out_c == C)
|
| 199 |
-
for (int t = 0; t < T; ++t)
|
| 200 |
-
for (int c = 0; c < out_c; ++c) mem[t * out_c + c] += cur[t * C + c];
|
| 201 |
-
cur = mem;
|
| 202 |
-
C = out_c;
|
| 203 |
-
}
|
| 204 |
-
return cur;
|
| 205 |
-
}
|
| 206 |
-
|
| 207 |
-
std::vector<float> VarFsmnRnnPredictor(const std::vector<float>& x, const Weights& w,
|
| 208 |
-
const std::string& pre, int T, int in_d) {
|
| 209 |
-
std::vector<float> h = FsmnEncoder(x, w, pre, T, in_d, {0, 0, 0});
|
| 210 |
-
std::vector<float> bh;
|
| 211 |
-
Blstm(h, w, pre, T, 128, 128, bh);
|
| 212 |
-
std::vector<float> out(T);
|
| 213 |
-
const auto& fw = w.Get(pre + "_fc_w");
|
| 214 |
-
const auto& fb = w.Get(pre + "_fc_b");
|
| 215 |
-
for (int t = 0; t < T; ++t) {
|
| 216 |
-
float acc = fb[0];
|
| 217 |
-
for (int k = 0; k < 256; ++k) acc += bh[t * 256 + k] * fw[0 * 256 + k];
|
| 218 |
-
out[t] = acc;
|
| 219 |
-
}
|
| 220 |
-
return out;
|
| 221 |
-
}
|
| 222 |
-
|
| 223 |
-
std::vector<float> DurationAr(const std::vector<float>& cond, const Weights& w, int T, int in_d) {
|
| 224 |
-
std::vector<float> h0(128, 0), c0(128, 0), h1(128, 0), c1(128, 0);
|
| 225 |
-
std::vector<float> x(1, 0.0f), out(T);
|
| 226 |
-
const auto& p0w = w.Get("dur_pre0_w");
|
| 227 |
-
const auto& p0b = w.Get("dur_pre0_b");
|
| 228 |
-
const auto& p1w = w.Get("dur_pre1_w");
|
| 229 |
-
const auto& p1b = w.Get("dur_pre1_b");
|
| 230 |
-
const auto& fw = w.Get("dur_fc_w");
|
| 231 |
-
const auto& fb = w.Get("dur_fc_b");
|
| 232 |
-
std::vector<float> inp, tmp;
|
| 233 |
-
for (int t = 0; t < T; ++t) {
|
| 234 |
-
Matmul(x, p0w, p0b, 1, 1, 128, inp);
|
| 235 |
-
for (auto& v : inp) v = std::max(v, 0.0f);
|
| 236 |
-
Matmul(inp, p1w, p1b, 1, 128, 128, tmp);
|
| 237 |
-
for (auto& v : tmp) v = std::max(v, 0.0f);
|
| 238 |
-
std::vector<float> xin(tmp);
|
| 239 |
-
xin.insert(xin.end(), cond.begin() + t * in_d, cond.begin() + (t + 1) * in_d);
|
| 240 |
-
LstmCell(xin, w.Get("dur_lstm_w_ih0"), w.Get("dur_lstm_w_hh0"), w.Get("dur_lstm_b_ih0"),
|
| 241 |
-
w.Get("dur_lstm_b_hh0"), h0, c0, 128);
|
| 242 |
-
LstmCell(h0, w.Get("dur_lstm_w_ih1"), w.Get("dur_lstm_w_hh1"), w.Get("dur_lstm_b_ih1"),
|
| 243 |
-
w.Get("dur_lstm_b_hh1"), h1, c1, 128);
|
| 244 |
-
float acc = fb[0];
|
| 245 |
-
for (int k = 0; k < 128; ++k) acc += h1[k] * fw[0 * 128 + k];
|
| 246 |
-
x[0] = std::max(acc, 0.0f);
|
| 247 |
-
out[t] = x[0];
|
| 248 |
-
}
|
| 249 |
-
return out;
|
| 250 |
-
}
|
| 251 |
-
|
| 252 |
} // namespace
|
| 253 |
|
| 254 |
void Weights::Load(const std::string& dir) {
|
|
@@ -408,102 +290,6 @@ Frontend::EncInput Frontend::Encode(const std::string& symbol_seq) {
|
|
| 408 |
|
| 409 |
namespace {
|
| 410 |
|
| 411 |
-
// build_memory:text/spk/emo (T,32) → memory (M,160) + lr_len + durations
|
| 412 |
-
void BuildMemory(const std::vector<float>& text_hid, const std::vector<float>& spk_hid,
|
| 413 |
-
const std::vector<float>& emo_hid, const Weights& w, int T,
|
| 414 |
-
std::vector<float>& memory, int& lr_len, std::vector<float>& durations) {
|
| 415 |
-
std::vector<float> var_in(T * 96);
|
| 416 |
-
for (int t = 0; t < T; ++t)
|
| 417 |
-
for (int c = 0; c < 32; ++c) {
|
| 418 |
-
var_in[t * 96 + c] = text_hid[t * 32 + c];
|
| 419 |
-
var_in[t * 96 + 32 + c] = spk_hid[t * 32 + c];
|
| 420 |
-
var_in[t * 96 + 64 + c] = emo_hid[t * 32 + c];
|
| 421 |
-
}
|
| 422 |
-
auto pitch = VarFsmnRnnPredictor(var_in, w, "pitch", T, 96);
|
| 423 |
-
auto energy = VarFsmnRnnPredictor(var_in, w, "energy", T, 96);
|
| 424 |
-
if (std::getenv("KANTTS_DUMP_ENC")) {
|
| 425 |
-
{
|
| 426 |
-
std::ofstream f("/tmp/kt/enc_pitch.bin", std::ios::binary);
|
| 427 |
-
f.write((const char*)pitch.data(), pitch.size() * 4);
|
| 428 |
-
}
|
| 429 |
-
{
|
| 430 |
-
std::ofstream f("/tmp/kt/enc_energy.bin", std::ios::binary);
|
| 431 |
-
f.write((const char*)energy.data(), energy.size() * 4);
|
| 432 |
-
}
|
| 433 |
-
}
|
| 434 |
-
std::vector<float> pe, ee;
|
| 435 |
-
Conv1dSame(pitch, w.Get("pitch_emb_w"), w.Get("pitch_emb_b"), T, 1, 32, 9, pe);
|
| 436 |
-
Conv1dSame(energy, w.Get("energy_emb_w"), w.Get("energy_emb_b"), T, 1, 32, 9, ee);
|
| 437 |
-
std::vector<float> aug(T * 32);
|
| 438 |
-
for (int t = 0; t < T * 32; ++t) aug[t] = text_hid[t] + pe[t] + ee[t];
|
| 439 |
-
if (std::getenv("KANTTS_DUMP_ENC")) {
|
| 440 |
-
std::ofstream f("/tmp/kt/enc_aug.bin", std::ios::binary);
|
| 441 |
-
f.write((const char*)aug.data(), aug.size() * 4);
|
| 442 |
-
}
|
| 443 |
-
std::vector<float> cond(T * 96);
|
| 444 |
-
for (int t = 0; t < T; ++t)
|
| 445 |
-
for (int c = 0; c < 32; ++c) {
|
| 446 |
-
cond[t * 96 + c] = aug[t * 32 + c];
|
| 447 |
-
cond[t * 96 + 32 + c] = spk_hid[t * 32 + c];
|
| 448 |
-
cond[t * 96 + 64 + c] = emo_hid[t * 32 + c];
|
| 449 |
-
}
|
| 450 |
-
auto log_dur = DurationAr(cond, w, T, 96);
|
| 451 |
-
if (std::getenv("KANTTS_DUMP_ENC")) {
|
| 452 |
-
std::ofstream f("/tmp/kt/enc_logdur.bin", std::ios::binary);
|
| 453 |
-
f.write((const char*)log_dur.data(), log_dur.size() * 4);
|
| 454 |
-
}
|
| 455 |
-
durations.resize(T);
|
| 456 |
-
int sum = 0;
|
| 457 |
-
std::vector<int> reps(T);
|
| 458 |
-
for (int t = 0; t < T; ++t) {
|
| 459 |
-
durations[t] = std::exp(log_dur[t]) - 1.0f;
|
| 460 |
-
reps[t] = (int)(durations[t] + 0.5f);
|
| 461 |
-
sum += reps[t];
|
| 462 |
-
}
|
| 463 |
-
int pad = 3 - sum % 3;
|
| 464 |
-
if (pad == 3) pad = 0;
|
| 465 |
-
int P = sum + pad;
|
| 466 |
-
// LR text/spk/emo
|
| 467 |
-
auto expand = [&](const std::vector<float>& src, std::vector<float>& dst) {
|
| 468 |
-
dst.assign(P * 32, 0.0f);
|
| 469 |
-
int pos = 0;
|
| 470 |
-
for (int t = 0; t < T; ++t)
|
| 471 |
-
for (int r = 0; r < reps[t]; ++r) {
|
| 472 |
-
std::copy(src.begin() + t * 32, src.begin() + (t + 1) * 32,
|
| 473 |
-
dst.begin() + (pos++) * 32);
|
| 474 |
-
}
|
| 475 |
-
};
|
| 476 |
-
std::vector<float> lr_text, lr_emo, lr_spk;
|
| 477 |
-
expand(aug, lr_text);
|
| 478 |
-
expand(emo_hid, lr_emo);
|
| 479 |
-
expand(spk_hid, lr_spk);
|
| 480 |
-
// dur position encoder
|
| 481 |
-
std::vector<float> rc(T + 1, 0);
|
| 482 |
-
for (int t = 0; t < T; ++t) rc[t + 1] = rc[t] + reps[t];
|
| 483 |
-
std::vector<float> lr_pos(P * 32, 0.0f);
|
| 484 |
-
for (int p = 0; p < P; ++p) {
|
| 485 |
-
int ph = 0;
|
| 486 |
-
for (int t = 0; t < T; ++t)
|
| 487 |
-
if (rc[t] <= p && p < rc[t + 1]) { ph = p - rc[t] + 1; break; }
|
| 488 |
-
for (int c = 0; c < 32; ++c) {
|
| 489 |
-
float inv = std::pow(10000.0f, 2.0f * (c / 2) / 32.0f);
|
| 490 |
-
float v = ph / inv;
|
| 491 |
-
lr_pos[p * 32 + c] = (c % 2 == 0) ? std::sin(v) : std::cos(v);
|
| 492 |
-
}
|
| 493 |
-
}
|
| 494 |
-
for (int i = 0; i < P * 32; ++i) lr_text[i] += lr_pos[i];
|
| 495 |
-
int M = P / 3;
|
| 496 |
-
memory.assign(M * 160, 0.0f);
|
| 497 |
-
for (int m = 0; m < M; ++m) {
|
| 498 |
-
for (int c = 0; c < 96; ++c) memory[m * 160 + c] = lr_text[m * 96 + c];
|
| 499 |
-
for (int c = 0; c < 32; ++c) {
|
| 500 |
-
memory[m * 160 + 96 + c] = lr_spk[m * 96 + c];
|
| 501 |
-
memory[m * 160 + 128 + c] = lr_emo[m * 96 + c];
|
| 502 |
-
}
|
| 503 |
-
}
|
| 504 |
-
lr_len = sum;
|
| 505 |
-
}
|
| 506 |
-
|
| 507 |
// PNCA 单步解码(host)
|
| 508 |
struct Decoder {
|
| 509 |
struct LW {
|
|
@@ -692,28 +478,16 @@ struct Decoder {
|
|
| 692 |
};
|
| 693 |
|
| 694 |
|
| 695 |
-
std::vector<float> Postnet(const std::vector<float>& dec, const Weights& w, int T) {
|
| 696 |
-
std::vector<float> x = FsmnEncoder(dec, w, "post", T, 80, {17, 17, 17, 17});
|
| 697 |
-
std::vector<float> h(128, 0), c(128, 0), out(T * 128);
|
| 698 |
-
std::vector<float> xi(256);
|
| 699 |
-
for (int t = 0; t < T; ++t) {
|
| 700 |
-
std::copy(x.begin() + t * 256, x.begin() + (t + 1) * 256, xi.begin());
|
| 701 |
-
LstmCell(xi, w.Get("post_lstm_w_ih"), w.Get("post_lstm_w_hh"), w.Get("post_lstm_b_ih"),
|
| 702 |
-
w.Get("post_lstm_b_hh"), h, c, 128);
|
| 703 |
-
std::copy(h.begin(), h.end(), out.begin() + t * 128);
|
| 704 |
-
}
|
| 705 |
-
std::vector<float> res(T * 80);
|
| 706 |
-
Matmul(out, w.Get("post_fc_w"), w.Get("post_fc_b"), T, 128, 80, res);
|
| 707 |
-
for (int i = 0; i < T * 80; ++i) res[i] += dec[i];
|
| 708 |
-
return res;
|
| 709 |
-
}
|
| 710 |
-
|
| 711 |
} // namespace
|
| 712 |
|
| 713 |
KanttsPipeline::KanttsPipeline(const std::string& model_dir, const std::string& resource_dir,
|
| 714 |
const std::string& am_config)
|
| 715 |
: enc_(new ModelSession(model_dir + "/am_enc.axmodel")),
|
| 716 |
voc_(new ModelSession(model_dir + "/voc.axmodel")),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 717 |
frontend_(new Frontend(resource_dir, am_config)) {
|
| 718 |
w_.Load(model_dir + "/host_weights");
|
| 719 |
std::fprintf(stderr, "[stage] weights loaded\n");
|
|
@@ -800,7 +574,98 @@ std::vector<float> KanttsPipeline::SynthesizeSymbols(
|
|
| 800 |
}
|
| 801 |
std::fprintf(stderr, "[dbg] 使用参考 memory(%d 行)\n", (int)memory.size() / 160);
|
| 802 |
} else {
|
| 803 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 804 |
}
|
| 805 |
int M = (int)memory.size() / 160;
|
| 806 |
std::fprintf(stderr, "[stage] memory M=%d lr_len=%d\n", M, lr_len);
|
|
@@ -812,25 +677,92 @@ std::vector<float> KanttsPipeline::SynthesizeSymbols(
|
|
| 812 |
}
|
| 813 |
int x_band = (int)(*std::max_element(durations.begin(), durations.end()) / 3.0f + 0.5f);
|
| 814 |
std::fprintf(stderr, "[stage] x_band=%d\n", x_band);
|
| 815 |
-
Decoder dec(w_);
|
| 816 |
-
dec.Prepare(memory);
|
| 817 |
-
std::fprintf(stderr, "[timing] host(预测+memory) %.0fms\n", std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now()-t_stage).count());
|
| 818 |
-
t_stage = std::chrono::steady_clock::now();
|
| 819 |
-
std::vector<float> xk(12 * 8 * 270 * 16, 0.0f), xv(12 * 8 * 270 * 16, 0.0f);
|
| 820 |
-
std::vector<float> frame(80, 0.0f), out;
|
| 821 |
std::vector<float> dec_all(M * 3 * 80);
|
| 822 |
double dec_sum = 0;
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 828 |
}
|
| 829 |
for (size_t i = 0; i < dec_all.size(); ++i) dec_sum += dec_all[i] * dec_all[i];
|
| 830 |
std::fprintf(stderr, "[dbg] dec rms=%.4f\n", std::sqrt(dec_sum / dec_all.size()));
|
| 831 |
std::fprintf(stderr, "[timing] decode %d 步 %.0fms\n", M, std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now()-t_stage).count());
|
| 832 |
t_stage = std::chrono::steady_clock::now();
|
| 833 |
-
std::vector<float> mel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 834 |
std::fprintf(stderr, "[timing] postnet %.0fms\n", std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now()-t_stage).count());
|
| 835 |
t_stage = std::chrono::steady_clock::now();
|
| 836 |
double mel_sum = 0;
|
|
|
|
| 109 |
}
|
| 110 |
}
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
void LstmCell(const std::vector<float>& x, const std::vector<float>& w_ih,
|
| 113 |
const std::vector<float>& w_hh, const std::vector<float>& b_ih,
|
| 114 |
const std::vector<float>& b_hh, std::vector<float>& h, std::vector<float>& c,
|
|
|
|
| 131 |
}
|
| 132 |
}
|
| 133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
} // namespace
|
| 135 |
|
| 136 |
void Weights::Load(const std::string& dir) {
|
|
|
|
| 290 |
|
| 291 |
namespace {
|
| 292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
// PNCA 单步解码(host)
|
| 294 |
struct Decoder {
|
| 295 |
struct LW {
|
|
|
|
| 478 |
};
|
| 479 |
|
| 480 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
} // namespace
|
| 482 |
|
| 483 |
KanttsPipeline::KanttsPipeline(const std::string& model_dir, const std::string& resource_dir,
|
| 484 |
const std::string& am_config)
|
| 485 |
: enc_(new ModelSession(model_dir + "/am_enc.axmodel")),
|
| 486 |
voc_(new ModelSession(model_dir + "/voc.axmodel")),
|
| 487 |
+
pe_(new ModelSession(model_dir + "/pitch_energy.axmodel")),
|
| 488 |
+
dur_(new ModelSession(model_dir + "/duration.axmodel")),
|
| 489 |
+
post_(new ModelSession(model_dir + "/postnet.axmodel")),
|
| 490 |
+
model_dir_(model_dir),
|
| 491 |
frontend_(new Frontend(resource_dir, am_config)) {
|
| 492 |
w_.Load(model_dir + "/host_weights");
|
| 493 |
std::fprintf(stderr, "[stage] weights loaded\n");
|
|
|
|
| 574 |
}
|
| 575 |
std::fprintf(stderr, "[dbg] 使用参考 memory(%d 行)\n", (int)memory.size() / 160);
|
| 576 |
} else {
|
| 577 |
+
// pitch/energy/duration 走 NPU
|
| 578 |
+
std::vector<float> var_in(T * 96);
|
| 579 |
+
for (int t = 0; t < T; ++t)
|
| 580 |
+
for (int c = 0; c < 32; ++c) {
|
| 581 |
+
var_in[t * 96 + c] = text_hid[t * 32 + c];
|
| 582 |
+
var_in[t * 96 + 32 + c] = spk_hid[t * 32 + c];
|
| 583 |
+
var_in[t * 96 + 64 + c] = emo_hid[t * 32 + c];
|
| 584 |
+
}
|
| 585 |
+
std::vector<float> pitch(T), energy(T);
|
| 586 |
+
std::vector<float> var_pad(128 * 96, 0.0f);
|
| 587 |
+
std::copy(var_in.begin(), var_in.end(), var_pad.begin());
|
| 588 |
+
pe_->SetInput("var_in", var_pad.data(), var_pad.size() * 4);
|
| 589 |
+
pe_->Run();
|
| 590 |
+
pe_->GetOutput("pitch", pitch.data(), pitch.size() * 4);
|
| 591 |
+
pe_->GetOutput("energy", energy.data(), energy.size() * 4);
|
| 592 |
+
std::vector<float> pe_c, ee_c;
|
| 593 |
+
Conv1dSame(pitch, w_.Get("pitch_emb_w"), w_.Get("pitch_emb_b"), T, 1, 32, 9, pe_c);
|
| 594 |
+
Conv1dSame(energy, w_.Get("energy_emb_w"), w_.Get("energy_emb_b"), T, 1, 32, 9, ee_c);
|
| 595 |
+
std::vector<float> aug(T * 32);
|
| 596 |
+
for (int i = 0; i < T * 32; ++i) aug[i] = text_hid[i] + pe_c[i] + ee_c[i];
|
| 597 |
+
std::vector<float> cond(T * 96);
|
| 598 |
+
for (int t = 0; t < T; ++t)
|
| 599 |
+
for (int c = 0; c < 32; ++c) {
|
| 600 |
+
cond[t * 96 + c] = aug[t * 32 + c];
|
| 601 |
+
cond[t * 96 + 32 + c] = spk_hid[t * 32 + c];
|
| 602 |
+
cond[t * 96 + 64 + c] = emo_hid[t * 32 + c];
|
| 603 |
+
}
|
| 604 |
+
std::vector<float> log_dur(T);
|
| 605 |
+
std::vector<float> cond_pad(22 * 96, 0.0f);
|
| 606 |
+
std::copy(cond.begin(), cond.end(), cond_pad.begin());
|
| 607 |
+
dur_->SetInput("cond", cond_pad.data(), cond_pad.size() * 4);
|
| 608 |
+
dur_->Run();
|
| 609 |
+
dur_->GetOutput("log_dur", log_dur.data(), log_dur.size() * 4);
|
| 610 |
+
if (std::getenv("KANTTS_DUMP_ENC")) {
|
| 611 |
+
std::fprintf(stderr, "[dbg-npu] pitch[0..3]=%.4f %.4f %.4f %.4f energy[0..3]=%.4f %.4f %.4f %.4f log_dur[0..3]=%.4f %.4f %.4f %.4f\n",
|
| 612 |
+
pitch[0], pitch[1], pitch[2], pitch[3],
|
| 613 |
+
energy[0], energy[1], energy[2], energy[3],
|
| 614 |
+
log_dur[0], log_dur[1], log_dur[2], log_dur[3]);
|
| 615 |
+
}
|
| 616 |
+
durations.resize(T);
|
| 617 |
+
int sum = 0;
|
| 618 |
+
std::vector<int> reps(T);
|
| 619 |
+
for (int t = 0; t < T; ++t) {
|
| 620 |
+
durations[t] = std::exp(log_dur[t]) - 1.0f;
|
| 621 |
+
reps[t] = (int)(durations[t] + 0.5f);
|
| 622 |
+
sum += reps[t];
|
| 623 |
+
}
|
| 624 |
+
if (std::getenv("KANTTS_DUMP_ENC")) {
|
| 625 |
+
std::fprintf(stderr, "[dbg-npu] log_dur all:");
|
| 626 |
+
for (int t = 0; t < T; ++t) std::fprintf(stderr, " %.3f", log_dur[t]);
|
| 627 |
+
std::fprintf(stderr, " | reps sum=%d\n", sum);
|
| 628 |
+
}
|
| 629 |
+
int pad = 3 - sum % 3;
|
| 630 |
+
if (pad == 3) pad = 0;
|
| 631 |
+
int P = sum + pad;
|
| 632 |
+
auto expand = [&](const std::vector<float>& src, std::vector<float>& dst) {
|
| 633 |
+
dst.assign(P * 32, 0.0f);
|
| 634 |
+
int pos = 0;
|
| 635 |
+
for (int t = 0; t < T; ++t)
|
| 636 |
+
for (int r = 0; r < reps[t]; ++r) {
|
| 637 |
+
std::copy(src.begin() + t * 32, src.begin() + (t + 1) * 32,
|
| 638 |
+
dst.begin() + (pos++) * 32);
|
| 639 |
+
}
|
| 640 |
+
};
|
| 641 |
+
std::vector<float> lr_text, lr_emo, lr_spk;
|
| 642 |
+
expand(aug, lr_text);
|
| 643 |
+
expand(emo_hid, lr_emo);
|
| 644 |
+
expand(spk_hid, lr_spk);
|
| 645 |
+
std::vector<float> rc(T + 1, 0);
|
| 646 |
+
for (int t = 0; t < T; ++t) rc[t + 1] = rc[t] + reps[t];
|
| 647 |
+
std::vector<float> lr_pos(P * 32, 0.0f);
|
| 648 |
+
for (int p = 0; p < P; ++p) {
|
| 649 |
+
int ph = 0;
|
| 650 |
+
for (int t = 0; t < T; ++t)
|
| 651 |
+
if (rc[t] <= p && p < rc[t + 1]) { ph = p - rc[t] + 1; break; }
|
| 652 |
+
for (int c = 0; c < 32; ++c) {
|
| 653 |
+
float inv = std::pow(10000.0f, 2.0f * (c / 2) / 32.0f);
|
| 654 |
+
float v = ph / inv;
|
| 655 |
+
lr_pos[p * 32 + c] = (c % 2 == 0) ? std::sin(v) : std::cos(v);
|
| 656 |
+
}
|
| 657 |
+
}
|
| 658 |
+
for (int i = 0; i < P * 32; ++i) lr_text[i] += lr_pos[i];
|
| 659 |
+
int MM = P / 3;
|
| 660 |
+
memory.assign(MM * 160, 0.0f);
|
| 661 |
+
for (int m = 0; m < MM; ++m) {
|
| 662 |
+
for (int c = 0; c < 96; ++c) memory[m * 160 + c] = lr_text[m * 96 + c];
|
| 663 |
+
for (int c = 0; c < 32; ++c) {
|
| 664 |
+
memory[m * 160 + 96 + c] = lr_spk[m * 96 + c];
|
| 665 |
+
memory[m * 160 + 128 + c] = lr_emo[m * 96 + c];
|
| 666 |
+
}
|
| 667 |
+
}
|
| 668 |
+
lr_len = sum;
|
| 669 |
}
|
| 670 |
int M = (int)memory.size() / 160;
|
| 671 |
std::fprintf(stderr, "[stage] memory M=%d lr_len=%d\n", M, lr_len);
|
|
|
|
| 677 |
}
|
| 678 |
int x_band = (int)(*std::max_element(durations.begin(), durations.end()) / 3.0f + 0.5f);
|
| 679 |
std::fprintf(stderr, "[stage] x_band=%d\n", x_band);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 680 |
std::vector<float> dec_all(M * 3 * 80);
|
| 681 |
double dec_sum = 0;
|
| 682 |
+
std::fprintf(stderr, "[timing] host(预测+memory) %.0fms\n", std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now()-t_stage).count());
|
| 683 |
+
t_stage = std::chrono::steady_clock::now();
|
| 684 |
+
// 交付配置:am_dec(PNCA 解码)默认 CPU,其余(enc/pe/dur/postnet/voc)全 NPU;
|
| 685 |
+
// KANTTS_NPU_DEC=1 可切回 NPU 解码(QAT 实验用)。
|
| 686 |
+
const bool dec_npu = std::getenv("KANTTS_NPU_DEC") != nullptr;
|
| 687 |
+
if (dec_npu) {
|
| 688 |
+
if (!dec_) dec_.reset(new ModelSession(model_dir_ + "/am_dec.axmodel"));
|
| 689 |
+
static const char* k_names[12] = {
|
| 690 |
+
"dequantize_per_tensor_101", "dequantize_per_tensor_166",
|
| 691 |
+
"dequantize_per_tensor_231", "dequantize_per_tensor_296",
|
| 692 |
+
"dequantize_per_tensor_361", "dequantize_per_tensor_426",
|
| 693 |
+
"dequantize_per_tensor_491", "dequantize_per_tensor_556",
|
| 694 |
+
"dequantize_per_tensor_621", "dequantize_per_tensor_686",
|
| 695 |
+
"dequantize_per_tensor_751", "dequantize_per_tensor_816"};
|
| 696 |
+
static const char* v_names[12] = {
|
| 697 |
+
"dequantize_per_tensor_103", "dequantize_per_tensor_168",
|
| 698 |
+
"dequantize_per_tensor_233", "dequantize_per_tensor_298",
|
| 699 |
+
"dequantize_per_tensor_363", "dequantize_per_tensor_428",
|
| 700 |
+
"dequantize_per_tensor_493", "dequantize_per_tensor_558",
|
| 701 |
+
"dequantize_per_tensor_623", "dequantize_per_tensor_688",
|
| 702 |
+
"dequantize_per_tensor_753", "dequantize_per_tensor_818"};
|
| 703 |
+
std::vector<float> mem_pad(270 * 160, 0.0f);
|
| 704 |
+
std::copy(memory.begin(), memory.end(), mem_pad.begin());
|
| 705 |
+
std::vector<float> xk(12 * 8 * 270 * 16, 0.0f), xv(12 * 8 * 270 * 16, 0.0f);
|
| 706 |
+
std::vector<float> frame(80, 0.0f), out(240), kbuf(8 * 16), vbuf(8 * 16);
|
| 707 |
+
int32_t xb = x_band, ml = M;
|
| 708 |
+
for (int s = 0; s < M; ++s) {
|
| 709 |
+
dec_->SetInput("mel_frame", frame.data(), frame.size() * 4);
|
| 710 |
+
dec_->SetInput("memory_step", memory.data() + s * 160, 160 * 4);
|
| 711 |
+
dec_->SetInput("memory", mem_pad.data(), mem_pad.size() * 4);
|
| 712 |
+
dec_->SetInput("x_k", xk.data(), xk.size() * 4);
|
| 713 |
+
dec_->SetInput("x_v", xv.data(), xv.size() * 4);
|
| 714 |
+
int32_t step_v = s;
|
| 715 |
+
dec_->SetInput("step", &step_v, 4);
|
| 716 |
+
dec_->SetInput("x_band", &xb, 4);
|
| 717 |
+
dec_->SetInput("h_band", &xb, 4);
|
| 718 |
+
dec_->SetInput("mem_len", &ml, 4);
|
| 719 |
+
dec_->Run();
|
| 720 |
+
dec_->GetOutput("output", out.data(), out.size() * 4);
|
| 721 |
+
std::copy(out.begin(), out.begin() + 240, dec_all.begin() + s * 240);
|
| 722 |
+
std::copy(out.begin() + 160, out.begin() + 240, frame.begin());
|
| 723 |
+
for (int li = 0; li < 12; ++li) {
|
| 724 |
+
dec_->GetOutput(k_names[li], kbuf.data(), kbuf.size() * 4);
|
| 725 |
+
dec_->GetOutput(v_names[li], vbuf.data(), vbuf.size() * 4);
|
| 726 |
+
for (int h = 0; h < 8; ++h)
|
| 727 |
+
for (int d = 0; d < 16; ++d) {
|
| 728 |
+
xk[(li * 8 + h) * 270 * 16 + s * 16 + d] = kbuf[h * 16 + d];
|
| 729 |
+
xv[(li * 8 + h) * 270 * 16 + s * 16 + d] = vbuf[h * 16 + d];
|
| 730 |
+
}
|
| 731 |
+
}
|
| 732 |
+
}
|
| 733 |
+
std::fprintf(stderr, "[dbg] dec NPU %d 步\n", M);
|
| 734 |
+
} else {
|
| 735 |
+
Decoder dec(w_);
|
| 736 |
+
dec.Prepare(memory);
|
| 737 |
+
std::vector<float> xk(12 * 8 * 270 * 16, 0.0f), xv(12 * 8 * 270 * 16, 0.0f);
|
| 738 |
+
std::vector<float> frame(80, 0.0f), out;
|
| 739 |
+
for (int s = 0; s < M; ++s) {
|
| 740 |
+
std::vector<float> mem_step(memory.begin() + s * 160, memory.begin() + (s + 1) * 160);
|
| 741 |
+
dec.Step(frame, mem_step, xk, xv, s, x_band, out);
|
| 742 |
+
std::copy(out.begin(), out.begin() + 240, dec_all.begin() + s * 240);
|
| 743 |
+
std::copy(out.begin() + 160, out.begin() + 240, frame.begin());
|
| 744 |
+
}
|
| 745 |
}
|
| 746 |
for (size_t i = 0; i < dec_all.size(); ++i) dec_sum += dec_all[i] * dec_all[i];
|
| 747 |
std::fprintf(stderr, "[dbg] dec rms=%.4f\n", std::sqrt(dec_sum / dec_all.size()));
|
| 748 |
std::fprintf(stderr, "[timing] decode %d 步 %.0fms\n", M, std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now()-t_stage).count());
|
| 749 |
t_stage = std::chrono::steady_clock::now();
|
| 750 |
+
std::vector<float> mel;
|
| 751 |
+
{
|
| 752 |
+
// postnet 模型固定 128 帧输入;M*3 可能超过 128,按 128 帧分块处理
|
| 753 |
+
const int Tf = M * 3;
|
| 754 |
+
for (int start = 0; start < Tf; start += 128) {
|
| 755 |
+
int n = std::min(128, Tf - start);
|
| 756 |
+
std::vector<float> dec_p(128 * 80, 0.0f);
|
| 757 |
+
std::copy(dec_all.begin() + start * 80, dec_all.begin() + (start + n) * 80,
|
| 758 |
+
dec_p.begin());
|
| 759 |
+
post_->SetInput("dec", dec_p.data(), dec_p.size() * 4);
|
| 760 |
+
post_->Run();
|
| 761 |
+
std::vector<float> mel_p(128 * 80);
|
| 762 |
+
post_->GetOutput("output", mel_p.data(), mel_p.size() * 4);
|
| 763 |
+
mel.insert(mel.end(), mel_p.begin(), mel_p.begin() + n * 80);
|
| 764 |
+
}
|
| 765 |
+
}
|
| 766 |
std::fprintf(stderr, "[timing] postnet %.0fms\n", std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now()-t_stage).count());
|
| 767 |
t_stage = std::chrono::steady_clock::now();
|
| 768 |
double mel_sum = 0;
|