ComfyUI Node
Siren Score (Lyrics β Plan) π§
Builds Siren Cast's plan from the lyrics instead of asking an LLM for it: the section list and order come from the '[Verse 1 - ...]' markers, the voice from the name in the marker (or MALE/FEMALE matched against the wired Character Cards, or the marker's own words), and each section's length from how many lines it has. So the song is exactly as long as its lyrics, which is the one thing a bar budget cannot make true. Two singers in one section are ALTERNATED where per-line markers allow it and reduced to a lead plus backing where they don't, because one description over the same frames comes back as a blend. Wire an LLM's table into 'plan' instead and it is passed through and audited.
Siren Score (Lyrics β Plan) π§
- voice_1
- voice_2
- plan
- report
βlyricsββΊ
βbpm120βΊ
βtimesignature4βΊ
βpad_to_seconds150βΊ
βtail_bars4βΊ
βpad_placementafter the vocalsβΊ
βpad_block_bars16βΊ
βmin_bars4βΊ
βinstrumental_bars4βΊ
βduetslead + split on inner markersβΊ
βarrangement_notesfalseβΊ
βverbosetrueβΊ
CategoryKinburg-Nodes/Bestiary/Siren
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| lyrics | STRING | The lyrics, with '[Verse 1 - ...]' style markers. The SAME text that goes to Siren Cast β wire one source into both. What the markers need: the section name FIRST (Intro / Verse 1 / Pre-Chorus / Chorus / Post-Chorus / Bridge / Solo / Break / Outro, or a synonym), then ideally the member's name, then how they sing it. 'MALE'/'FEMALE' works instead of a name when the roster has exactly one of each. A bracketed line that NAMES a member splits the section β that is how an exchange between two singers is written, and it is the only way the model can actually do two voices. Any other bracketed line is an annotation of the current section. | |
| bpm | INT | 12010β300 | Tempo β only used to report the resulting length in seconds. The plan itself is written in bars, so Siren Cast converts it with ITS bpm; wire both from one source or the report will lie to you. |
| timesignature | STRING | 4 | Beats per bar, for the same reason as 'bpm'. A plain field rather than a dropdown because a combo input cannot accept the STRING a text parser hands it β anything with a digit in it is read (4, '4', '4/4'). |
| pad_to_seconds | FLOAT | 15010β2000 | How long the song should be, in seconds β the reference the whole plan is built from. The bars it buys are shared out like this: instrumental sections (a marker with no sung lines) take 'instrumental_bars' each, 'tail_bars' comes off the end, and everything left goes to the sung sections IN PROPORTION TO THEIR SYLLABLES. So the singing rate is not a dial here, it is a consequence β the report prints what it came out at. If that lands outside 2-8 syllables a second the node says so and names the length this lyric would actually suit, because a section given more room than its words need does not get sung slower: the model FILLS it, and at the top of a song that reads as the intro running on. |
| tail_bars | COMBO | 4 | Bars of instrumental added after the vocals, so the track does not stop dead on the last word. 0 = none. Measured with 'lyrics_in_negative' off, which is the setting that makes the voices land: a SHORT tail (2-8 bars) gives a last chorus, a proper outro and a clean ending. A LONG one is actively bad β the model repeats the last phrase over and over to fill it, and starts eating the ends of notes the singer should be holding. It also lengthens the intro, which is the other thing to listen for. This replaced a target-duration dial. That one made the tail whatever was left over between the lyrics and the target, which is how a six-section lyric ended up with forty bars of instrumental behind it. |
| pad_placement | COMBO | after the vocals | Where the instrumental blocks go. The trade-off is not taste β it is where a lyric can be interrupted. AceStep gets the words with NO timing in them, matched against the plan, so a gap in the middle asks the model to hold the line until the singing resumes; if it doesn't, everything after it shifts. β’ after the vocals β everything at the end. The least song-shaped, and the only one with a take behind it, which is why it is the default. β’ intro + outro β a third opens the record, the rest is an outro jam. Still entirely outside the lyric, so it carries the same zero risk and sounds more like a record. Try this second. β’ between sections β one block opens, the rest go after choruses and bridges (never inside a verse running into its own pre-chorus), remainder at the end. The most song-shaped and the only one that can make the lyric drift. |
| pad_block_bars | INT | 162β64 | Longest instrumental section the padding may use. The tail is split into as FEW rows as it takes, each at most this, sharing the bars out evenly β 40 bars at 16 becomes 14 + 13 + 13, not twenty rows of 2. Why it matters: every row is its own LM decode with its own caption, so a tail chopped into 2-bar rows is a restart every ten audio codes β no room for the model to develop anything, and a seam at each one. Merging them by hand was the first thing that sounded better, so this does it by default. Raise it for one long jam, lower it for a tail that changes character more often. |
| min_bars | INT | 42β32 | Floor for a whole section. Below about 4 bars a section is too short for a voice to establish itself. Sub-sections made by inner markers are exempt β an exchange of single shouted lines is meant to be short, and they get a floor of 2 bars instead. |
| instrumental_bars | INT | 42β32 | Length for a section with no sung lines at all (an instrumental intro, a solo, a break). There is no line count to derive it from, so it is simply this. |
| duets | COMBO | lead + split on inner markers | What to do with a section header that names more than one singer AND has no inner markers to split on. The plan carries ONE audio code per 200 ms and the caption is one description, so two timbres over the same frames come back as their average β measured once as 'two female vocals' where a man and a woman were asked for. This does NOT govern inner markers. A bracketed line naming a member always starts a sub-section, in every mode, so the voices ALTERNATE β that is an explicit instruction in the lyrics and the one form of duet the model genuinely does well. It used to be switched off by this setting, which meant a song could have alternation or a unison chorus but never both, and the loss was silent. β’ lead + split on inner markers (recommended) β an unsplittable header duet becomes the first-named singer plus a short backing note carrying the other's own timbre. β’ both names in one section β both names go into the cell and 'Siren Cast' decides what to do with them, which is where the unison mode lives. Use this when a section is meant to be sung TOGETHER. |
| arrangement_notes | BOOLEAN | false | Put the non-vocal part of a marker into the plan's 4th column, which appends it to that section's caption β '[Chorus - massive explosion of sound, wall of distorted guitars]' is a real instruction about the chorus and this is the only place it fits. Everything here lands inside Siren Cast's cfg delta, so it is guided as hard as the voice is: at most 4 clauses per section are kept and the rest is reported. If a take comes back muddy or sung by one indistinct voice, turning this OFF is the cheapest thing to try. |
| verbose | BOOLEAN | true | Print the report to the console. The same text is always on the 'report' output. |
| voice_1opt | KINBURG_VOICE | A band member β Character Card's 'voice' output. Wire the SAME cards you wire into Siren Cast: this node matches marker names against them and reads their gender when a marker only says MALE / FEMALE. With nothing wired the markers' own wording is used as the vocal description, which still works β it just can't say 'Nina', and inner markers can't split a section. | |
| voice_2opt | KINBURG_VOICE | β |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| plan | STRING | β |
| report | STRING | β |