some fixes but some issues

This commit is contained in:
Concedo
2026-02-25 23:41:32 +08:00
parent 0eafc3cf2d
commit 8a3ccfcba5
6 changed files with 603 additions and 23 deletions
+496
View File
@@ -0,0 +1,496 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KoboldCpp Music Generation</title>
<style>
:root{
--bg:#0f172a;
--panel:#1e293b;
--accent:#6366f1;
--accent2:#22d3ee;
--text:#f1f5f9;
--muted:#94a3b8;
--danger:#ef4444;
}
*{box-sizing:border-box}
body{
margin:0;
font-family:Inter,system-ui,sans-serif;
background:linear-gradient(135deg,#0f172a,#1e1b4b);
color:var(--text);
}
header{
padding:16px 20px;
font-size:20px;
font-weight:600;
background:rgba(0,0,0,0.3);
backdrop-filter:blur(10px);
}
.wrapper{
display:grid;
grid-template-columns:minmax(340px,500px) 1fr;
gap:20px;
padding:20px;
}
@media(max-width:1100px){
.wrapper{grid-template-columns:1fr;}
}
.panel{
background:var(--panel);
padding:18px;
border-radius:16px;
box-shadow:0 10px 40px rgba(0,0,0,.4);
}
h2{
margin:0 0 14px 0;
font-size:16px;
color:var(--accent2);
}
input,textarea{
width:100%;
padding:8px 10px;
border-radius:8px;
border:none;
background:#0f172a;
color:var(--text);
font-size:14px;
}
textarea{resize:vertical;min-height:90px;}
label{font-size:12px;color:var(--muted);}
.form-grid{
display:grid;
grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
gap:10px;
}
.compact-row{
display:grid;
grid-template-columns:repeat(auto-fit,minmax(100px,1fr));
gap:8px;
}
button{
padding:8px 12px;
border-radius:8px;
border:none;
cursor:pointer;
font-weight:600;
font-size:14px;
}
.primary{background:var(--accent);color:white;}
.secondary{background:#334155;color:white;}
.danger{background:var(--danger);color:white;}
.actions{
display:flex;
gap:10px;
margin-top:12px;
flex-wrap:wrap;
align-items:center;
}
.library-grid{
display:grid;
grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
gap:14px;
}
.library-item{
background:#0f172a;
padding:12px;
border-radius:12px;
display:flex;
flex-direction:column;
}
.library-item h4{
margin:0 0 6px 0;
font-size:14px;
}
.meta{
font-size:11px;
color:var(--muted);
margin-bottom:6px;
}
audio{width:100%;margin-top:6px;}
.advanced-toggle{
margin-top:8px;
font-size:12px;
cursor:pointer;
color:var(--accent2);
}
.hidden{display:none}
.pagination{
margin-top:12px;
display:flex;
justify-content:center;
align-items:center;
gap:10px;
}
/* Small inline spinner */
.inline-spinner{
width:18px;
height:18px;
border:3px solid rgba(255,255,255,.2);
border-top:3px solid var(--accent2);
border-radius:50%;
animation:spin 1s linear infinite;
}
@keyframes spin{
to{transform:rotate(360deg);}
}
/* Message Box */
#messageBox{
position:fixed;
bottom:20px;
right:20px;
background:#1e293b;
padding:12px 16px;
border-radius:12px;
box-shadow:0 10px 30px rgba(0,0,0,.5);
display:none;
max-width:300px;
font-size:13px;
}
</style>
</head>
<body>
<header>🎵 KoboldCpp Music Generation</header>
<div class="wrapper">
<div class="panel">
<h2>Song Setup</h2>
<label>Caption</label>
<input id="caption">
<div style="margin-top:10px">
<label>Lyrics</label>
<textarea id="lyrics"></textarea>
</div>
<div class="form-grid" style="margin-top:12px">
<div><label>BPM</label><input id="bpm" type="number"></div>
<div><label>Duration</label><input id="duration" type="number"></div>
<div><label>Key</label><input id="keyscale"></div>
<div><label>Time Sig</label><input id="timesignature"></div>
<div><label>Language</label><input id="vocal_language"></div>
</div>
<div class="advanced-toggle" onclick="toggleAdvanced()">⚙ Advanced Settings</div>
<div id="advanced" class="hidden">
<div class="compact-row" style="margin-top:10px">
<div><label>Seed</label><input id="seed" type="number"></div>
<div><label>Temp</label><input id="lm_temperature" type="number" step="0.01"></div>
<div><label>CFG</label><input id="lm_cfg_scale" type="number" step="0.1"></div>
<div><label>Top P</label><input id="lm_top_p" type="number" step="0.01"></div>
<div><label>Steps</label><input id="inference_steps" type="number"></div>
</div>
</div>
<div style="margin-top:14px">
<label>API Base URL (optional)</label>
<div style="display:flex; gap:6px;">
<input id="baseUrl" placeholder="http://localhost:5001">
</div>
</div>
<div class="actions" id="actionContainer">
<div id="normalActions" style="display:flex; gap:10px; flex-wrap:wrap;">
<button class="secondary" onclick="planSong()">Plan</button>
<button class="primary" onclick="generateSong()">Generate</button>
<button class="danger" onclick="clearFields()">Clear</button>
<button onclick="exportPlan()">Export JSON</button>
<button onclick="document.getElementById('importFile').click()">Import JSON</button>
</div>
<button id="abortBtn" class="danger hidden" onclick="abortRequest()">Abort</button>
<div id="inlineSpinner" class="inline-spinner hidden"></div>
<input type="file" id="importFile" hidden accept="application/json" onchange="importPlan(event)">
</div>
</div>
<div class="panel">
<h2>Your Library</h2>
<div id="library" class="library-grid"></div>
<div class="pagination">
<button onclick="prevPage()">Prev</button>
<span id="pageInfo"></span>
<button onclick="nextPage()">Next</button>
</div>
</div>
</div>
<div id="messageBox"><span id="messageText"></span></div>
<script>
const DB_NAME="kobo_music_db";
const STORE="kobo_music_tracks";
const PAGE_SIZE=20;
let db;
let currentPage=1;
let totalItems=0;
let currentController=null;
function setLoading(isLoading){
document.getElementById("normalActions").style.display = isLoading ? "none" : "flex";
document.getElementById("abortBtn").classList.toggle("hidden", !isLoading);
document.getElementById("inlineSpinner").classList.toggle("hidden", !isLoading);
}
function abortRequest(){
if(currentController){
currentController.abort();
currentController=null;
setLoading(false);
showMessage("Request aborted.");
}
}
function showMessage(msg, timeout=3000){
const box=document.getElementById("messageBox");
document.getElementById("messageText").innerText=msg;
box.style.display="block";
setTimeout(()=>box.style.display="none",timeout);
}
function buildUrl(path){
let BASE_URL=document.getElementById("baseUrl").value.trim();
if(!BASE_URL) return path;
return BASE_URL.replace(/\/$/,"")+path;
}
function initDB(){
return new Promise((res,rej)=>{
const req=indexedDB.open(DB_NAME,2);
req.onupgradeneeded=e=>{
db=e.target.result;
db.createObjectStore(STORE,{keyPath:"id",autoIncrement:true});
};
req.onsuccess=e=>{db=e.target.result;res()};
req.onerror=rej;
});
}
function toggleAdvanced(){
document.getElementById("advanced").classList.toggle("hidden");
}
function getFormData(){
const ids=["caption","lyrics","bpm","duration","keyscale","timesignature",
"vocal_language","seed","lm_temperature","lm_cfg_scale","lm_top_p","inference_steps"];
const data={};
ids.forEach(id=>{
const el=document.getElementById(id);
if(!el) return;
const v=el.value;
if(v!=="") data[id]=isNaN(v)?v:Number(v);
});
return data;
}
function updateForm(data){
Object.keys(data).forEach(k=>{
if(document.getElementById(k))
document.getElementById(k).value=data[k]??"";
});
}
function deriveTitle(caption){
let rnd_id = Math.floor(Math.random() * 8999) + 1000;
if(!caption)
{
caption = "Untitled";
}
let output = caption.trim().split("\n")[0].slice(0,30);
output += ` ${rnd_id}`;
return output;
}
async function planSong(){
try{
currentController=new AbortController();
setLoading(true);
const res=await fetch(buildUrl("/api/extra/music/prepare"),{
method:"POST",
headers:{"Content-Type":"application/json"},
body:JSON.stringify(getFormData()),
signal:currentController.signal
});
if(!res.ok) throw new Error();
const data=await res.json();
updateForm(data);
showMessage("Plan generated.");
}catch(e){
if(e.name!=="AbortError")
showMessage("⚠ Unable to connect to server.");
}finally{
currentController=null;
setLoading(false);
}
}
async function generateSong(){
try{
currentController=new AbortController();
setLoading(true);
const payload=getFormData();
const res=await fetch(buildUrl("/api/extra/music/generate"),{
method:"POST",
headers:{"Content-Type":"application/json"},
body:JSON.stringify(payload),
signal:currentController.signal
});
if(!res.ok) throw new Error();
const wavBlob=await res.blob();
const tx=db.transaction(STORE,"readwrite");
tx.objectStore(STORE).add({
title:deriveTitle(payload.caption),
date:new Date().toISOString(),
params:JSON.parse(JSON.stringify(payload)),
audio:wavBlob
});
tx.oncomplete=()=>{
currentPage=1;
loadLibrary();
showMessage("Song generated successfully!");
};
}catch(e){
if(e.name!=="AbortError")
showMessage("⚠ Failed to generate song.");
}finally{
currentController=null;
setLoading(false);
}
}
function downloadTrackJSON(id){
const tx = db.transaction(STORE, "readonly");
const store = tx.objectStore(STORE);
const req = store.get(id);
req.onsuccess = function(){
const item = req.result;
if(!item || !item.params){
showMessage("No JSON data found.");
return;
}
const blob = new Blob(
[JSON.stringify(item.params, null, 2)],
{ type: "application/json" }
);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${item.title}.json`;
a.click();
URL.revokeObjectURL(url);
};
req.onerror = function(){
showMessage("Failed to load JSON.");
};
}
/* Library functions unchanged */
function loadLibrary(){
const container=document.getElementById("library");
container.innerHTML="";
const tx=db.transaction(STORE,"readonly");
const store=tx.objectStore(STORE);
let items=[];
store.openCursor(null,"prev").onsuccess=e=>{
const cursor=e.target.result;
if(cursor){
items.push(cursor.value);
cursor.continue();
} else {
totalItems=items.length;
const start=(currentPage-1)*PAGE_SIZE;
const pageItems=items.slice(start,start+PAGE_SIZE);
pageItems.forEach(item=>{
const div=document.createElement("div");
div.className="library-item";
const url=URL.createObjectURL(item.audio);
div.innerHTML=`
<h4>${item.title}</h4>
<div class="meta">${new Date(item.date).toLocaleString()}</div>
<audio controls src="${url}"></audio>
<div style="margin-top:6px;display:flex;gap:6px;">
<a href="${url}" download="${item.title}.wav">
<button class="secondary">Download</button>
</a>
<button class="secondary" onclick="downloadTrackJSON(${item.id})">
Get JSON
</button>
<button class="danger" onclick="deleteTrack(${item.id})">Delete</button>
</div>
`;
container.appendChild(div);
});
const totalPages=Math.ceil(totalItems/PAGE_SIZE)||1;
document.getElementById("pageInfo").innerText=
`Page ${currentPage} / ${totalPages}`;
}
};
}
function nextPage(){ if(currentPage<Math.ceil(totalItems/PAGE_SIZE)){currentPage++;loadLibrary();}}
function prevPage(){ if(currentPage>1){currentPage--;loadLibrary();}}
function deleteTrack(id){
const tx=db.transaction(STORE,"readwrite");
tx.objectStore(STORE).delete(id);
tx.oncomplete=loadLibrary;
}
function clearFields()
{
const fields = document.querySelectorAll('.form-grid input, #advanced input');
fields.forEach(field => {
field.value = '';
});
document.getElementById("caption").value = "";
document.getElementById("lyrics").value = "";
}
function exportPlan(){
const data=getFormData();
const blob=new Blob([JSON.stringify(data,null,2)],{type:"application/json"});
const url=URL.createObjectURL(blob);
const a=document.createElement("a");
a.href=url;
a.download="music_plan.json";
a.click();
}
function importPlan(event){
const file=event.target.files[0];
if(!file) return;
const reader=new FileReader();
reader.onload=e=>{
const data=JSON.parse(e.target.result);
updateForm(data);
};
reader.readAsText(file);
}
initDB().then(loadLibrary);
</script>
</body>
</html>
+28 -2
View File
@@ -138,6 +138,8 @@ embedded_kcpp_docs_gz = None
embedded_kcpp_sdui = None
embedded_kcpp_sdui_gz = None
embedded_lcpp_ui_gz = None
embedded_musicui = None
embedded_musicui_gz = None
voicebank = {}
voicelist = ["kobo","cheery","sleepy","shouty","chatty"]
sslvalid = False
@@ -3926,7 +3928,7 @@ Change Mode<br>
self.wfile.write(finalhtml)
def do_GET(self):
global embedded_kailite, embedded_kcpp_docs, embedded_kcpp_sdui, embedded_kailite_gz, embedded_kcpp_docs_gz, embedded_kcpp_sdui_gz, embedded_lcpp_ui_gz
global embedded_kailite, embedded_kcpp_docs, embedded_kcpp_sdui, embedded_kailite_gz, embedded_kcpp_docs_gz, embedded_kcpp_sdui_gz, embedded_lcpp_ui_gz, embedded_musicui, embedded_musicui_gz
global last_req_time, start_time, cached_chat_template, has_vision_support, has_audio_support, has_whisper, friendlymodelname
global savedata_obj, has_multiplayer, multiplayer_turn_major, multiplayer_turn_minor, multiplayer_story_data_compressed, multiplayer_dataformat, multiplayer_lastactive, maxctx, maxhordelen, friendlymodelname, lastuploadedcomfyimg, lastgeneratedcomfyimg, KcppVersion, totalgens, preloaded_story, exitcounter, currentusergenkey, friendlysdmodelname, fullsdmodelpath, password, friendlyembeddingsmodelname, voicelist
@@ -4230,6 +4232,16 @@ Change Mode<br>
else:
response_body = ("KoboldCpp API is running, but KCPP SDUI is not loaded").encode()
elif clean_path.startswith(("/musicui")):
content_type = 'text/html'
if supports_gzip and embedded_musicui_gz is not None:
response_body = embedded_musicui_gz
content_encoding = 'gzip'
elif embedded_musicui is not None:
response_body = embedded_musicui
else:
response_body = ("KoboldCpp API is running, but KCPP MusicUI is not loaded").encode()
elif clean_path=="/v1":
content_type = 'text/html'
response_body = ("KoboldCpp OpenAI compatible endpoint is running!<br>For usage reference, see <a href='https://platform.openai.com/docs/api-reference'>https://platform.openai.com/docs/api-reference</a><br>For other endpoints, see <a href='/api'>KoboldCpp API Documentation</a>").encode()
@@ -8269,7 +8281,7 @@ def main(launch_args, default_args):
input()
def kcpp_main_process(launch_args, g_memory=None, gui_launcher=False):
global embedded_kailite, embedded_kcpp_docs, embedded_kcpp_sdui, embedded_kailite_gz, embedded_kcpp_docs_gz, embedded_kcpp_sdui_gz, embedded_lcpp_ui_gz, start_time, exitcounter, global_memory, using_gui_launcher
global embedded_kailite, embedded_kcpp_docs, embedded_kcpp_sdui, embedded_kailite_gz, embedded_kcpp_docs_gz, embedded_kcpp_sdui_gz, embedded_lcpp_ui_gz, embedded_musicui, embedded_musicui_gz, start_time, exitcounter, global_memory, using_gui_launcher
global libname, args, friendlymodelname, friendlysdmodelname, fullsdmodelpath, password, fullwhispermodelpath, ttsmodelpath, embeddingsmodelpath, musicdiffusionmodelpath, friendlyembeddingsmodelname, has_audio_support, has_vision_support, cached_chat_template
start_server = True
@@ -8882,6 +8894,15 @@ def kcpp_main_process(launch_args, g_memory=None, gui_launcher=False):
except Exception:
print("Could not find Embedded llama.cpp UI.")
try:
with open(os.path.join(embddir, "kcpp_musicui.embd"), mode='rb') as f:
embedded_musicui = f.read()
embedded_musicui_gz = gzip.compress(embedded_musicui)
if args.musicllm or args.musicdiffusion:
print("Embedded MusicUI loaded.")
except Exception:
print("Could not find Embedded MusicUI.")
# load all TTS audio files
if args.ttsdir and args.ttsmodel and os.path.isdir(args.ttsdir):
try:
@@ -8946,6 +8967,7 @@ def kcpp_main_process(launch_args, g_memory=None, gui_launcher=False):
enabledmlist.append("VectorEmbeddings") if "embeddings" in caps and caps["embeddings"] else disabledmlist.append("VectorEmbeddings")
enabledmlist.append("AdminControl") if "admin" in caps and caps["admin"]!=0 else disabledmlist.append("AdminControl")
enabledmlist.append("MCPBridge") if "mcp" in caps and caps["mcp"] else disabledmlist.append("MCPBridge")
enabledmlist.append("MusicGen") if "music" in caps and caps["music"] else disabledmlist.append("MusicGen")
print(f"======\nActive Modules: {' '.join(enabledmlist)}")
print(f"Inactive Modules: {' '.join(disabledmlist)}")
@@ -8974,6 +8996,8 @@ def kcpp_main_process(launch_args, g_memory=None, gui_launcher=False):
print(f"Starting llama.cpp secondary WebUI at {endpoint_url}/lcpp/")
if args.sdmodel:
print(f"StableUI is available at {endpoint_url}/sdui/")
if args.musicdiffusion or args.musicllm:
print(f"MusicUI is available at {endpoint_url}/musicui/")
elif global_memory:
val = global_memory["tunnel_url"]
if val:
@@ -8984,6 +9008,8 @@ def kcpp_main_process(launch_args, g_memory=None, gui_launcher=False):
print(f"Starting llama.cpp secondary WebUI at {endpoint_url}/lcpp/")
if args.sdmodel:
print(f"StableUI is available at {endpoint_url}/sdui/")
if args.musicdiffusion or args.musicllm:
print(f"MusicUI is available at {endpoint_url}/musicui/")
global_memory["load_complete"] = True
if args.launch:
def launch_browser_thread():
+16 -9
View File
@@ -1520,23 +1520,30 @@ std::string acestep_prepare_request(const music_generation_inputs inputs)
bool user_has_codes = !req.audio_codes.empty();
bool need_lm_codes = req.thinking && !user_has_codes;
bool is_simple = ace.lyrics.empty() &&
ace.bpm <= 0 && ace.duration <= 0 &&
ace.keyscale.empty() && ace.timesignature.empty();
bool is_simple = ace.lyrics.empty();
std::vector<int> prompt;
std::vector<AcePrompt> aces; // populated by Phase 1 (simple or partial)
// Preprocessor: simple mode generates lyrics + metas from caption
if (is_simple) {
fprintf(stderr, "[Simple] Inspiration\n");
fprintf(stderr, "[Simple] Inspiration, Language: %s\n",ace.vocal_language.c_str());
const char * sys =
"# Instruction\n"
"Expand the user's input into a more detailed"
" and specific musical description:\n";
std::string user_msg = ace.caption + "\n\ninstrumental: "
+ std::string(req.instrumental ? "true" : "false");
"Expand the user's input into a more detailed and specific musical description:\n";
bool forcelang = (ace.vocal_language != "unknown" && !ace.vocal_language.empty());
std::string langstr = forcelang?("language: "+ace.vocal_language+"\n"):"";
std::string cap = "";
std::string instru = "instrumental: false\n";
if(ace.caption!="")
{
cap = "Music Caption: " + ace.caption;
}
std::string user_msg = cap + "\n\n"+instru+langstr;
printf("\n[Prompt: %s]\n",user_msg.c_str());
prompt = build_custom_prompt(acestep_bpe, sys, user_msg.c_str());
// FSM: reset then optionally force language (shared for both paths)
@@ -1549,7 +1556,7 @@ std::string acestep_prepare_request(const music_generation_inputs inputs)
prompt.size(), batch_size, seed, seed + batch_size - 1);
auto phase1_texts = generate_phase1_batch(
&acestep_llm, &acestep_bpe, prompt, 2048, temperature, 1.0f, 0,
&acestep_llm, &acestep_bpe, prompt, 2048, temperature, 0.95f, 0,
seed, batch_size, use_fsm ? &fsm : nullptr, true);
parse_phase1_into_aces(phase1_texts, ace, aces, seed, "Simple", true);
+58 -7
View File
@@ -179,9 +179,21 @@ static void cond_ggml_forward(CondGGML * m,
// Linear embed: [1024, S_lyric] -> [2048, S_lyric]
struct ggml_tensor * lyric_h = qwen3_linear_bias(ctx, m->lyric_embed_w,
m->lyric_embed_b, t_lyric_in);
// 8 layers + final norm (bidirectional: mask=NULL)
lyric_h = qwen3_build_layers(ctx, m->lyric_cfg, m->lyric_layers, m->lyric_norm,
lyric_h, lyric_pos, NULL, S_lyric);
// Bidirectional sliding window mask for even layers (|i-j| <= 128)
// Python: layer_types = [sliding, full, sliding, full, ...]
// sliding_window = 128
struct ggml_tensor * lyric_slide_mask = ggml_new_tensor_2d(ctx, GGML_TYPE_F16, S_lyric, S_lyric);
ggml_set_name(lyric_slide_mask, "lyric_slide_mask");
ggml_set_input(lyric_slide_mask);
// 8 layers with alternating masks + final norm
for (int i = 0; i < m->lyric_cfg.n_layers; i++) {
struct ggml_tensor * layer_mask = (i % 2 == 0) ? lyric_slide_mask : NULL;
lyric_h = qwen3_build_layer(ctx, m->lyric_cfg, &m->lyric_layers[i],
lyric_h, lyric_pos, layer_mask, S_lyric);
}
lyric_h = qwen3_rms_norm(ctx, lyric_h, m->lyric_norm, m->lyric_cfg.rms_norm_eps);
ggml_set_name(lyric_h, "lyric_out");
ggml_set_output(lyric_h);
@@ -200,6 +212,7 @@ static void cond_ggml_forward(CondGGML * m,
struct ggml_tensor * timbre_out = NULL;
struct ggml_tensor * t_timbre_in = NULL;
struct ggml_tensor * timbre_pos = NULL;
struct ggml_tensor * timbre_slide_mask = NULL;
if (has_timbre) {
timbre_pos = ggml_new_tensor_1d(ctx, GGML_TYPE_I32, S_ref);
@@ -213,9 +226,19 @@ static void cond_ggml_forward(CondGGML * m,
// Linear embed: [64, S_ref] -> [2048, S_ref]
struct ggml_tensor * timbre_h = qwen3_linear_bias(ctx, m->timbre_embed_w,
m->timbre_embed_b, t_timbre_in);
// 4 layers + final norm
timbre_h = qwen3_build_layers(ctx, m->timbre_cfg, m->timbre_layers, m->timbre_norm,
timbre_h, timbre_pos, NULL, S_ref);
// Bidirectional sliding window mask for even layers
timbre_slide_mask = ggml_new_tensor_2d(ctx, GGML_TYPE_F16, S_ref, S_ref);
ggml_set_name(timbre_slide_mask, "timbre_slide_mask");
ggml_set_input(timbre_slide_mask);
// 4 layers with alternating masks + final norm
for (int i = 0; i < m->timbre_cfg.n_layers; i++) {
struct ggml_tensor * layer_mask = (i % 2 == 0) ? timbre_slide_mask : NULL;
timbre_h = qwen3_build_layer(ctx, m->timbre_cfg, &m->timbre_layers[i],
timbre_h, timbre_pos, layer_mask, S_ref);
}
timbre_h = qwen3_rms_norm(ctx, timbre_h, m->timbre_norm, m->timbre_cfg.rms_norm_eps);
// Take first frame: [2048, S_ref] -> view [2048, 1]
timbre_out = ggml_view_2d(ctx, timbre_h, H, 1,
@@ -242,11 +265,39 @@ static void cond_ggml_forward(CondGGML * m,
ggml_backend_tensor_set(lyric_pos, pos.data(), 0, S_lyric * sizeof(int));
}
// Lyric sliding window mask: bidirectional, |i-j| <= 128
{
const int W = 128;
std::vector<uint16_t> mask_data(S_lyric * S_lyric);
for (int i = 0; i < S_lyric; i++) {
for (int j = 0; j < S_lyric; j++) {
int d = i - j; if (d < 0) d = -d;
mask_data[i * S_lyric + j] = ggml_fp32_to_fp16(d <= W ? 0.0f : -INFINITY);
}
}
ggml_backend_tensor_set(lyric_slide_mask, mask_data.data(), 0,
S_lyric * S_lyric * sizeof(uint16_t));
fprintf(stderr, "[CondEnc] Lyric sliding mask: %dx%d, window=%d\n", S_lyric, S_lyric, W);
}
if (has_timbre) {
ggml_backend_tensor_set(t_timbre_in, timbre_feats, 0, 64 * S_ref * sizeof(float));
std::vector<int> pos(S_ref);
for (int i = 0; i < S_ref; i++) pos[i] = i;
ggml_backend_tensor_set(timbre_pos, pos.data(), 0, S_ref * sizeof(int));
// Timbre sliding window mask: bidirectional, |i-j| <= 128
const int W = 128;
std::vector<uint16_t> mask_data(S_ref * S_ref);
for (int i = 0; i < S_ref; i++) {
for (int j = 0; j < S_ref; j++) {
int d = i - j; if (d < 0) d = -d;
mask_data[i * S_ref + j] = ggml_fp32_to_fp16(d <= W ? 0.0f : -INFINITY);
}
}
ggml_backend_tensor_set(timbre_slide_mask, mask_data.data(), 0,
S_ref * S_ref * sizeof(uint16_t));
fprintf(stderr, "[CondEnc] Timbre sliding mask: %dx%d, window=%d\n", S_ref, S_ref, W);
}
// Compute
@@ -292,4 +343,4 @@ static void cond_ggml_free(CondGGML * m) {
if (m->cpu_backend) ggml_backend_free(m->cpu_backend);
wctx_free(&m->wctx);
*m = {};
}
}
+4 -4
View File
@@ -762,7 +762,7 @@ std::string acestep_generate_audio(const music_generation_inputs inputs)
const char * keyscale = req.keyscale.empty() ? "N/A" : req.keyscale.c_str();
const char * timesig = req.timesignature.empty() ? "N/A" : req.timesignature.c_str();
const char * language = req.vocal_language.empty() ? "en" : req.vocal_language.c_str();
float duration = req.duration > 0 ? req.duration : 120.0f;
float duration = req.duration > 0 ? req.duration : 60.0f;
long long seed = req.seed;
int num_steps = req.inference_steps > 0 ? req.inference_steps : 8;
float guidance_scale = req.guidance_scale > 0 ? req.guidance_scale : 7.0f;
@@ -869,8 +869,8 @@ std::string acestep_generate_audio(const music_generation_inputs inputs)
// Context building
// Silence latent for this T
std::vector<float> silence(Oc * T);
memcpy(silence.data(), silence_full.data(), (size_t)(Oc * T) * sizeof(float));
// std::vector<float> silence(Oc * T);
// memcpy(silence.data(), silence_full.data(), (size_t)(Oc * T) * sizeof(float));
// Decode audio codes if provided
int decoded_T = 0;
@@ -896,7 +896,7 @@ std::string acestep_generate_audio(const music_generation_inputs inputs)
for (int t = 0; t < T; t++) {
const float * src = (t < decoded_T)
? decoded_latents.data() + t * Oc
: silence.data() + t * Oc;
: silence_full.data() + (t - decoded_T) * Oc;
for (int c = 0; c < Oc; c++)
context_single[t * ctx_ch + c] = src[c];
for (int c = 0; c < Oc; c++)
+1 -1
View File
@@ -19,7 +19,7 @@ void request_init(AceRequest * r) {
r->duration = -1.0f;
r->keyscale = "";
r->timesignature = "";
r->vocal_language = "unknown";
r->vocal_language = "en";
r->task_type = "text2music";
r->seed = -1;
r->thinking = false;