Guide
PHALAR stem pairing
Find stems against the audible mix in Zen mode, or rank candidates against an anchor recording, then accept a fixed ordinary stem or part.
PHALAR ranks candidates from your eligible sample library by learned musical compatibility. You can query the audible mix while composing in Zen, or use one catalog recording as an anchor. A mix request encodes the captured audio on a background worker, off the render and scheduler path, and can do so while music plays; anchor rankings and pattern event queries never run model inference.
Write an ordinary stem inside stem-stack, leaving the new stack unevaluated:
(d1! (stem-stack
(>> (stem :type :drums
:n 0
:match :tempo)
(orbit 0))
(>> (stem :type :bass
:n 0
:match t)
(orbit 1))))Keep the existing drum form unchanged and place the cursor on the bass :n number.
| Action | Shortcut | Effect |
|---|---|---|
| Request fits | Shift+Return | Capture four seconds of the existing analysis input, then rank eligible bass sources. |
| Next / previous rank | Ctrl+Shift+N / Ctrl+Shift+P | Move the inline selection silently. |
| Accept | Option+Shift+Return | Write the chosen fixed coordinates into the code: :n, and also :v in family mode. Nothing is played or evaluated. |
| Play the edit | Cmd+Return | Evaluate the stack normally; unchanged stem lanes retain playback. |
Shortcuts are shown with macOS modifiers. The rank keys use the Control key and stop at the first and last rank; Ctrl+Return also evaluates the form.
Status and up to five ranked choices appear directly under the focused stem, including in Zen. Rank zero is the best-scoring candidate. The list includes source names, native tempo/key and relative scores. A literal :filter, such as :filter '(:synth), restricts the candidates using the same rules as stem. The cursor must be inside a stem or part call with a literal type keyword, a literal :filter if it has one, and no :library override. A new request replaces the previous inline list.
Acceptance checks the chosen recording again before writing: its exact coordinates and physical recording must still be current, and member 0 is never substituted for it. The edit is one undo step. Inside an :n mini-notation string only the number under the cursor changes, and a stem without :n receives one. An existing :v progression is refused rather than overwritten.
Capture waits for an existing stem crossfade to settle. Changing the playing mix (channel patterns or mute state), key, tempo, source pool or target source form invalidates an outstanding ranking; request again rather than accepting a stale variant. Unrelated edits elsewhere do not invalidate the target. Refusals appear as nonmodal notices beginning with PHALAR:.
The query hears the whole configured analysis input, including other audio in that return. It does not analyze an unevaluated draft, average the embeddings of the playing sources, or subtract a lane being replaced. The existing input must already be running and receiving the mix, and a silent input is not a usable query; requesting fits never starts a device, changes routing, starts an audition or downloads a model.
Recordings that the installed patterns already select, and byte-identical copies of them, are left out of the candidates; in family mode an installed selection excludes its whole family. A selector that cannot be resolved to fixed recordings is not guessed at: the request status reports its exclusion coverage as incomplete.
The same operation is available for code-built compositions. Evaluate one form at a time: install a retained drum lane, request bass candidates against the audible mix, then accept a rank once the request is ready.
(defparameter *drums*
(>> (stem :type :drums
:n 0
:match :tempo)
(orbit 0)))
(d1! (stem-stack *drums*))
(suggest-stems :bass
:seconds 4
:limit 8)
;; Once (stem-suggestion-status) reports :ready, accept once
;; and retain the complete routed lane.
(defparameter *bass*
(>> (suggested-stem 0
:match t)
(orbit 1)))
(d1! (stem-stack *drums* *bass*))The second stem-stack reuses the same *drums* object, so the drum lane keeps playing; only the bass lane is new.
suggested-stem returns a normal fixed-choice stem, not a live recommendation player. In family mode it carries both :n and :v. Because it always returns a stem, it is the clear way to add a stem-stack lane. :request selects an explicit request instead of the latest one; :match has the ordinary stem meaning and defaults to nil. Pending, failed, cancelled and stale requests are errors rather than old choices, and the ranked source is checked again before the stem is built.
suggest-stems returns a request at once; a bounded background worker then captures a contiguous window of the analysis input, encodes it and ranks the cached candidate recordings. :seconds sets the capture length (default 4, from 2 to 16) and :limit the number of results (default 32, from 1 to 256). :filter restricts candidate tags, and :exclude adds source ID strings to leave out. The embeddings must already be prepared, and the call cannot be made from inside a playing pattern. Unlike the inline workflow, a request from Lisp does not wait for a crossfade to settle.
Inspect a request with stem-suggestion-status, read its candidates with stem-suggestions (which returns them only once the request is ready), and cancel it with cancel-stem-suggestions, which never stops a playing pattern or the analysis input. There is one current request, shared by the inline editor, the Samples pane and the REPL; a new request cancels the older one. The keyboard workflow above provides the source-anchored inline display and literal acceptance.
Learned search finds similar audio or matches a text description. PHALAR addresses a different question: compatibility between recordings.
Mora implements local source embeddings and a compatibility ranker with the public PHALAR model. The ranking uses the model’s learned complex-valued pairing score rather than generic cosine similarity.
The workflow is explicit and cached:
;; The first call explicitly authorizes model installation.
(embed-stems :install-model t)
;; Resume/reuse an existing installation and unchanged source cache.
(embed-stems)
(stem-embedding-status)
(load-stem-embeddings)In the first call, :install-model t explicitly authorizes model installation. Later calls resume or reuse an existing installation and an unchanged source cache.
- Off the performance path. Embedding runs outside the scheduler and render loop; the feature prepares embeddings in the background. Pairing does not perform model inference during event queries.
- Tracked identity. Per-source status, together with source, model, and preprocessing identity, prevents a failed or stale embedding from being treated as a successful one.
- Local audio. The source audio remains local in this workflow. It does not require uploading a sample collection to a hosted service.
pairings ranks candidates within the current eligible source pools by learned compatibility with one anchor, keeping ordinary library eligibility and variant numbering:
(pairings :melody 0
:with :bass
:filter '(:synth)
:limit 8)The eligible pools are the ones published by loops; see Stems and sample libraries. :limit accepts 1 to 256 and defaults to 8. :filter restricts the candidates’ tags, and :anchor-filter applies when the anchor’s own number comes from a filtered pool.
When loops uses :group :family, the anchor number selects a family and :v selects its exact recording, defaulting to 0. Flat mode accepts only :v 0 and keeps its original numbering.
(pairings :melody 0
:v 1
:with :bass
:limit 8)paired constructs ordinary playback from one result: a part in flat mode, or a stem carrying :n and :v in family mode. Its roles are the reverse of pairings: the first argument is the candidate type, and :with names the anchor as a type and number.
(paired :bass
:with '(:melody 0)
:rank 0
:match t):rank is zero-based (0 to 255, default 0), and :anchor-v selects the anchor’s recording in family mode (default 0). :filter and :anchor-filter have the same meaning as in pairings. When no analyzed eligible candidate exists at that rank, paired signals an error; it never falls back to another kind of similarity. The example also requests :match t; matching and its optional live-stretch requirement are described in Tempo and key matching.
A flat-mode result is a part, which cannot be a stem-stack lane. For a lane, write a literal stem with the result’s coordinates, or use suggested-stem with a mix request.
pairing-info describes one pairing result from pairings or stem-suggestions, not the constructed part or stem:
(pairing-info (first (pairings :melody 0
:with :bass)))It reports :group, :n, :v, :family-id, :family-label, :source-id and :source-label, together with the score, tags, :tempo-reading (the half, normal or double-time reading toward the current tempo) and :target-native-bpm.
Both the anchor and the mix paths return a family-diverse shortlist: PHALAR scores every eligible recording, keeps the best-scoring eligible member of each family, and only then applies the limit, so alternate recordings of one idea do not fill the list. This also happens in flat mode, without changing flat numbers. It does not claim that every family sounds different, and the anchor path does not exclude the anchor’s family: when :with names the anchor’s own type, the best-scoring other member of that family can still appear.
Scores are model logits, not calibrated probabilities that two sounds will work together.
The candidate embeddings describe the original recordings. They are not re-encoded from the stretched, transposed, sliced, or effects-processed audio of a performance. Only the query side of a mix request is measured: the captured mix is encoded as it actually sounded.
The PHALAR source and checkpoint carry their own MIT notices, and the official PHALAR repository identifies MIT. This license is separate from those of MuQ and MuQ-MuLan and from your samples. See Licensing and assets.
Source references
Repository-relative paths in the Mora source where these mechanisms are implemented.
-
src/mini/stem-embeddings.lisp -
src/mini/stem-context.lisp -
src/analysis/mixture-context.lisp -
src/samples-studio/stem-suggestions.lisp -
src/studio/stem-suggestions-inline.lisp -
scripts/audio-analysis/mora_phalar.py -
src/mini/loop-library.lisp -
src/mini/stem.lisp