From 30afb78e565dcff78a8cf2338cbffed1399a3e0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 03:48:40 +0000 Subject: [PATCH 1/2] Initial plan From 9cf3cdf652a2a8b4e83e1c4b9e20b0edc9edd317 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 03:51:55 +0000 Subject: [PATCH 2/2] Define named constants for preferredStemCount limits with documentation Co-authored-by: soficis <107279009+soficis@users.noreply.github.com> --- src/domain/JsonSerialization.cpp | 4 +++- src/domain/ProjectProfile.cpp | 2 +- src/domain/ProjectProfile.h | 6 ++++++ tools/commands/DevToolsUtils.cpp | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/domain/JsonSerialization.cpp b/src/domain/JsonSerialization.cpp index ca354f5..71849c1 100644 --- a/src/domain/JsonSerialization.cpp +++ b/src/domain/JsonSerialization.cpp @@ -2,6 +2,8 @@ #include +#include "domain/ProjectProfile.h" + namespace automix::domain { void to_json(Json& j, const Stem& value) { @@ -293,7 +295,7 @@ void from_json(const Json& j, Session& value) { value.buses = j.value("buses", std::vector{}); value.projectProfileId = j.value("projectProfileId", "default"); value.safetyPolicyId = j.value("safetyPolicyId", "balanced"); - value.preferredStemCount = std::clamp(j.value("preferredStemCount", 4), 2, 6); + value.preferredStemCount = std::clamp(j.value("preferredStemCount", 4), kMinPreferredStemCount, kMaxPreferredStemCount); const auto timelineJson = j.value("timeline", Json::object()); value.timeline.loopEnabled = timelineJson.value("loopEnabled", false); diff --git a/src/domain/ProjectProfile.cpp b/src/domain/ProjectProfile.cpp index efb2680..c6ad4c7 100644 --- a/src/domain/ProjectProfile.cpp +++ b/src/domain/ProjectProfile.cpp @@ -24,7 +24,7 @@ ProjectProfile profileFromJson(const nlohmann::json& json) { profile.mixModelPackId = json.value("mixModelPackId", "none"); profile.masterModelPackId = json.value("masterModelPackId", "none"); profile.safetyPolicyId = json.value("safetyPolicyId", "balanced"); - profile.preferredStemCount = std::clamp(json.value("preferredStemCount", 4), 2, 6); + profile.preferredStemCount = std::clamp(json.value("preferredStemCount", 4), kMinPreferredStemCount, kMaxPreferredStemCount); profile.metadataPolicy = json.value("metadataPolicy", "copy_common"); if (profile.metadataPolicy != "copy_all" && profile.metadataPolicy != "copy_common" && diff --git a/src/domain/ProjectProfile.h b/src/domain/ProjectProfile.h index 638a2f1..501dc0f 100644 --- a/src/domain/ProjectProfile.h +++ b/src/domain/ProjectProfile.h @@ -8,6 +8,12 @@ namespace automix::domain { +// Stem count constraints for audio separation. +// Maximum of 6 stems is based on common separation models (vocals, drums, bass, guitar, keys, other) +// and practical UI/performance limits for real-time mixing workflows. +constexpr int kMinPreferredStemCount = 2; +constexpr int kMaxPreferredStemCount = 6; + struct ProjectProfile { std::string id; std::string name; diff --git a/tools/commands/DevToolsUtils.cpp b/tools/commands/DevToolsUtils.cpp index 9659027..86a03c7 100644 --- a/tools/commands/DevToolsUtils.cpp +++ b/tools/commands/DevToolsUtils.cpp @@ -693,7 +693,7 @@ std::optional projectProfileFromJson(const nloh profile.mixModelPackId = json.value("mixModelPackId", "none"); profile.masterModelPackId = json.value("masterModelPackId", "none"); profile.safetyPolicyId = json.value("safetyPolicyId", "balanced"); - profile.preferredStemCount = std::clamp(json.value("preferredStemCount", 4), 2, 6); + profile.preferredStemCount = std::clamp(json.value("preferredStemCount", 4), kMinPreferredStemCount, kMaxPreferredStemCount); profile.metadataPolicy = json.value("metadataPolicy", "copy_common"); if (profile.metadataPolicy != "copy_all" && profile.metadataPolicy != "copy_common" &&