Phase 4+5: WebAudio I/O shim + verify DAW checklist — live=export, order, fader, PDC, smoke

This commit is contained in:
2026-08-22 21:02:52 +07:00
parent e5c957fc87
commit c3aba40ffe
9 changed files with 756 additions and 388 deletions
+17
View File
@@ -205,6 +205,23 @@ public:
}
bool setParam(const std::string& key, double value) override {
if (key == "amount") { amount_ = value / 100.0; rebuild(); return true; }
if (key.compare(0, 4, "band") == 0) {
const size_t us = key.find('_', 4);
if (us != std::string::npos && us > 4) {
const int idx = std::atoi(key.c_str() + 4);
const std::string field = key.substr(us + 1);
if (idx >= 0 && idx < (int)bands_.size()) {
Band& b = bands_[idx];
if (field == "freq") b.freq = value;
else if (field == "gain") b.gain = value;
else if (field == "q") b.q = value;
else if (field == "active") b.active = (value != 0.0);
else return false;
rebuild();
return true;
}
}
}
return false;
}
private:
+24 -3
View File
@@ -1144,6 +1144,12 @@ struct RealtimeFxChain::Impl {
};
struct Chain { std::vector<Entry> entries; };
// SET_PARAM chờ chain swap (setParam tới trước setChain): worker áp sau
// khi swap — không mất param race lúc khởi động.
struct PendingParam { int slot; std::string key; double value; };
std::mutex pmutex_; // guards pending_
std::vector<PendingParam> pending_;
std::mutex mutex_; // guards chain_ / retired_
std::shared_ptr<Chain> chain_;
std::shared_ptr<Chain> retired_; // dtor deferred to the worker thread
@@ -1224,9 +1230,14 @@ void RealtimeFxChain::setParam(int slot, const std::string& key, double value) {
if (!impl_) return;
std::shared_ptr<Impl::Chain> c;
{ std::lock_guard<std::mutex> lk(impl_->mutex_); c = impl_->chain_; }
if (!c || slot < 0 || (size_t)slot >= c->entries.size()) return;
auto& e = c->entries[(size_t)slot];
if (e.bfx) e.bfx->setParam(key, value);
if (c && slot >= 0 && (size_t)slot < c->entries.size()) {
auto& e = c->entries[(size_t)slot];
if (e.bfx) e.bfx->setParam(key, value);
return;
}
// Chain chưa swap (SET_PARAM tới trước setChain) — stash, worker áp sau swap.
std::lock_guard<std::mutex> lk(impl_->pmutex_);
impl_->pending_.push_back({slot, key, value});
}
uint64_t RealtimeFxChain::chainGen() {
@@ -1325,6 +1336,16 @@ void RealtimeFxChain::Impl::workerLoop() {
retired_ = std::move(chain_); // old chain destroyed on THIS thread
chain_ = std::move(next);
}
{
// Áp param chờ (đăng ký trước khi chain tồn tại).
std::lock_guard<std::mutex> lk(pmutex_);
for (const auto& p : pending_) {
if (p.slot < 0 || (size_t)p.slot >= chain_->entries.size()) continue;
auto& e = chain_->entries[(size_t)p.slot];
if (e.bfx) e.bfx->setParam(p.key, p.value);
}
pending_.clear();
}
gen_.fetch_add(1, std::memory_order_release); // loop báo lại latency
}
#ifdef _WIN32