# Chapter 9 · Phrases and Motivic Development In [Chapter 8](08-motifs) you named a short figure as a Motif and learned that its transforms hand you *new* values; now we grow one of those motifs into a multi-bar **phrase** — a sentence, a period, a development plan — place its per-cycle window in a pattern, and regenerate a bar or two while keeping the rest. A motif is a single gesture; a phrase is a *sentence made of gestures*. Where the last chapter gave you the words, this one gives you the grammar that turns "five, six, five, three" into eight bars that state an idea, push it, and land. And because a phrase is a value — frozen, printable, immutable, exactly like the Motif and Progression before it — you can develop it, inspect it, and surgically edit one bar without disturbing the others. That last move, **selective regeneration**, is the manual-to-generate-and-back round trip this whole Part has been building toward. ```{testsetup} ch9 # Hidden per-chapter setup: the imports the first example shows in full, so later # blocks can use these names without repeating them. import subsequence from subsequence import motif, sentence, period, Phrase, Motif, progression import subsequence.constants.instruments.gm_drums as gm_drums import subsequence.constants.midi_notes as notes ``` (sec-motif-to-phrase)= ## 9.1 From motif to phrase A **Phrase** is a frozen *sequence of Motifs* — and crucially, it keeps the seams between them. Where a Motif is one figure, a Phrase remembers that it is "this two-bar idea, then that one, then a third" — and that **segmentation is the unit of editing**. It is what every builder, development plan, and selective reroll in this chapter operates on. You already met the smallest way to make one in [Chapter 8](08-motifs): the `+` operator joins two motifs into a two-segment phrase, and `*` repeats one. Start there. Here is a two-bar *basic idea* — a melody as scale degrees, the relative form from [§5.1](05-pitch-and-scales) — and the simplest phrase you can build from it, the idea stated and then answered: ```{testcode} ch9 import subsequence from subsequence import motif, sentence, period, Phrase # A two-bar basic idea: degrees, one per beat, with a rest at beat 4. idea = motif([5, 6, 5, 3, None, 1, 2, 3]) print(idea.describe()) # `+` makes a two-segment Phrase; the second segment is the idea, varied. simple = idea + idea.vary(notes=1, seed=4) print(simple.describe()) ``` ```{testoutput} ch9 Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] Phrase 16 beats, 2 segments 1. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 2. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^2@7] ``` Read the printout the way you read a progression's `.describe()` in [§7.2](07-progressions): one line per *segment*, each itself a one-line motif summary. The `^5@0` notation is "degree 5, at beat 0" — the same degree content from the last chapter, now laid out across the phrase. The two segments are identical except for their last note (`^3` became `^2`), because `vary()` moved a single tail pitch and left everything else — rhythm, the other notes, the rest — untouched. ```{note} **A Phrase keeps its seams; a Motif erases them.** `idea + idea` gives a *two-segment* Phrase (16 beats, two motifs you can still address individually); `idea.then(idea)` from [§8.4](08-motifs) gives *one* 16-beat Motif with no internal boundary. The seam is not cosmetic — `replace`, `reroll`, and every development plan in this chapter act on segments, so when you want a thing you can later edit bar by bar, keep it a Phrase. To collapse a phrase into one flat motif when you no longer need the seams, call `.flatten()` ([§9.5](#sec-selective)). ``` Building phrases by hand with `+` and `vary()` works, but for the shapes a musician already knows by name — the *sentence*, the *period* — Subsequence gives you one-call builders. That is the next section. ```{admonition} Reference :class: seealso {py:class}`~subsequence.motifs.Phrase` ``` (sec-builders)= ## 9.2 Classical builders: `sentence()` and `period()` Two phrase shapes are old enough to have names in every theory book, and Subsequence ships both as thin combinators. They take a basic idea and a cadence, and hand you back a finished phrase — segmentation, contrast, and close all in place. They are `subsequence.sentence(...)` and `subsequence.period(...)`, importable directly. ### The sentence: idea, idea, drive, close A **sentence** is four units: the basic idea stated twice (the *presentation*), a contrasting *continuation* that develops the material, and a *cadential* unit whose tail lands on the cadence. An eight-bar sentence from a two-bar idea is the textbook proportion. ```{testcode} ch9 idea = motif([5, 6, 5, 3, None, 1, 2, 3]) # the two-bar basic idea again verse = sentence(idea, bars=8, cadence="open", seed=11) print(verse.describe()) ``` ```{testoutput} ch9 Phrase 32 beats, 4 segments 1. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 2. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 3. Motif 8 beats [^6@0, ^6@1, ^5@2, ^5@3, ^1@5, ^2@6, ^5@7] 4. Motif 8 beats [^6@0, ^6@1, ^6@2, ^5@3, ^1@5, ^2@6, ^5@7] ``` The four segments are exactly the sentence anatomy. Segments 1 and 2 are your idea, verbatim — that is the *presentation*, the figure stated and immediately restated. Segment 3 keeps the idea's rhythm but re-pitches it: a recognisable but new *continuation*. Segment 4 is the *cadential* unit, and because we asked for `cadence="open"`, its last pitched note lands on degree `5` (`^5@7`) — the half-close, the musical comma that leaves the door ajar for whatever comes next. The `cadence` argument is the same vocabulary you met for harmony in [§7.5](07-progressions), here aiming the *melody's* last note rather than rewriting chords: ```{list-table} :header-rows: 1 :widths: 22 18 60 * - `cadence=` - Lands on - The feeling * - `"strong"` - degree 1 - The full stop — the tune comes home. (Theory: *authentic*.) * - `"open"` - degree 5 - A question, a comma — hangs unresolved. (*Half*.) * - `"soft"` - degree 1 - Also home, the gentler close. (*Plagal*.) * - `"fakeout"` - degree 1 - The melodic close still aims home; the *swerve* is harmonic. (*Deceptive*.) ``` ```{important} **A cadence has two halves, and `sentence()` writes only the melodic one.** The builder re-aims the *tune's* last note (degree 5 for `"open"`, degree 1 for the closes). The *harmony's* cadence — the V→I or IV→V under it — is a separate call: `prog.cadence("open")` from [§7.5](07-progressions), or `cadence=` on the live engine. Pair the two and the melody and chords arrive at the cadence together; use one without the other and only half the punctuation lands. They are written separately on purpose — a melody can ask a question over a harmony that answers, and that tension is a tool. ``` ### The period: question, then answer A **period** is two halves of the *same* material that differ only at their close. The first half — the *antecedent* — ends open, on a half-close; the second — the *consequent* — restates it but ends home. The open-then-closed contrast *is* the period. Because nothing is generated (only the two tail notes re-aim), `period()` is fully deterministic and takes no seed. ```{testcode} ch9 # A two-bar antecedent (length=8 makes the trailing rest explicit). antecedent = motif([3, 4, 5, 1, None, 6, 5, 4], length=8) question_answer = period(antecedent) print(question_answer.describe()) ``` ```{testoutput} ch9 Phrase 16 beats, 2 segments 1. Motif 8 beats [^3@0, ^4@1, ^5@2, ^1@3, ^6@5, ^5@6, ^5@7] 2. Motif 8 beats [^3@0, ^4@1, ^5@2, ^1@3, ^6@5, ^5@6, ^1@7] ``` The two segments are identical right up to the last note: segment 1 ends on degree `5` (`^5@7`, the half-close question), segment 2 ends on degree `1` (`^1@7`, the answer home). That single-note difference, repeated across two restated bars, is the entire gesture — and it reads straight out of the printout. ```{tip} **`period()` takes a Phrase, not only a Motif — and keeps its segmentation.** Pass a multi-segment antecedent (say, a `sentence(...)` or an `a + b` phrase) and only the *last segment's* tail re-aims; every interior seam is preserved through both halves. That is how you build a sixteen-bar period out of an eight-bar sentence: `period(sentence(idea, bars=8, seed=3))`. ``` ```{admonition} Reference :class: seealso {py:func}`~subsequence.motifs.sentence`, {py:func}`~subsequence.motifs.period` ``` (sec-develop)= ## 9.3 Development plans: `Phrase.develop` `sentence` and `period` are two named shapes; **`Phrase.develop(...)`** is the general engine underneath them. You hand it a motif, a phrase length in bars, and a *plan* — and it grows the motif into a phrase by that plan. There are two ways to write the plan, and they follow the standard-form rule you have seen throughout the guide: **a sequence of things is a Python list.** ### A plan as a list of unit labels The literal form is a list of **unit labels**, one per segment. The first label is the motif you gave; each *new* label is a generated contrast unit (the source's rhythm, freshly re-pitched); a *repeated* label restates whatever that label already named. So `["a", "a", "a", "b"]` is "state it three times, then contrast" — the classic AAAB drive into a new fourth bar: ```{testcode} ch9 idea = motif([5, 6, 5, 3, None, 1, 2, 3]) aaab = Phrase.develop(idea, bars=8, plan=["a", "a", "a", "b"], seed=11) print(aaab.describe()) ``` ```{testoutput} ch9 Phrase 32 beats, 4 segments 1. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 2. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 3. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 4. Motif 8 beats [^7@0, ^6@1, ^5@2, ^1@3, ^1@5, ^2@6, ^5@7] ``` The first three segments are the idea verbatim (the three `"a"` labels), and the fourth — the single `"b"` — is a contrast unit that kept the rhythm but moved several pitches. Because labels are just names, you control the *form*: `["a", "b", "a", "b"]` alternates, `["a", "a", "b", "a"]` puts the contrast third, and `["a"] * 3 + ["b"]` is the same AAAB written with Python list arithmetic. The `bars=` spreads evenly across however many units the plan asks for — eight bars over four units is two bars each. ```{important} **A plan is a list, because a letter-string is a sequence of labels.** Write `plan=["a", "a", "a", "b"]`, never `plan="aaab"`. A bare string means something else entirely (a *recipe name*, below), and Subsequence will reject an ambiguous letter-string loudly rather than guess — `plan="aaab"` raises a `ValueError` that points you to the list form. This is the same "a sequence is a list" standard form that made a rhythm `[0, 4, 8, 12]` back in [§1.4](01-step-grid) and a progression `[1, 6, 4, 5]` in [§7.1](07-progressions). ``` ### A plan as a recipe name When a plan's logic is richer than "restate or contrast", it gets a *name* instead — a bare string naming a curated recipe. The built-in one is `"call_response"`: call, answer (the call with its tail re-aimed home), call again, then a varied answer. ```{testcode} ch9 lead = Phrase.develop(idea, bars=8, plan="call_response", seed=11) print(lead.describe()) ``` ```{testoutput} ch9 Phrase 32 beats, 4 segments 1. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 2. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^1@7] 3. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 4. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^2@7] ``` Segments 1 and 3 are the call; segment 2 is the answer (its tail re-aimed to `^1`, home); segment 4 is the varied answer (`^2` — the answer, nudged). The bare string `"call_response"` is the only thing that distinguishes a recipe name from a label list, which is exactly why a multi-label plan *must* be a list. ```{note} **`develop()` wants a `seed=`.** Any plan that *generates* contrast units (a label list with a new label, or a recipe) makes random pitch choices, so a phrase built without a seed is a fresh walk every time the file reloads — which breaks live coding. Pass `seed=` (any number) and the phrase is the same value on every run, the repeatability habit from [§4.6](04-generators-euclidean). Without one, `develop()` warns. `period()` is the exception: it generates nothing, so it needs no seed. ``` ```{note} **Under the hood: `sentence` and `period` are `develop` with the close baked in.** A `sentence(...)` is a four-unit development (idea, idea, continuation, cadential) whose last unit's tail is re-aimed to the cadence degree; a `period(...)` is a two-unit plan whose two tails differ at the close. Both record their *recipe* — the source motif, the plan, the seed — inside the phrase, which is what makes the selective reroll of [§9.5](#sec-selective) possible. Hand-written phrases and transformed ones carry no recipe, because their notes no longer came from a generator; there would be nothing honest to regenerate from. ``` ```{admonition} Reference :class: seealso {py:meth}`~subsequence.motifs.Phrase.develop` ``` (sec-placing-phrase)= ## 9.4 Placing a phrase: `p.phrase`, `align` A phrase, like every value in this Part, makes no sound until something *places* it. In a pattern you place a single motif with `p.motif(...)` (from [§8.5](08-motifs)); you place a phrase with **`p.phrase(value, ...)`** — and it does one clever thing automatically: it plays only *this cycle's window* of the phrase, advancing through it cycle by cycle. Here is the running arrangement carried forward — the GM drum loop and a chord-following bass from Part IV — joined by an eight-bar lead phrase placed on a two-bar pattern. The harmony is a progression bound to the engine, exactly as in [§7.6](07-progressions): ```{testcode} ch9 import subsequence from subsequence import progression, motif, sentence import subsequence.constants.instruments.gm_drums as gm_drums import subsequence.constants.midi_notes as notes composition = subsequence.Composition(bpm=120, key="A", scale="minor") composition.harmony(progression=progression([1, 6, 4, 5])) idea = motif([5, 6, 5, 3, None, 1, 2, 3]) lead_line = sentence(idea, bars=8, cadence="open", seed=11) # an 8-bar phrase, stored once @composition.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP) def drums(p): p.hit_steps("kick_1", [0, 4, 8, 12], velocity=100) p.hit_steps("snare_1", [4, 12], velocity=95) p.hit_steps("hi_hat_closed", range(16), velocity=70) @composition.pattern(channel=6, beats=4) def bass(p, chord): p.note(chord.bass_note(notes.A2), beat=0, duration=3.5, velocity=90) @composition.pattern(channel=4, bars=2) def lead(p): p.phrase(lead_line, root=notes.A4) # this cycle's 2-bar window of the 8-bar phrase composition.render(bars=8, filename="phrase-lead.mid") ``` The lead pattern is **two bars** long but the phrase is **eight**. `p.phrase` handles the mismatch by *windowing*: cycle 0 plays bars 1–2 of the phrase, cycle 1 plays bars 3–4, and so on, looping back to the start after bar 8. You do not track position yourself — it is computed fresh each cycle from the engine's own counters, so it is correct under live reload, render, and jumps, with no stored state. A pattern shorter than its phrase simply *walks through* it. The arguments mirror `p.motif` so the two read as one verb: ```{list-table} :header-rows: 1 :widths: 22 78 * - Argument - What it does * - `value` - The Phrase to place (a Motif works too — it places its window directly). * - `root=` - The register anchor for scale-degree resolution: the tonic lands at its nearest instance to this MIDI note, and the melody keeps its written contour from there. `notes.A4` puts the lead up in a singable register. * - `fit=` - The chord-tones-on-strong-beats dial, `0.0`–`1.0` (from [§8.5](08-motifs)): resolved degrees landing on strong beats snap to the nearest chord tone with this probability. Defaults to the phrase's own fit. * - `align=` - How position is counted: `"pattern"` (the default) counts pattern cycles; `"section"` counts bars within the current form section. * - `offset=` - Beats added to the computed position — a phase shift into the phrase. ``` ```{note} **`fit` and "the same notes sound different under different chords."** Your `idea` is written as scale degrees, and degrees resolve late against the key — and, with `fit` active, against the *chord* under each strong beat, exactly the specification-resolved-late idea from [§5.5](05-pitch-and-scales) and [§6.5](06-harmony-context). By default a *hand-written* phrase has no fit (typed degrees are sacred — they play as written), so the lead above floats over the chords on the key's scale tones. Pass `fit=1.0` to `p.phrase` and every strong-beat degree snaps to a chord tone, locking the melody to the harmony; somewhere in between blends the two. It is one dial between "the tune I wrote" and "the tune the chords want." ``` The other `align` mode points forward. With `align="pattern"` the phrase advances by *pattern cycle*, which is what you want for a lead that simply loops. With `align="section"` the phrase position is read from the bar *within the current form section*, so the phrase restarts when the section does — the natural choice once a track has verses and choruses. Forms and sections are [Chapter 10](10-form-sections); `align="section"` is mentioned here only so you know the seam exists. ```{important} **One stored phrase, placed live — the value/canvas split holds.** `lead_line` is built *once* at module level: it is an immutable value, frozen the moment `sentence(...)` returns. The pattern function `lead` is the per-cycle *canvas* (the rebuild loop from [Chapter 2](02-rebuild-loop)), and `p.phrase` reads a window of the stored value into it each cycle. You never mutate `lead_line`; you *place* it. This is the same discipline as a Progression or a Motif — material is a value you keep, `p` is the bar you fill from it. ``` ```{admonition} Reference :class: seealso {py:meth}`~subsequence.pattern_builder.PatternBuilder.phrase` ``` (sec-selective)= ## 9.5 Selective regeneration: reroll/replace while keeping the rest Here is the payoff of segmentation. You have an eight-bar phrase you mostly like, but bar 7 is not landing. You do **not** want to regenerate the whole thing and lose the seven bars that work. A Phrase lets you regenerate *one region* and keep the rest — the surgical edit that makes generate-then-tweak a real workflow rather than a slot machine. ### `reroll` — regenerate a region from the recipe **`.reroll(bar=...)`** (or the plural `bars=[...]`) regenerates only the named bars, keeping their rhythm and their *boundary* pitches. Within each rerolled bar the first and last pitched notes stay put (they pin the bar to its neighbours) and only the interior pitches re-roll, drawing fresh choices from the phrase's recipe. Take the open-cadence sentence from §9.2 and reroll just bar 7: ```{testcode} ch9 lead_line = sentence(idea, bars=8, cadence="open", seed=11) fixed = lead_line.reroll(bar=7, seed=4) print(fixed.describe()) ``` ```{testoutput} ch9 Phrase 32 beats, 4 segments 1. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 2. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 3. Motif 8 beats [^6@0, ^6@1, ^5@2, ^5@3, ^1@5, ^2@6, ^5@7] 4. Motif 8 beats [^6@0, ^8@1, ^5@2, ^5@3, ^1@5, ^2@6, ^5@7] ``` Compare against the original sentence in §9.2: segments 1–3 are byte-for-byte identical, and in segment 4 (which is bars 7–8) only the *interior* of bar 7 moved — the second note went from `^6` to `^8` while the bar's boundary notes held. Seven bars you liked, untouched; one bar, freshly dealt. Change the `seed=` and you get a different bar 7; the rest never budges. ```{important} **`reroll` needs a recipe — so it works on *generated* phrases, not hand-built ones.** A phrase made by `sentence`, `period`, or `Phrase.develop` carries its recipe (the source motif, plan, and seed), so `reroll` knows what stream to draw fresh pitches from. A phrase you wrote by hand with `+`, or one you *transformed* (transposed, reversed, sliced) after generating, carries no recipe — its notes no longer come from a generator, so there is nothing honest to regenerate. Calling `reroll` on such a phrase raises a `ValueError` telling you to edit segments with `replace()` instead. Reroll regenerates; replace substitutes. ``` ### `replace` — substitute one segment wholesale When you want to *swap a bar for something specific* rather than re-roll it, **`.replace(position, motif)`** substitutes the segment at a 1-based position (musicians count from one) and leaves the rest alone. It is the surgical edit that works on *any* phrase, generated or not: ```{testcode} ch9 contrast = motif([1, 1, 1, 1, None, 7, 6, 5]) # a hand-written replacement bar edited = lead_line.replace(3, contrast) print(edited.describe()) ``` ```{testoutput} ch9 Phrase 32 beats, 4 segments 1. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 2. Motif 8 beats [^5@0, ^6@1, ^5@2, ^3@3, ^1@5, ^2@6, ^3@7] 3. Motif 8 beats [^1@0, ^1@1, ^1@2, ^1@3, ^7@5, ^6@6, ^5@7] 4. Motif 8 beats [^6@0, ^6@1, ^6@2, ^5@3, ^1@5, ^2@6, ^5@7] ``` Segment 3 is now exactly the `contrast` motif; segments 1, 2, and 4 are unchanged. `reroll` and `replace` are the two ends of the editing dial: `reroll` keeps the material and re-rolls its details, `replace` throws a segment out and puts a new one in. ### `flatten` and `reverse` — whole-phrase shapes Two more transforms round out the phrase toolkit, and like every transform in this Part they return a **new** value, leaving the original frozen. **`.flatten()`** erases the seams: it collapses the phrase into a single long Motif. Reach for it when you are done editing and want one figure to hand to `p.motif`, or to stack under another part with `&`: ```{testcode} ch9 flat = lead_line.flatten() print(flat.length, "beats,", "one motif now") ``` ```{testoutput} ch9 32.0 beats, one motif now ``` **`.reverse()`** mirrors the whole timeline — the segments reverse order *and* each one reverses internally, so the last note of the phrase becomes the first. On a Motif it does the same to a single figure: ```{testcode} ch9 retrograde = idea.reverse() print(retrograde.describe()) ``` ```{testoutput} ch9 Motif 8 beats [^3@0, ^2@1, ^1@2, ^3@4, ^5@5, ^6@6, ^5@7] ``` The idea `5 6 5 3 · 1 2 3` came back as its mirror image in time — the *retrograde*, a development device as old as counterpoint, here a one-word transform. ### The round trip, placed Putting the editing tools onto the canvas: build a phrase, reroll the bar that bothers you, and place the edited value. The pattern is unchanged from §9.4 — only the stored value is now the rerolled one: ```{testcode} ch9 import subsequence from subsequence import progression, motif, sentence import subsequence.constants.instruments.gm_drums as gm_drums import subsequence.constants.midi_notes as notes composition = subsequence.Composition(bpm=120, key="A", scale="minor") composition.harmony(progression=progression([1, 6, 4, 5])) idea = motif([5, 6, 5, 3, None, 1, 2, 3]) lead_line = sentence(idea, bars=8, cadence="open", seed=11).reroll(bar=7, seed=4) @composition.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP) def drums(p): p.hit_steps("kick_1", [0, 4, 8, 12], velocity=100) p.hit_steps("hi_hat_closed", range(16), velocity=70) @composition.pattern(channel=4, bars=2) def lead(p): p.phrase(lead_line, root=notes.A4, fit=0.6) # blend the written tune toward the chords composition.render(bars=8, filename="phrase-reroll.mid") ``` That is the full manual-to-generate-and-back loop on a phrase: write a basic idea by hand, grow it with a builder, audition it, reroll or replace the bars that miss, and place the result — keeping every bar you already liked. Each transform handed you a new value; the original `idea` and the unedited `sentence(...)` are still exactly as you wrote them. ```{tip} **`reroll`, `replace`, and `vary` compose, because each returns a phrase.** Chain them — `sentence(idea, bars=8, seed=3).reroll(bar=5, seed=9).replace(4, tag)` — and each step builds on the last, the same fluent style as the progression transforms in [§7.4](07-progressions). When you finally `.flatten()`, you have one motif carrying the whole edit history's result, ready for `p.motif` or a parallel stack. ``` ```{admonition} Reference :class: seealso {py:meth}`~subsequence.motifs.Phrase.reroll`, {py:meth}`~subsequence.motifs.Phrase.replace`, {py:meth}`~subsequence.motifs.Phrase.flatten`, {py:meth}`~subsequence.motifs.Phrase.reverse` ``` --- You can now grow a single motif into a multi-bar phrase — by the classical sentence and period, or a development plan of your own — inspect it with `print`, place its per-cycle window with `p.phrase`, and regenerate a bar or two while keeping the rest, all on immutable values you store once and never mutate. So far a phrase loops on its own pattern. Next we give the track a *shape*: in [Chapter 10](10-form-sections) we build forms and sections, set energy as the arranging dial, and bind harmony, motifs, and phrases to named sections so a verse and a chorus can carry different material.