Repository navigation
Conversation
jcelerier
force-pushed
the
feature/midi-effects
branch
from
October 28, 2026 03:52
b261d1d to
c368dd6
Compare
The executor requests a tick after stop() for objects with a MIDI output and a stop() member, so they can send the note-offs of what they hold. score_plugin_fx sees avendish's examples for the shared MIDI helpers, which get their own unit test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Bumps avendish for the MIDI objects: Midi transform, CC snapshot, value shaper, sustain, delay, dispatcher and MPE are registered; Midi filter, Humanize, scaler and MIDI Sync In gain the features of the batch. MIDI Sync Out gets a free-running clock with its own BPM and transport, tap tempo, nudge, a clock rate and a clock offset; following score's timeline is unchanged at the defaults. The time-dependent logic lives in MIDIClockEngine.hpp so it can be tested with an injected clock. It ignores the frameless tick that follows stop(), which would overwrite the song position stop() resets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Chord: the 37 chord types of free-midi-chords after the six existing ones (unchanged), harmonizer intervals, per-voice chance and velocity, strum, chord memory and an MPE mode. Midi scale: a per-degree remap mode and a direction for out-of-scale notes. Arpeggiator: new patterns, gate, swing, accents, velocity decay, retrigger, latch, pressure to velocity (note repeat), seed; non-note messages pass through. Midi quantify: gate, trigger on note-off, decay, release velocity. LFO: one shot. Every object releases what it holds on CC 120 / 123 and on stop, and the existing controls keep their behaviour at the new controls' defaults. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
One test per new or extended MIDI object: the features, every note-on paired with one note-off under random input and control changes, CC 120 / 123, pass-through order, timestamps inside the tick, stop, and seeded reproducibility; pinned outputs check that existing objects keep their behaviour at the defaults. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- An enum with more than 8 values and no icons is drawn as a drop-down in process views instead of a grid of buttons. - Text fields in process views draw their background, so an empty one can be seen and clicked. - In the inspector, a control drawn through a graphics view (time choosers) is as tall as its item instead of taking the remaining height, and text fields are no longer capped at 70 pixels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Range sliders in process views draw their two values, each in a color that reads on the range or on the background. Combo boxes leave 8 pixels on each side of their longest entry so it does not touch the marker or the stepper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- Grouped layouts for Chord, Midi scale, Arpeggiator and Midi quantify, with
controls greyed when they do not apply; clearer labels ("Voice chance",
"Voice velocity", "Strum direction", "Latch hold"), descriptions for the
Midi scale degrees.
- Midi scale: a custom mask starts on Base like the built-in scales, and a
scale text that is not a mask (picking "custom" in the list) keeps every
note instead of dropping them all.
- Arpeggiator: the Up/Down, Down/Up, Converge, Diverge, Low Up and High Up
patterns run across all the octaves instead of repeating inside each one;
the most recent kind of pressure sets the velocity.
- Midi quantify: a note on a grid point plays on it instead of waiting a
step (the frame to musical time conversion is not exact).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
MTC rate code 2 is 29.97 fps and 3 is 30 fps: the codes sent were right but the timing used the other rate. Layout in Send / Clock / Free clock sections, the free clock greyed unless the source is Free. avendish: MIDI object layouts, Midi filter note-off routing, dispatcher voice taking, Midi scaler input bend range, MIDI Sync In fixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
MidiPresetHarness loads a package's .scp presets and applies them to an object's inputs the way the avnd process maps them (entry N is input N; synced times converted to seconds as the ossia binding does). One test per object checks that every preset applies cleanly and does what its name says, with notes paired and timestamps inside the tick. Dispatcher and filter tests follow the new voice-taking and note-off routing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Registers Midi random sequencer (Turing Machine / Marbles style), Midi progression player (with the free-midi-chords progressions) and Midi life (a Game of Life sequencer), with their unit tests and the tests of their presets in the default package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A list control edits rows of the existing spinboxes and combo boxes: + appends a copy of the last row, x or - removes one, the context menu inserts, duplicates, moves and clears, and the whole list can be edited as text. The note matrix maps 12 input degrees to output degrees, with muted degrees; the channel mask toggles the 16 MIDI channels. They bind to halp::value_list, halp::note_matrix and halp::channel_mask. A control that changes size lays out again the sections around it, and the inspector view follows a list's size. Integer range spinboxes show integers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Chord's intervals, voice chances and voice velocities are number lists and its MPE channels a channel mask. Midi scale's twelve remap offsets become a note matrix in the way of Ableton's Scale, with muted degrees, Fold, and a Lowest / Range band outside which notes pass unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Sequencers (piano roll, pattern sequencer, Patternal, Melodial, file reader and scroller), Generators, Pitch, Timing, Routing, Control (CC tools and MIDI to and from values) and Sync (MIDI clock and MTC, from Timing/Midi). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A preset naming an entry ("Toggle") of a combo box whose entries have
values reached the engine, which maps labels, but the widget matched values
only and showed the first entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…st tick The edition and GC queues' try_enqueue called enqueue, which can allocate: they use the real try_ versions and fail when full. Messages too large for a command go through a fixed ring per node; controller updates from the audio thread go through a lock-free latest-value buffer. An interval usually ends inside a buffer, and its last partial tick runs after the process is stopped. Objects that release their notes on stop get their stop() at the start of the extra empty tick, so the notes that last tick starts also end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
… loops With a bound device, the clock and MTC threads and the graph both wrote to it. The audio thread now computes every message once and the clock thread sends them at absolute times, without drift. A loop or seek is a jump: Stop, Start or Song Position and Continue, clock phase realigned, a full MTC frame. A positive clock offset delays the transport messages with the clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A value arriving between a row removal and its deferred rebuild read rows past the end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- Chord: voice chance and velocity lists in 0-1 and 0-4; chord names that were digits renamed (an int selected the wrong entry); Learn no longer allocates on the audio thread. - Midi scale: the page follows Mode; the scale is kept as notes, no string copy on the audio thread. - Arpeggiator: the engine builds arpeggios without allocating; gate, swing and velocity decay are 0-1 knobs; compact layout. - Quantify: gate and decay knobs. - LFO: One shot plays again when its process starts again. - halp_flag(process_exec) on Chord, Arpeggiator v2, Quantify v2 and LFO v3, whose start() / stop() the host only calls with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
… through MIDI 2 avendish: compact layouts, 0-1 proportions, process_exec, review fixes, MIDI Sync In full frames. libossia: libremidi keeps a pitch bend's center through MIDI 2 (it was scaled as 16 bits). Tests for each fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
The audio Looper keeps its uuid and controls; its transport moves to a core shared with a new MIDI looper. Passes are layers of their own with undo, redo, clear and feedback; buffers are reserved before playback. A take is written as a looping WAV or a MIDI file when a recording or overdub ends, and goes to the timeline by Send to timeline or by dragging it from the looper's view. Custom items can start drags and place clips in the timeline, and every view of a process gets the processor's messages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Loopers of one sync group share a loop: the first to record leads, the others round their length to a multiple or a fraction of it and go round in phase. Capture turns the last bars heard into the loop without having recorded them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…asked Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
The audio looper loads a dropped sound file as its loop, and goes round with nothing patched in. Undo gives the passes under an overdub the gains feedback took from them, and later laps of an overdub fade its own earlier ones. Sync groups start their loop where it restarted, also after a late stop. MIDI notes held past the loop and notes replaced while sounding end; take paths, dates and names are kept per take. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
… tempo A take can be written as the loop's mix, each pass in a file of its own, or both; sending or dragging it places every file on a lane of its own. Overdubbing an empty loop records it. A loop keeps the tempo it was recorded at for its quantize grid and its takes. Quantizing note ends no longer shortens a note to nothing. Rate limiters are reset when their process stops. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Past the end: an overdub goes round the loop (Wrap) or makes it longer by the loop's length each time it reaches the end, the passes under it repeating (Extend); undo gives the loop its length back. The MIDI looper plays its loop at the score's tempo when Follow tempo is on, the default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
QGraphicsGridChooser keeps the time chooser's knob and readout; a click on the readout picks the unit (free time, note value, bars, the object's period) and the feel. Process::GridChooser saves its configuration with the port. The note table moves to NoteValues.hpp, shared by both widgets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
near is a macro in the Windows headers. A readout wider than the chip
("1/2 loop", "16 bars") is drawn smaller and narrowed instead of cut.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Quantif takes free time, a note value, bars or the loop (1/4, 1/2, 1, 2x...). On an empty loop, Loop waits for Bars bars, or one bar when Bars is 0. Note values are whole-note fractions in every signature. Old scores and presets convert: None stays none, Whole becomes 1 bar, any other value the same note value. Presets saved when a control was of another kind now go through its upgrade_value, as documents do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…he loop Every change waits for the loop to come round; the first recording, with no loop yet, ends on a bar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A MIDI looper take writes the tempo and time signature it was recorded at. score's timeline counts a quarter as half a second whatever the tempo, so a dropped MIDI file is placed by its quarters, not by its file tempo: two bars stay two bars. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- Sync groups are removed, with their presets. - Record on a loop that holds something overdubs it; Clear starts anew. - Stopping the score while recording or overdubbing leaves Mode on Play, so playing again no longer records over the loop. - Loop is Mode, Quantif is Quantize, Bars is Record bars. On the MIDI looper, Grid is Note grid (note values, no None), its Quantize is Strength and Quantize ends is Note ends. Follow tempo has readable labels. - Old scores and presets load with the new names; a score from master gets the grid its Quantif waited for, not seconds. - avnd presets name their controls, and a rebuilt process keeps its port ids, so presets and cables survive a removed port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
PassStack.hpp holds what a layer is (period, loop before and after, mute), undo, redo, erase, merges, set-aside and unmerge, for any payload; LooperNode.hpp holds the tick, the layer actions, closing and trimming takes, capture and export. Each looper keeps only its medium. Where the two loopers differed, they now agree: - solo is forgotten when a merge completes; - material cut from a recording by its bars is carried into the overdub; - merging with a muted layer keeps it for undo, and two muted layers merge into a muted one that keeps both; - a take written when a pass closes leaves out the pass begun with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A take sent or dragged to the timeline carries its stretch mode, from the Follow tempo the loop played with; Off plays it unstretched at its recorded length. The metadata travels in an application/x-ossia-take mime next to the files, applied by the Sound drop handler for both Send and drag. A plain file drop keeps the mode guessed from its name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
One value inlet and outlet. Impulses fire where they were played and merge; every other value is held until the next, and an overdub takes over from its first new value to its end (latch). Whatever changes the held value -- mute, erase, undo, the end of a pass, a jump -- sends the newly held one. Each value carries a key, 0 for now, for several sources later. Stored values go through one value_slot type. Takes are .values files; a take of numbers or vectors lands as Automation curves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- A paused or stopped looper no longer leaves its view waiting for a take forever, which stopped every drag. - Dragging a lane drags that layer's own file, written on demand when the take has none; the Send button sends on click and drags the whole take. - Lanes share the view's height, up to 32 lanes. - MIDI and value loopers: an overdub becomes a layer on its first event; a pass that records nothing adds no layer, take or merge. - Value looper: takes of numeric lists land as one automation per index. - Tabs: Speed (Speed, Reverse, Follow tempo and their switches); Capture and Capture bars in Length; Keep last in Memory; Switches holds One button and Transport. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…inlet MIDI registration Parameter, node, pattern, empty and non-MIDI addresses, rebinding across devices, two inlets on one device, double registration, a removed device, reset, and devices added and removed within one batch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
… 13.3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…modes - Chord: Memory is a list of rows (C4: 0 4 7), learned without allocating; old text converts. - Midi filter: Types as a toggle grid (QGraphicsToggleGrid, which the channel mask now builds on), Notes and CCs as range rows; old text converts in scores and presets. - Midi transform and Midi value shaper: Value outputs. Midi Glide modes. Midi sustain's Pedal is a momentary button. - Midi CC snapshot removed; a score holding one still loads. - Control values larger than the execution queue's inline size travel through the heap path built on the UI thread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
VST2 gets VstMidiSysexEvent, VST3 a kMidiSysEx data event, CLAP CLAP_EVENT_MIDI_SYSEX, LV2 one MIDI 1 event per message; the bytes live in storage made beforehand for each node. MIDI 1 devices join the packets (libremidi), JS scripts send and receive sysex as one message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
On an empty loop Capture still makes the loop of the last Capture bars. Over a loop it now adds what was played during the last round as a new layer, kept with the other layers' mutes, and Undo takes it out like any pass. MIDI tests also cover Replace across three layers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A take dragged from a looper went through the plain MIDI file drop: dropped on an existing box, e.g. the looper's own, it took the box's length and did not loop, which made a four bar loop an eight bar piano roll. Takes now carry loop=1 in their clip metadata, from the view's drags and from Send, and the MIDI, value and sound drops set the clip to loop at the take's length, in the same undo step. A .mid from a file browser is unchanged. libossia: a tick split at a date keeps its musical positions, so a looper in a box that does not start at 0 records the right number of quarters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- Replace as you play: Passes Per cycle, so each round played over replaces the one before; it overdubbed one pass across rounds, and a pass never replaces itself. - One footswitch, song form stops at the loop's end, as Song form. - Comping, a layer per press exports the mix and each layer, as per round. - MIDI Four bar phrase and Free phrase are Four bars, then play and Free loop, as for audio. - Capture what I played (MIDI) and Capture what moved (values) are gone: they set nothing Capture needs. The audio one stays, for Keep last. - Channels is no longer set by audio presets: it is the input's. - Quantize and Note grid are stored in the grid chooser's format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…ized A node lays its layer out over its width, at the zoom of what it shows: a loop when the process loops. updateSize, which a rename runs, set the width alone, which makes the layer draw the whole process over the node. A take dropped in the nodal view, named after the take once its loop was set, showed its four bars squeezed into the first half of a box of eight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
After a stop no node is left to write the files a drag or Send asks for, and Send placed the last take as written, whatever Export said since. Now: - the score's stop leaves a take with the mix and every layer, unless the last one is already whole: the audio thread hands a preallocated snapshot to the worker, which writes the files and tells the views through a host sender that reaches them once the node is gone; - Export only chooses what Send and the grip place, read from the control on the UI side (a custom item's watched() controls), so it holds while stopped and when changed after the take was written; - a deferred stop that never got its tick runs as the node is destroyed, and a worker job marked must_run runs once its object is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…rk merged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
jcelerier
force-pushed
the
feature/midi-effects
branch
from
October 28, 2026 20:41
a8171ce to
5061ebb
Compare
The painter gives the width of a text, so that a custom item can right-align one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
A pass per cycle is cut on the loop's start while what is played goes on: both ends were faded as a punch is, a 128-frame dip to silence on every seam, heard at each new pass and on every round after. Each pass now keeps where its ends meet the passes before and after it, and an end is faded only while the pass on the other side is not heard (muted, soloed out, undone, erased, cleared, merged away); the recording's end into its overdub is the first of these seams. Also at a cut, or on every round: - Feedback glides the gains of the passes under the overdub instead of stepping them, which made each seam jump by 1/feedback once played. - An overdub pass is written already moved by the latency, instead of moved when it closes, which left the last positions of each round silent. - Below x1, the overdub no longer hears back what it just wrote. - A pass begun after a merge into the newest layer gets a buffer of its own. - A pass that went round over its start fades what it last wrote at its end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MIDI effects, loopers and MIDI sync.
Depends on
Merge these first, then bump the submodules here to their merged commits:
What it adds
Behaviour changes from master
New ports are appended; uuids, port order and saved enum values of existing objects are unchanged.
Release notes (for ossia-score.appdata.xml)
New features
Improvements
Tests
Full build; 105 targeted test programs pass (avnd, fx, looper, preset loader with 263 preset fixtures in tests/fixtures/presets, midi, execution, graphics, protocol, nodes). UI checked in the running app (screenshots of the loopers, take boxes, MIDI layers).
🤖 Generated with Claude Code
https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr