Docs file normalization.
This commit is contained in:
parent
dd32143bf8
commit
619c2d0808
46 changed files with 3587 additions and 2579 deletions
399
docs/IDEA.md
399
docs/IDEA.md
|
|
@ -1,48 +1,78 @@
|
|||
# Project Brief: A Modern, Lightweight, energyXT-Inspired DAW
|
||||
|
||||
**Document purpose:** This file is the authoritative project brief and implementation guide for an AI coding agent working inside an IDE.
|
||||
**Document purpose:** This file is the authoritative project brief and
|
||||
implementation guide for an AI coding agent working inside an IDE.
|
||||
|
||||
**Working project name:** `xtc` (temporary; keep the project name configurable and do not hard-code it into public APIs).
|
||||
**Working project name:** `xtc` (temporary; keep the project name configurable
|
||||
and do not hard-code it into public APIs).
|
||||
|
||||
**Primary goal:** Build a modern, reliable, lightweight digital audio workstation inspired by the workflow and modular philosophy of energyXT. This is a new implementation, not a clone of energyXT's proprietary code or assets.
|
||||
**Primary goal:** Build a modern, reliable, lightweight digital audio
|
||||
workstation inspired by the workflow and modular philosophy of energyXT. This is
|
||||
a new implementation, not a clone of energyXT's proprietary code or assets.
|
||||
|
||||
**Architecture decision:** **B — Modular engine first.** The sequencer, instruments, effects, mixers, audio inputs, and outputs are components in one unified processing graph. The default user experience should still be a simple sequencer-first workspace; users can open the modular view when they need to inspect or edit signal flow.
|
||||
**Architecture decision:** **B — Modular engine first.** The sequencer,
|
||||
instruments, effects, mixers, audio inputs, and outputs are components in one
|
||||
unified processing graph. The default user experience should still be a simple
|
||||
sequencer-first workspace; users can open the modular view when they need to
|
||||
inspect or edit signal flow.
|
||||
|
||||
**Language decision:**
|
||||
|
||||
- **100% C for the audio engine and core domain logic.**
|
||||
- **FLTK with C++ for the graphical user interface only.**
|
||||
- The GUI talks to the core through a small, documented C API.
|
||||
- Do not introduce C++ into the audio engine or core library.
|
||||
- Keep dependencies small, prefer open-source components, and avoid unnecessary frameworks.
|
||||
- Keep dependencies small, prefer open-source components, and avoid unnecessary
|
||||
frameworks.
|
||||
|
||||
---
|
||||
|
||||
## 1. Instructions to the AI coding agent
|
||||
## 1. Instructions to the AI Coding Agent
|
||||
|
||||
Treat this document as the project contract. Follow it in every implementation task.
|
||||
Treat this document as the project contract. Follow it in every implementation
|
||||
task.
|
||||
|
||||
1. Read this file and the existing project before making changes.
|
||||
2. Inspect the current build system, source tree, and tests. Do not assume the repository is empty.
|
||||
3. Implement work in small, buildable increments. Each increment must compile and have relevant tests before proceeding.
|
||||
4. Prefer complete, coherent file updates over partial snippets. Do not silently remove existing functionality.
|
||||
5. Before editing, state briefly what you intend to change and which files are affected. Then make the changes.
|
||||
6. Do not invent APIs, FLTK features, audio backend capabilities, or dependency behavior. Check installed headers and official documentation when uncertain.
|
||||
7. Keep C source compatible with **C99** initially. Use C11 features only when explicitly justified and supported by the selected compiler/toolchain.
|
||||
8. Use C snake_case identifiers. Use clear names; avoid cryptic one-letter names except conventional loop counters.
|
||||
9. Validate external input, lengths, indexes, counts, enum values, and allocation sizes. Handle errors explicitly.
|
||||
10. Do not hide failures, silently clamp invalid data, or continue with partially initialized objects.
|
||||
11. Avoid unnecessary dependencies, generated-code systems, global mutable state, and elaborate abstractions.
|
||||
12. Never perform audio-thread-unsafe operations from the real-time callback. See the real-time rules below.
|
||||
13. Keep the project usable on Linux first. Do not make Linux-specific details leak into the public core API.
|
||||
2. Inspect the current build system, source tree, and tests. Do not assume the
|
||||
repository is empty.
|
||||
3. Implement work in small, buildable increments. Each increment must compile
|
||||
and have relevant tests before proceeding.
|
||||
4. Prefer complete, coherent file updates over partial snippets. Do not silently
|
||||
remove existing functionality.
|
||||
5. Before editing, state briefly what you intend to change and which files are
|
||||
affected. Then make the changes.
|
||||
6. Do not invent APIs, FLTK features, audio backend capabilities, or dependency
|
||||
behavior. Check installed headers and official documentation when uncertain.
|
||||
7. Keep C source compatible with **C99** initially. Use C11 features only when
|
||||
explicitly justified and supported by the selected compiler/toolchain.
|
||||
8. Use C snake_case identifiers. Use clear names; avoid cryptic one-letter names
|
||||
except conventional loop counters.
|
||||
9. Validate external input, lengths, indexes, counts, enum values, and
|
||||
allocation sizes. Handle errors explicitly.
|
||||
10. Do not hide failures, silently clamp invalid data, or continue with
|
||||
partially initialized objects.
|
||||
11. Avoid unnecessary dependencies, generated-code systems, global mutable
|
||||
state, and elaborate abstractions.
|
||||
12. Never perform audio-thread-unsafe operations from the real-time callback.
|
||||
See the real-time rules below.
|
||||
13. Keep the project usable on Linux first. Do not make Linux-specific details
|
||||
leak into the public core API.
|
||||
14. Add or update tests and documentation with each feature.
|
||||
15. At the end of a task, report: files changed, behavior added, build/test commands run, results, known limitations, and the next sensible step.
|
||||
16. If a requirement is ambiguous, choose the smallest safe implementation consistent with this document and explain the assumption. Ask a question only if the ambiguity blocks safe progress.
|
||||
17. Do not claim that a feature works unless it has been implemented and tested. Clearly distinguish a prototype, stub, and finished feature.
|
||||
18. Never copy energyXT source code, proprietary resources, UI artwork, or undocumented internal implementation. Use energyXT only as inspiration for high-level workflow ideas.
|
||||
15. At the end of a task, report: files changed, behavior added, build/test
|
||||
commands run, results, known limitations, and the next sensible step.
|
||||
16. If a requirement is ambiguous, choose the smallest safe implementation
|
||||
consistent with this document and explain the assumption. Ask a question
|
||||
only if the ambiguity blocks safe progress.
|
||||
17. Do not claim that a feature works unless it has been implemented and tested.
|
||||
Clearly distinguish a prototype, stub, and finished feature.
|
||||
18. Never copy energyXT source code, proprietary resources, UI artwork, or
|
||||
undocumented internal implementation. Use energyXT only as inspiration for
|
||||
high-level workflow ideas.
|
||||
|
||||
### Definition of done for every task
|
||||
|
||||
A task is complete only when:
|
||||
|
||||
- the code builds with warnings enabled;
|
||||
- relevant tests pass;
|
||||
- error paths are considered;
|
||||
|
|
@ -53,16 +83,19 @@ A task is complete only when:
|
|||
|
||||
---
|
||||
|
||||
## 2. Product principles
|
||||
## 2. Product Principles
|
||||
|
||||
The application should feel like a small, responsive music instrument rather than a general-purpose content-creation suite.
|
||||
The application should feel like a small, responsive music instrument rather
|
||||
than a general-purpose content-creation suite.
|
||||
|
||||
### Core principles
|
||||
|
||||
- **Simple by default, powerful when opened up.**
|
||||
- A single unified component graph underlies the application.
|
||||
- The sequencer, mixer, instruments, effects, audio I/O, and utility processors use a common node model.
|
||||
- Common operations should require few clicks and avoid modal dialogs when practical.
|
||||
- The sequencer, mixer, instruments, effects, audio I/O, and utility processors
|
||||
use a common node model.
|
||||
- Common operations should require few clicks and avoid modal dialogs when
|
||||
practical.
|
||||
- The modular graph should expose real signal flow, not be a decorative diagram.
|
||||
- The project must remain understandable to a human developer.
|
||||
- Audio reliability is more important than visual effects or feature count.
|
||||
|
|
@ -75,6 +108,7 @@ The application should feel like a small, responsive music instrument rather tha
|
|||
### Explicit non-goals for the first release
|
||||
|
||||
Do not initially implement:
|
||||
|
||||
- video, notation, collaboration, cloud accounts, or online services;
|
||||
- an integrated marketplace;
|
||||
- scripting as a requirement for basic operation;
|
||||
|
|
@ -86,11 +120,12 @@ Do not initially implement:
|
|||
- automatic online update services;
|
||||
- a proprietary project format that cannot be inspected or migrated.
|
||||
|
||||
These may be considered later, but they must not delay the first reliable recording and playback workflow.
|
||||
These may be considered later, but they must not delay the first reliable
|
||||
recording and playback workflow.
|
||||
|
||||
---
|
||||
|
||||
## 3. High-level architecture
|
||||
## 3. High-Level Architecture
|
||||
|
||||
Use distinct layers with narrow interfaces.
|
||||
|
||||
|
|
@ -125,7 +160,9 @@ Use distinct layers with narrow interfaces.
|
|||
+------------------------------------------------------------+
|
||||
```
|
||||
|
||||
The C core and audio engine may be separate libraries or clearly separated modules within one C library. Keep their interfaces explicit even if they initially compile into one library.
|
||||
The C core and audio engine may be separate libraries or clearly separated
|
||||
modules within one C library. Keep their interfaces explicit even if they
|
||||
initially compile into one library.
|
||||
|
||||
### Suggested repository layout
|
||||
|
||||
|
|
@ -179,13 +216,14 @@ xtc/
|
|||
└── build/ # generated; do not commit
|
||||
```
|
||||
|
||||
Keep C and C++ files clearly separated. C headers exposed to C++ must use `extern "C"` guards.
|
||||
Keep C and C++ files clearly separated. C headers exposed to C++ must use
|
||||
`extern "C"` guards.
|
||||
|
||||
---
|
||||
|
||||
## 4. Language and API boundary
|
||||
## 4. Language and API Boundary
|
||||
|
||||
### C code owns
|
||||
### C Code owns
|
||||
|
||||
- project and track data;
|
||||
- graph nodes, ports, and connections;
|
||||
|
|
@ -198,7 +236,7 @@ Keep C and C++ files clearly separated. C headers exposed to C++ must use `exter
|
|||
- backend-independent engine state;
|
||||
- error codes and diagnostic messages.
|
||||
|
||||
### C++/FLTK code owns
|
||||
### C++/FLTK Code owns
|
||||
|
||||
- windows and widgets;
|
||||
- layout and drawing;
|
||||
|
|
@ -211,15 +249,19 @@ Keep C and C++ files clearly separated. C headers exposed to C++ must use `exter
|
|||
### Boundary rules
|
||||
|
||||
- Public C headers must compile from both C and C++.
|
||||
- Do not expose C++ classes, STL containers, exceptions, or FLTK types through the C API.
|
||||
- Do not expose C++ classes, STL containers, exceptions, or FLTK types through
|
||||
the C API.
|
||||
- Prefer opaque handles for objects whose internal layout must remain private.
|
||||
- Use explicit integer error codes and documented output parameters.
|
||||
- Define ownership for every pointer: borrowed, caller-owned, or transferred.
|
||||
- Do not return pointers into mutable engine memory unless their lifetime is guaranteed.
|
||||
- Do not return pointers into mutable engine memory unless their lifetime is
|
||||
guaranteed.
|
||||
- Do not let GUI widgets mutate internal engine structures directly.
|
||||
- Avoid a public API that mirrors every internal struct field. Provide stable operations instead.
|
||||
- Avoid a public API that mirrors every internal struct field. Provide stable
|
||||
operations instead.
|
||||
|
||||
Example API shape (illustrative only; refine after reviewing the actual codebase):
|
||||
Example API shape (illustrative only; refine after reviewing the actual
|
||||
codebase):
|
||||
|
||||
```c
|
||||
#ifndef XTC_H
|
||||
|
|
@ -254,17 +296,21 @@ xtc_result xtc_transport_stop(xtc_app *app);
|
|||
#endif
|
||||
```
|
||||
|
||||
Do not implement this exact API blindly if the existing design calls for a better interface. Keep it small and consistent.
|
||||
Do not implement this exact API blindly if the existing design calls for a
|
||||
better interface. Keep it small and consistent.
|
||||
|
||||
---
|
||||
|
||||
## 5. Modular processing graph — primary design decision
|
||||
## 5. Modular Processing Graph — Primary Design Decision
|
||||
|
||||
**Decision B: Modular engine first.** The graph is the common representation of signal processing and routing. The sequencer is a source of time-based events and clips, not a separate audio system disconnected from the graph.
|
||||
**Decision B: Modular engine first.** The graph is the common representation of
|
||||
signal processing and routing. The sequencer is a source of time-based events
|
||||
and clips, not a separate audio system disconnected from the graph.
|
||||
|
||||
### Node categories
|
||||
|
||||
Start with a small set:
|
||||
|
||||
- audio input;
|
||||
- audio output;
|
||||
- audio clip player;
|
||||
|
|
@ -277,11 +323,13 @@ Start with a small set:
|
|||
- metering/analyzer;
|
||||
- utility nodes such as channel mapping.
|
||||
|
||||
Do not build every node at once. First prove the graph with a test tone, gain node, and output node.
|
||||
Do not build every node at once. First prove the graph with a test tone, gain
|
||||
node, and output node.
|
||||
|
||||
### Ports and connections
|
||||
|
||||
Each node has a stable identifier, a node type, and declared ports. A port has:
|
||||
|
||||
- a unique identifier within its node;
|
||||
- a direction (input or output);
|
||||
- a signal/data type (audio, MIDI/event, or control);
|
||||
|
|
@ -289,6 +337,7 @@ Each node has a stable identifier, a node type, and declared ports. A port has:
|
|||
- a documented sample/block processing contract.
|
||||
|
||||
Validate connections before accepting them:
|
||||
|
||||
- source and destination exist;
|
||||
- source port is an output and destination is an input;
|
||||
- signal types are compatible;
|
||||
|
|
@ -298,13 +347,18 @@ Validate connections before accepting them:
|
|||
|
||||
### Cycles and feedback
|
||||
|
||||
For the first working engine, reject cycles in the audio-processing graph. A directed acyclic graph is easier to schedule safely and predictably. Report a useful error to the user. Do not silently break a cycle.
|
||||
For the first working engine, reject cycles in the audio-processing graph. A
|
||||
directed acyclic graph is easier to schedule safely and predictably. Report a
|
||||
useful error to the user. Do not silently break a cycle.
|
||||
|
||||
Feedback support can be considered later using explicit delay/feedback nodes and a defined block-boundary model. Never introduce arbitrary graph cycles without a correct scheduling design.
|
||||
Feedback support can be considered later using explicit delay/feedback nodes and
|
||||
a defined block-boundary model. Never introduce arbitrary graph cycles without a
|
||||
correct scheduling design.
|
||||
|
||||
### Graph compilation
|
||||
|
||||
Compile the editable graph into an execution plan outside the real-time thread:
|
||||
|
||||
1. validate nodes, ports, and edges;
|
||||
2. identify source nodes and reachable output nodes;
|
||||
3. detect cycles;
|
||||
|
|
@ -313,21 +367,31 @@ Compile the editable graph into an execution plan outside the real-time thread:
|
|||
6. allocate buffers and prepare node state;
|
||||
7. publish an immutable, ready-to-run plan.
|
||||
|
||||
The audio callback processes the prepared plan. It must not perform graph discovery, sorting, dynamic allocation, file loading, or plugin creation.
|
||||
The audio callback processes the prepared plan. It must not perform graph
|
||||
discovery, sorting, dynamic allocation, file loading, or plugin creation.
|
||||
|
||||
### Graph replacement during playback
|
||||
|
||||
The editor must not modify the graph currently being traversed by the audio thread. Prepare a new plan off-thread and publish it through a bounded real-time-safe mechanism. Define how the old plan is retired only after the audio thread can no longer access it. Do not use a naive pointer swap followed by immediate free.
|
||||
The editor must not modify the graph currently being traversed by the audio
|
||||
thread. Prepare a new plan off-thread and publish it through a bounded
|
||||
real-time-safe mechanism. Define how the old plan is retired only after the
|
||||
audio thread can no longer access it. Do not use a naive pointer swap followed
|
||||
by immediate free.
|
||||
|
||||
Possible approaches include a carefully designed single-producer/single-consumer handoff, epochs, or another proven reclamation scheme. Choose one, document it, and test it under stress. Keep the initial design as simple as safety allows.
|
||||
Possible approaches include a carefully designed single-producer/single-consumer
|
||||
handoff, epochs, or another proven reclamation scheme. Choose one, document it,
|
||||
and test it under stress. Keep the initial design as simple as safety allows.
|
||||
|
||||
### Sequencer integration
|
||||
|
||||
The sequencer stores timeline content and emits events to the graph at the correct sample positions. A clip player or instrument node consumes those events. The GUI timeline is a view/editor for project data; it is not the audio scheduler.
|
||||
The sequencer stores timeline content and emits events to the graph at the
|
||||
correct sample positions. A clip player or instrument node consumes those
|
||||
events. The GUI timeline is a view/editor for project data; it is not the audio
|
||||
scheduler.
|
||||
|
||||
---
|
||||
|
||||
## 6. Real-time audio requirements
|
||||
## 6. Real-Time Audio Requirements
|
||||
|
||||
These rules are mandatory.
|
||||
|
||||
|
|
@ -354,54 +418,75 @@ These rules are mandatory.
|
|||
- process silence safely when a source is unavailable;
|
||||
- handle backend buffer sizes and channel counts within documented limits.
|
||||
|
||||
Do not assume all backends use a fixed block size unless the backend contract guarantees it. Establish maximum supported frame/event counts and define what happens when limits are exceeded.
|
||||
Do not assume all backends use a fixed block size unless the backend contract
|
||||
guarantees it. Establish maximum supported frame/event counts and define what
|
||||
happens when limits are exceeded.
|
||||
|
||||
### Thread ownership
|
||||
|
||||
Document which thread owns each mutable resource:
|
||||
|
||||
- GUI thread: widgets and GUI state;
|
||||
- control/project thread: editable project state, file operations, graph compilation;
|
||||
- control/project thread: editable project state, file operations, graph
|
||||
compilation;
|
||||
- audio thread: active processing plan and real-time DSP state;
|
||||
- backend callbacks: follow the backend's documented threading model.
|
||||
|
||||
Avoid sharing mutable structs across threads without an explicit synchronization strategy. Atomics are not automatically safe for every use: verify that the selected atomic operations are lock-free where required and use correct memory ordering.
|
||||
Avoid sharing mutable structs across threads without an explicit synchronization
|
||||
strategy. Atomics are not automatically safe for every use: verify that the
|
||||
selected atomic operations are lock-free where required and use correct memory
|
||||
ordering.
|
||||
|
||||
### Timing
|
||||
|
||||
Use audio sample position as the authoritative playback clock. Represent timeline positions with an integer or rational scheme that avoids accumulated floating-point drift. Convert musical time (bars/beats/ticks) to sample positions using tempo and meter maps. Define behavior at tempo changes before implementing advanced tempo automation.
|
||||
Use audio sample position as the authoritative playback clock. Represent
|
||||
timeline positions with an integer or rational scheme that avoids accumulated
|
||||
floating-point drift. Convert musical time (bars/beats/ticks) to sample
|
||||
positions using tempo and meter maps. Define behavior at tempo changes before
|
||||
implementing advanced tempo automation.
|
||||
|
||||
---
|
||||
|
||||
## 7. Audio backend strategy
|
||||
## 7. Audio Backend Strategy
|
||||
|
||||
Start on Linux and keep the backend replaceable.
|
||||
|
||||
1. Define a small backend interface in C.
|
||||
2. Implement one backend first, selected after checking the target system and installed development packages. JACK-compatible audio is a reasonable first target on Linux.
|
||||
3. Test device enumeration, start/stop, sample rate, buffer size, channel count, disconnects, and shutdown.
|
||||
2. Implement one backend first, selected after checking the target system and
|
||||
installed development packages. JACK-compatible audio is a reasonable first
|
||||
target on Linux.
|
||||
3. Test device enumeration, start/stop, sample rate, buffer size, channel count,
|
||||
disconnects, and shutdown.
|
||||
4. Keep backend-specific headers out of the public API.
|
||||
5. Add another backend only after the engine works and tests pass.
|
||||
|
||||
Do not assume PipeWire-native, JACK compatibility, ALSA PCM, and desktop audio routing are interchangeable. Document the chosen backend's setup and limitations.
|
||||
Do not assume PipeWire-native, JACK compatibility, ALSA PCM, and desktop audio
|
||||
routing are interchangeable. Document the chosen backend's setup and
|
||||
limitations.
|
||||
|
||||
The engine should also have an offline/test mode that processes buffers without physical audio hardware. This makes unit and integration testing repeatable.
|
||||
The engine should also have an offline/test mode that processes buffers without
|
||||
physical audio hardware. This makes unit and integration testing repeatable.
|
||||
|
||||
---
|
||||
|
||||
## 8. MIDI, parameters, automation, and DSP
|
||||
## 8. MIDI, Parameters, Automation, and DSP
|
||||
|
||||
### MIDI/events
|
||||
### MIDI/Events
|
||||
|
||||
- Use a compact, well-defined event representation.
|
||||
- Store event time relative to a project timeline and convert it to sample offsets for a processing block.
|
||||
- Store event time relative to a project timeline and convert it to sample
|
||||
offsets for a processing block.
|
||||
- Validate event sizes and event counts.
|
||||
- Handle note-on, note-off, velocity, channel, controller, pitch bend, and tempo/transport events as needed.
|
||||
- Ensure all held notes can be released on stop, panic, seek, device loss, or project teardown.
|
||||
- Handle note-on, note-off, velocity, channel, controller, pitch bend, and
|
||||
tempo/transport events as needed.
|
||||
- Ensure all held notes can be released on stop, panic, seek, device loss, or
|
||||
project teardown.
|
||||
- Avoid unbounded event queues.
|
||||
|
||||
### Parameters
|
||||
|
||||
Every automatable control should have:
|
||||
|
||||
- a stable parameter ID;
|
||||
- a type and valid range;
|
||||
- a default value;
|
||||
|
|
@ -409,85 +494,115 @@ Every automatable control should have:
|
|||
- a safe update mechanism;
|
||||
- optional automation and MIDI mapping.
|
||||
|
||||
Do not silently clamp invalid serialized values. Validate project data and return an error or apply a clearly documented migration rule. UI controls may constrain user input, but core validation must remain authoritative.
|
||||
Do not silently clamp invalid serialized values. Validate project data and
|
||||
return an error or apply a clearly documented migration rule. UI controls may
|
||||
constrain user input, but core validation must remain authoritative.
|
||||
|
||||
### Automation
|
||||
|
||||
Implement automation only after transport, graph processing, and basic parameter updates work. Define interpolation types explicitly (initially step and linear are enough). Automation evaluation must be deterministic and bounded.
|
||||
Implement automation only after transport, graph processing, and basic parameter
|
||||
updates work. Define interpolation types explicitly (initially step and linear
|
||||
are enough). Automation evaluation must be deterministic and bounded.
|
||||
|
||||
### DSP
|
||||
|
||||
Start with a few well-tested processors:
|
||||
|
||||
- gain;
|
||||
- pan;
|
||||
- simple meter/peak detector;
|
||||
- test oscillator;
|
||||
- basic delay only after buffer/lifetime handling is sound.
|
||||
|
||||
Keep DSP algorithms in C and independently testable. Use appropriate numerical safeguards, including finite-value checks where needed. Avoid premature SIMD optimization until profiling shows a real bottleneck.
|
||||
Keep DSP algorithms in C and independently testable. Use appropriate numerical
|
||||
safeguards, including finite-value checks where needed. Avoid premature SIMD
|
||||
optimization until profiling shows a real bottleneck.
|
||||
|
||||
---
|
||||
|
||||
## 9. FLTK/C++ GUI guidelines
|
||||
## 9. FLTK/C++ GUI Guidelines
|
||||
|
||||
The GUI is a thin client of the C API, not the owner of the engine.
|
||||
|
||||
### Main views
|
||||
|
||||
1. **Sequencer:** tracks, audio/MIDI clips, timeline ruler, playhead, selection, zoom and horizontal scrolling.
|
||||
2. **Mixer:** channels, faders, pan, mute/solo, inserts/sends when supported, and meters.
|
||||
3. **Modular graph:** nodes, ports, connections, zoom/pan, selection, and connection validation feedback.
|
||||
4. **Transport:** play, stop, record, tempo, meter, loop range, and current position.
|
||||
5. **Project/file dialogs:** create, open, save, import audio, and manage missing assets.
|
||||
1. **Sequencer:** tracks, audio/MIDI clips, timeline ruler, playhead, selection,
|
||||
zoom and horizontal scrolling.
|
||||
2. **Mixer:** channels, faders, pan, mute/solo, inserts/sends when supported,
|
||||
and meters.
|
||||
3. **Modular graph:** nodes, ports, connections, zoom/pan, selection, and
|
||||
connection validation feedback.
|
||||
4. **Transport:** play, stop, record, tempo, meter, loop range, and current
|
||||
position.
|
||||
5. **Project/file dialogs:** create, open, save, import audio, and manage
|
||||
missing assets.
|
||||
|
||||
The default workspace should emphasize the sequencer and transport. The graph view is an advanced but first-class view of the same underlying project.
|
||||
The default workspace should emphasize the sequencer and transport. The graph
|
||||
view is an advanced but first-class view of the same underlying project.
|
||||
|
||||
### GUI implementation
|
||||
### GUI Implementation
|
||||
|
||||
- Use FLTK for conventional widgets and application windows.
|
||||
- Use custom-drawn widgets for the timeline, piano roll, mixer strips, waveform display, and graph canvas where needed.
|
||||
- Use custom-drawn widgets for the timeline, piano roll, mixer strips, waveform
|
||||
display, and graph canvas where needed.
|
||||
- Keep drawing code separate from project mutation.
|
||||
- Use GUI timers or the toolkit's appropriate event mechanism for refreshing meters; never poll from the audio callback or block the GUI waiting for audio.
|
||||
- Use GUI timers or the toolkit's appropriate event mechanism for refreshing
|
||||
meters; never poll from the audio callback or block the GUI waiting for audio.
|
||||
- Avoid redrawing the entire application when only a small region changes.
|
||||
- Support keyboard shortcuts and predictable focus behavior.
|
||||
- Make selection, dragging, snapping, zooming, and scrolling consistent across editors.
|
||||
- Make selection, dragging, snapping, zooming, and scrolling consistent across
|
||||
editors.
|
||||
- Never call FLTK APIs from the audio thread.
|
||||
- Do not hold GUI locks while calling potentially blocking engine operations.
|
||||
- Keep C++ simple: use RAII for GUI resources, clear ownership, and small classes. Do not force the C core into C++ abstractions.
|
||||
- Keep C++ simple: use RAII for GUI resources, clear ownership, and small
|
||||
classes. Do not force the C core into C++ abstractions.
|
||||
|
||||
### Visual direction
|
||||
|
||||
Aim for a compact, dark, high-contrast interface with restrained decoration. Prioritize legible waveforms, clip boundaries, transport state, and meter levels. Avoid excessive gradients, animations, nested panels, and modal configuration windows.
|
||||
Aim for a compact, dark, high-contrast interface with restrained decoration.
|
||||
Prioritize legible waveforms, clip boundaries, transport state, and meter
|
||||
levels. Avoid excessive gradients, animations, nested panels, and modal
|
||||
configuration windows.
|
||||
|
||||
Do not copy energyXT's artwork, exact visual assets, or proprietary UI resources. Recreate the general principles of compactness, direct manipulation, and modular routing in an original design.
|
||||
Do not copy energyXT's artwork, exact visual assets, or proprietary UI
|
||||
resources. Recreate the general principles of compactness, direct manipulation,
|
||||
and modular routing in an original design.
|
||||
|
||||
---
|
||||
|
||||
## 10. Project format and persistence
|
||||
## 10. Project Format and Persistence
|
||||
|
||||
The project format must be versioned from its first release.
|
||||
|
||||
### Requirements
|
||||
|
||||
- Include a format version and application version.
|
||||
- Store stable IDs for tracks, nodes, ports where necessary, clips, parameters, and connections.
|
||||
- Store stable IDs for tracks, nodes, ports where necessary, clips, parameters,
|
||||
and connections.
|
||||
- Save relative asset paths when possible.
|
||||
- Define behavior for missing audio files.
|
||||
- Validate every field before allocating large amounts of memory.
|
||||
- Handle truncated, malformed, unsupported, or corrupted files gracefully.
|
||||
- Never execute code while loading a project.
|
||||
- Save atomically: write a temporary file, flush as appropriate, and rename it into place when safe.
|
||||
- Preserve unknown optional fields when practical, or explicitly document when they are discarded.
|
||||
- Save atomically: write a temporary file, flush as appropriate, and rename it
|
||||
into place when safe.
|
||||
- Preserve unknown optional fields when practical, or explicitly document when
|
||||
they are discarded.
|
||||
- Include migration functions when the format changes.
|
||||
- Keep project serialization outside the real-time thread.
|
||||
|
||||
Choose a simple, well-supported format after considering the dependency and robustness trade-offs. A small, documented text format can help inspect projects, but large binary audio data should generally live in separate assets rather than be embedded in a text document. Do not add a serialization dependency without a clear reason.
|
||||
Choose a simple, well-supported format after considering the dependency and
|
||||
robustness trade-offs. A small, documented text format can help inspect
|
||||
projects, but large binary audio data should generally live in separate assets
|
||||
rather than be embedded in a text document. Do not add a serialization
|
||||
dependency without a clear reason.
|
||||
|
||||
---
|
||||
|
||||
## 11. Undo/redo and editing commands
|
||||
## 11. Undo/Redo and Editing Commands
|
||||
|
||||
Use explicit commands for user-visible edits, such as:
|
||||
|
||||
- create/delete/move/resize clip;
|
||||
- create/delete/rename track;
|
||||
- change parameter;
|
||||
|
|
@ -495,21 +610,28 @@ Use explicit commands for user-visible edits, such as:
|
|||
- connect/disconnect ports;
|
||||
- change tempo or meter.
|
||||
|
||||
A command should validate its inputs and have a well-defined inverse or stored previous state. Avoid designing a generic event-sourcing framework before it is needed.
|
||||
A command should validate its inputs and have a well-defined inverse or stored
|
||||
previous state. Avoid designing a generic event-sourcing framework before it is
|
||||
needed.
|
||||
|
||||
The initial implementation may begin without a complete undo stack, but design edit operations so undo/redo can be added without rewriting all editors. Never make an edit partially visible if it fails validation.
|
||||
The initial implementation may begin without a complete undo stack, but design
|
||||
edit operations so undo/redo can be added without rewriting all editors. Never
|
||||
make an edit partially visible if it fails validation.
|
||||
|
||||
---
|
||||
|
||||
## 12. Build, coding standards, and dependencies
|
||||
## 12. Build, Coding Standards, and Dependencies
|
||||
|
||||
### Build system
|
||||
|
||||
Use a straightforward Makefile unless the existing repository has a sound reason to use another build system.
|
||||
Use a straightforward Makefile unless the existing repository has a sound reason
|
||||
to use another build system.
|
||||
|
||||
The build must:
|
||||
|
||||
- compile C with the selected C standard and warnings enabled;
|
||||
- compile C++ GUI sources with the standard supported by the chosen FLTK version;
|
||||
- compile C++ GUI sources with the standard supported by the chosen FLTK
|
||||
version;
|
||||
- link the GUI with FLTK and the C core;
|
||||
- link the required audio backend;
|
||||
- provide `all`, `clean`, `test`, and a debug build target;
|
||||
|
|
@ -517,9 +639,11 @@ The build must:
|
|||
- avoid embedding machine-specific paths;
|
||||
- separate generated objects and binaries into a build directory.
|
||||
|
||||
Use `pkg-config` where supported by the installed dependencies. Check actual package names on the target distribution rather than hard-coding unverified names.
|
||||
Use `pkg-config` where supported by the installed dependencies. Check actual
|
||||
package names on the target distribution rather than hard-coding unverified
|
||||
names.
|
||||
|
||||
### C style
|
||||
### C Style
|
||||
|
||||
- Use C99 initially.
|
||||
- Use `snake_case`.
|
||||
|
|
@ -532,7 +656,7 @@ Use `pkg-config` where supported by the installed dependencies. Check actual pac
|
|||
- Use `const` where appropriate.
|
||||
- Do not suppress warnings merely to get a clean build.
|
||||
|
||||
### C++ GUI style
|
||||
### C++ GUI Style
|
||||
|
||||
- Keep C++ confined to the GUI and any unavoidable C++-only third-party wrapper.
|
||||
- Prefer small classes with explicit ownership.
|
||||
|
|
@ -544,21 +668,26 @@ Use `pkg-config` where supported by the installed dependencies. Check actual pac
|
|||
### Dependencies
|
||||
|
||||
Before adding a dependency:
|
||||
|
||||
1. identify the exact feature it provides;
|
||||
2. check license and maintenance status;
|
||||
3. determine whether the existing code can provide the functionality simply and safely;
|
||||
3. determine whether the existing code can provide the functionality simply and
|
||||
safely;
|
||||
4. document the dependency and its version constraints;
|
||||
5. keep it optional if the feature is optional.
|
||||
|
||||
Prefer open-source dependencies with clear licensing. Do not claim the whole application is license-compatible until all direct and bundled dependencies have been reviewed.
|
||||
Prefer open-source dependencies with clear licensing. Do not claim the whole
|
||||
application is license-compatible until all direct and bundled dependencies have
|
||||
been reviewed.
|
||||
|
||||
---
|
||||
|
||||
## 13. Testing and diagnostics
|
||||
## 13. Testing and Diagnostics
|
||||
|
||||
### Unit tests
|
||||
|
||||
Test at least:
|
||||
|
||||
- graph validation and topological sorting;
|
||||
- invalid ports and incompatible connections;
|
||||
- cycle detection;
|
||||
|
|
@ -573,6 +702,7 @@ Test at least:
|
|||
### Integration tests
|
||||
|
||||
Test:
|
||||
|
||||
- test oscillator → gain → output processing;
|
||||
- offline rendering with deterministic output;
|
||||
- graph replacement during active processing;
|
||||
|
|
@ -585,6 +715,7 @@ Test:
|
|||
### Tools
|
||||
|
||||
Where available, use:
|
||||
|
||||
- compiler warnings;
|
||||
- AddressSanitizer and UndefinedBehaviorSanitizer in non-real-time test builds;
|
||||
- static analysis;
|
||||
|
|
@ -592,25 +723,29 @@ Where available, use:
|
|||
- stress tests for graph edits and shutdown;
|
||||
- audio loopback or offline render comparisons.
|
||||
|
||||
Sanitizers and diagnostic logging should not be enabled in production real-time callbacks unless their real-time implications have been specifically evaluated.
|
||||
Sanitizers and diagnostic logging should not be enabled in production real-time
|
||||
callbacks unless their real-time implications have been specifically evaluated.
|
||||
|
||||
---
|
||||
|
||||
## 14. Development roadmap and acceptance criteria
|
||||
## 14. Development Roadmap and Acceptance Criteria
|
||||
|
||||
Implement these milestones in order. Do not jump ahead merely because a later feature is exciting.
|
||||
Implement these milestones in order. Do not jump ahead merely because a later
|
||||
feature is exciting.
|
||||
|
||||
### Repository and design baseline
|
||||
|
||||
- Inspect the repository and available toolchain.
|
||||
- Create or update architecture documentation and the Makefile.
|
||||
- Verify C compiler, C++ compiler, FLTK, audio development headers, and test tools.
|
||||
- Verify C compiler, C++ compiler, FLTK, audio development headers, and test
|
||||
tools.
|
||||
- Record dependency and licensing decisions.
|
||||
- Add a minimal application that starts and exits cleanly.
|
||||
|
||||
**Acceptance:** clean build on the target Linux environment; no audio engine assumptions hidden in GUI code.
|
||||
**Acceptance:** clean build on the target Linux environment; no audio engine
|
||||
assumptions hidden in GUI code.
|
||||
|
||||
### C core and offline processing
|
||||
### C Core and offline processing
|
||||
|
||||
- Create the C library/API.
|
||||
- Define node, port, connection, and graph data structures.
|
||||
|
|
@ -619,7 +754,8 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
|||
- Add oscillator, gain, meter, and output test nodes.
|
||||
- Implement deterministic offline block processing.
|
||||
|
||||
**Acceptance:** automated test proves oscillator → gain → meter/output produces expected samples without hardware.
|
||||
**Acceptance:** automated test proves oscillator → gain → meter/output produces
|
||||
expected samples without hardware.
|
||||
|
||||
### Real-time backend
|
||||
|
||||
|
|
@ -629,16 +765,18 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
|||
- Add safe control-to-audio communication.
|
||||
- Stress-test shutdown and graph replacement.
|
||||
|
||||
**Acceptance:** stable playback for a sustained test; no known callback allocations or blocking calls; failures are reported clearly.
|
||||
**Acceptance:** stable playback for a sustained test; no known callback
|
||||
allocations or blocking calls; failures are reported clearly.
|
||||
|
||||
### FLTK shell
|
||||
### FLTK Shell
|
||||
|
||||
- Create main window, menus, transport, status area, and view switching.
|
||||
- Call the C API through the public header.
|
||||
- Add an audio engine status indicator.
|
||||
- Implement clean startup and shutdown.
|
||||
|
||||
**Acceptance:** GUI can start/stop the engine, report backend errors, and close without leaks or hangs.
|
||||
**Acceptance:** GUI can start/stop the engine, report backend errors, and close
|
||||
without leaks or hangs.
|
||||
|
||||
### Modular graph editor
|
||||
|
||||
|
|
@ -648,16 +786,19 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
|||
- Display invalid connection feedback.
|
||||
- Submit graph edits through validated C API commands.
|
||||
|
||||
**Acceptance:** graph shown by the GUI matches the graph used by the engine; invalid connections are rejected without corrupting active playback.
|
||||
**Acceptance:** graph shown by the GUI matches the graph used by the engine;
|
||||
invalid connections are rejected without corrupting active playback.
|
||||
|
||||
### Project and sequencer foundation
|
||||
|
||||
- Add project persistence and stable IDs.
|
||||
- Add tracks and clip objects.
|
||||
- Implement timeline rendering, selection, moving, trimming, zoom, and scrolling.
|
||||
- Implement timeline rendering, selection, moving, trimming, zoom, and
|
||||
scrolling.
|
||||
- Add transport/sample-position synchronization.
|
||||
|
||||
**Acceptance:** save/load a project with clips and reproduce the same arrangement.
|
||||
**Acceptance:** save/load a project with clips and reproduce the same
|
||||
arrangement.
|
||||
|
||||
### Audio clips and recording
|
||||
|
||||
|
|
@ -666,16 +807,18 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
|||
- Keep file I/O outside the audio callback.
|
||||
- Add missing-asset reporting.
|
||||
|
||||
**Acceptance:** record, save, reopen, and play a basic audio project without callback file I/O.
|
||||
**Acceptance:** record, save, reopen, and play a basic audio project without
|
||||
callback file I/O.
|
||||
|
||||
### MIDI and a simple instrument
|
||||
### MIDI And a simple instrument
|
||||
|
||||
- Add MIDI input and clip events.
|
||||
- Add a basic internal synthesizer or test instrument.
|
||||
- Handle note-off, panic, seeking, and stop correctly.
|
||||
- Add a minimal piano-roll editor only after event scheduling works.
|
||||
|
||||
**Acceptance:** record or draw MIDI notes, play them in time, save the project, and reopen it.
|
||||
**Acceptance:** record or draw MIDI notes, play them in time, save the project,
|
||||
and reopen it.
|
||||
|
||||
### Mixer, automation, and editing polish
|
||||
|
||||
|
|
@ -684,7 +827,8 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
|||
- Add a bounded undo/redo system for common edits.
|
||||
- Improve keyboard interaction and workflow.
|
||||
|
||||
**Acceptance:** basic composition and mixing can be completed without editing project files manually.
|
||||
**Acceptance:** basic composition and mixing can be completed without editing
|
||||
project files manually.
|
||||
|
||||
### Extensibility and release preparation
|
||||
|
||||
|
|
@ -693,31 +837,40 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
|||
- Review project format migration, crash behavior, performance, and licensing.
|
||||
- Package the application and document Linux setup.
|
||||
|
||||
**Acceptance:** reproducible release build, tested install/uninstall, clear limitations, and complete user/developer documentation.
|
||||
**Acceptance:** reproducible release build, tested install/uninstall, clear
|
||||
limitations, and complete user/developer documentation.
|
||||
|
||||
---
|
||||
|
||||
## 15. Initial implementation task for the agent
|
||||
## 15. Initial Implementation Task for the Agent
|
||||
|
||||
Start with the **repository and design baseline** only.
|
||||
|
||||
1. Inspect the current repository and report its state.
|
||||
2. Identify the available C/C++ compilers, FLTK version, audio backend development packages, `pkg-config`, and test tools.
|
||||
2. Identify the available C/C++ compilers, FLTK version, audio backend
|
||||
development packages, `pkg-config`, and test tools.
|
||||
3. Do not install packages or modify system configuration without permission.
|
||||
4. Propose the smallest initial source tree compatible with this brief.
|
||||
5. Add or update the Makefile and documentation only as needed.
|
||||
6. Create a minimal program that builds and exits cleanly; do not yet implement a full audio engine or GUI.
|
||||
6. Create a minimal program that builds and exits cleanly; do not yet implement
|
||||
a full audio engine or GUI.
|
||||
7. Build it and run its tests.
|
||||
8. Report exact commands, results, assumptions, and any missing dependencies.
|
||||
|
||||
After the baseline is reviewed, continue with the C core and offline processing. Keep each milestone independently buildable and testable.
|
||||
After the baseline is reviewed, continue with the C core and offline processing.
|
||||
Keep each milestone independently buildable and testable.
|
||||
|
||||
---
|
||||
|
||||
## 16. Long-term quality bar
|
||||
## 16. Long-Term Quality Bar
|
||||
|
||||
The project succeeds if a musician can open it quickly, connect components without fighting the interface, record and arrange audio/MIDI, and make music without needing to understand every detail of the engine.
|
||||
The project succeeds if a musician can open it quickly, connect components
|
||||
without fighting the interface, record and arrange audio/MIDI, and make music
|
||||
without needing to understand every detail of the engine.
|
||||
|
||||
The implementation succeeds if a developer can read the C code, understand ownership and thread boundaries, test components independently, and add functionality without turning the application into an unmaintainable framework.
|
||||
The implementation succeeds if a developer can read the C code, understand
|
||||
ownership and thread boundaries, test components independently, and add
|
||||
functionality without turning the application into an unmaintainable framework.
|
||||
|
||||
**Guiding rule:** build a small, coherent system whose components compose well. Do not build a large DAW and then attempt to simplify it afterward.
|
||||
**Guiding rule:** build a small, coherent system whose components compose well.
|
||||
Do not build a large DAW and then attempt to simplify it afterward.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue