Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v19.1.7
hooks:
- id: clang-format

- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
92 changes: 69 additions & 23 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,69 @@
### 0.3.0

* Add playback rate control to disksampler
* Add node placement options to node creation API commands. `Methcla::NodePlacement` can be used to control node placement in the C++ API.
* Remove `Methcla_Resource` from plugin API: Remove argument from `Methcla_SynthDef::construct` and rename `methcla_world_resource_retain`/`methcla_world_resource_release` to `methcla_world_synth_retain`/`methcla_world_synth_release`
* Implement various node placement options
* Allow plugins to notify the engine that they are done processing; add `methcla_world_synth_done` function to plugin API
* Fix bus zeroing logic (#102)
* Add operator bool to `Methcla::NodeId`
* Add `Methcla::Engine::nodeEndedHandler` API method returning `/node/ended` notification handler
* Add `ExponentialFade` plugin (`METHCLA_PLUGINS_EXPONENTIAL_FADE_URI`) to `methcla_plugins_node_control` library
* Fix bug in linked list implementation when adding a node before or after an existing node

### 0.2.0

* Rename `Methcla::Engine::freeNode` to `Methcla::Engine::free`
* Use `Methcla::Engine::Bundle` instead of `Methcla::Engine::Request`
* Move plugin includes to `<methcla/plugins/*>`
* **[Pro]** Include ExtAudioFile soundfile API
* Split synth creation into `/synth/new` (`Methcla::Engine::synth`) and `/synth/activate` (`Methcla::Engine::activate`)
* Refactor engine interface: Rename `Methcla::Engine::Request` to `Methcla::Request` and remove `Methcla::Engine::Bundle`. `Methcla::Request` now has `openBundle`/`closeBundle` methods for creating (nested) bundle structures.
* Add function for querying library version (`methcla_version`, `Methcla::version()`)
* Add function for changing debug logging behaviour (`methcla_engine_set_log_flags`, `Methcla::Engine::setLogFlags`)
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Playback rate control to disksampler
- Node placement options to node creation API commands (`Methcla::NodePlacement`)
- `methcla_world_synth_done` function to plugin API to notify the engine when processing is finished
- `operator bool` to `Methcla::NodeId`
- `Methcla::Engine::nodeEndedHandler` API method returning `/node/ended` notification handler
- `ExponentialFade` plugin (`METHCLA_PLUGINS_EXPONENTIAL_FADE_URI`) to `methcla_plugins_node_control` library
- Install and export CMake targets; `methcla::methcla` now available via `find_package` (#123)
- `METHCLA_BUILD_TESTS` CMake option, defaults to on when building as top-level project (#122)
- CMake presets (`debug`, `release`) replacing ad-hoc build configuration
- GitHub Actions CI replacing Travis CI
- `CONTRIBUTING.md` with build, test, and PR workflow instructions
- `docs/architecture.md` with Mermaid audio routing diagram
- `docs/osc-api.md` (moved from `doc/OSC API.md`)
- `examples/README.md` describing the thADDeus and sampler examples

### Changed

- Dependency management modernised: `FetchContent` for oscpp and googletest; Boost 1.91.0 vendored with `methcla_boost` namespace to avoid symbol collisions (#129)
- C++ standard raised to C++17
- `Driver::Options` channel and buffer size fields changed from `int` to `size_t` (#80)
- Plugin libraries now build as CMake `MODULE` targets; soundfile API plugin selected per platform (#121)
- CMake target structure cleaned up: proper `PUBLIC`/`PRIVATE` dependencies, `methcla::methcla` alias target (#120)
- Warning flags scoped per-target via `methcla_target_warnings()` (#120)
- README rewritten: corrects platform scope (macOS and Linux desktop), updates build instructions, adds usage snippet

### Fixed

- Bus zeroing logic (#102)
- Bug in linked list implementation when adding a node before or after an existing node
- Rounding, float precision, and type safety issues (#135)
- Implicit `NodeId` conversions broken by explicit constructor (#81)
- Missing `#include` directives causing build failures with GCC 13 and recent Clang
- GCC 13 false positive warnings from Boost lockfree and tinydir

### Removed

- `Methcla_Resource` from plugin API: removed argument from `Methcla_SynthDef::construct`; renamed `methcla_world_resource_retain`/`methcla_world_resource_release` to `methcla_world_synth_retain`/`methcla_world_synth_release`
- Dead platform code and unused vendored libraries (Android, iOS, PNaCl, NaCl) (#128)
- `VERSION` file (version is solely in `CMakeLists.txt`)
- Stale `doc/Notes.md` and `doc/diagrams/`

## [0.2.0]

### Added

- Function for querying library version (`methcla_version`, `Methcla::version()`)
- Function for changing debug logging behaviour (`methcla_engine_set_log_flags`, `Methcla::Engine::setLogFlags`)
- ExtAudioFile soundfile API (macOS)

### Changed

- Split synth creation into `/synth/new` (`Methcla::Engine::synth`) and `/synth/activate` (`Methcla::Engine::activate`)
- Refactored engine interface: renamed `Methcla::Engine::Request` to `Methcla::Request`, removed `Methcla::Engine::Bundle`; `Methcla::Request` now has `openBundle`/`closeBundle` for nested bundle structures
- Renamed `Methcla::Engine::freeNode` to `Methcla::Engine::free`
- Moved plugin includes to `<methcla/plugins/*>`

[unreleased]: https://github.com/samplecount/methcla/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/samplecount/methcla/releases/tag/v0.2.0
79 changes: 77 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,67 @@
# CLAUDE.md

## Fundamentals

### 1. Think Before Coding

**Don't assume. Don't hide confusion. Surface tradeoffs.**

Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.

### 2. Simplicity First

**Minimum code that solves the problem. Nothing speculative.**

- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

### 3. Surgical Changes

**Touch only what you must. Clean up only your own mess.**

When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

### 4. Goal-Driven Execution

**Define success criteria. Loop until verified.**

Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:
```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.

---

**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.

## Agent skills

### Issue tracker
Expand All @@ -12,11 +76,22 @@ Uses the default five-role vocabulary (needs-triage, needs-info, ready-for-agent

Single-context layout: one `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.

## GitHub workflows
## Workflows

- Create PRs for non-trivial changes. This allows reviewing code and running actions before merging.
- Create PR branches before submitting a PR or when prompted to submit changes to a PR branch.
- For small, low-risk changes, or when prompted to do so, commit directly to develop.
- Before committing changes or submitting PRs, build locally and run tests.
- Before committing changes or submitting PRs, run `pre-commit run --all-files` to format code, then build locally and run tests.
- When merging PRs via gh, update the working copy accordingly (pull and delete PR branch).
- Keep PR branch name descriptive but short. No prefixes like `feat/`. Dashes: `my-awesome-new-feature`.
- See `CONTRIBUTING.md` for the human-facing version of these workflows.
- When adding features or fixes, add an entry under `## [Unreleased]` in `CHANGELOG.md` using the standard sections: Added, Changed, Deprecated, Removed, Fixed, Security.
- To cut a release: run `scripts/release.py <version>` then `git push && git push --tags`.

## Domain and API references

- Use the domain language in `CONTEXT.md`; avoid the listed synonyms.
- Before changing build structure or dependencies, check `docs/adr/` for prior decisions.
- When working with synth, node, or bus commands, consult `docs/osc-api.md`.
- For audio routing and node tree structure, see `docs/architecture.md`.
- Follow `docs/coding-style.md` for all code changes.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ add_subdirectory(src)
if(METHCLA_BUILD_TESTS)
add_subdirectory(tests)
endif()
if(PROJECT_IS_TOP_LEVEL)
add_subdirectory(tools)
endif()

install(EXPORT methclaTargets
NAMESPACE methcla::
Expand Down
52 changes: 52 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Contributing

## Setup

Install the pre-commit hooks after cloning:

```sh
pip install pre-commit # or: brew install pre-commit
pre-commit install
```

Hooks run automatically on `git commit`. To format all files manually:

```sh
pre-commit run --all-files
```

## Build and test

```sh
cmake --preset debug # or: release
cmake --build build/debug # or: build/release
ctest --test-dir build/debug --output-on-failure
```

Always build and run tests before submitting changes.

## Workflow

- **Non-trivial changes**: open a pull request. This lets CI run and allows review before merging.
- **Small, low-risk changes**: commit directly to `develop`.
- **Branch names**: short, descriptive, dashes. No prefixes. Example: `fix-rtaudio-latency`.
- **Merging**: use squash or merge commit via GitHub. Delete the branch after merging.

## Code style

See [`docs/coding-style.md`](docs/coding-style.md). C++17, C99. No new dependencies without discussion.

## Changelog

Add an entry under `## [Unreleased]` in `CHANGELOG.md` for every feature, fix, or notable change,
using the standard sections: Added, Changed, Deprecated, Removed, Fixed, Security.

## Releasing

1. Ensure `## [Unreleased]` in `CHANGELOG.md` is up to date.
2. Run `scripts/release.py <version>` (e.g. `scripts/release.py 1.2.3`).
- Bumps the version in `CMakeLists.txt`
- Moves `[Unreleased]` content to `[version]` in `CHANGELOG.md`
- Commits both files and creates an annotated git tag
3. Push: `git push && git push --tags`
4. Create a GitHub release from the tag, pasting the changelog entry as the description.
95 changes: 61 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,85 @@
[![Build Status](https://travis-ci.org/samplecount/methcla.svg?branch=develop)](https://travis-ci.org/samplecount/methcla)
[![CI](https://github.com/samplecount/methcla/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/samplecount/methcla/actions/workflows/ci.yml)

# Methcla - Mobile sound engine
# Methcla

Methcla is a light-weight, efficient sound engine for mobile devices, see our [website](http://methc.la) for the full picture.
A real-time C++ audio engine library for macOS and Linux. Exposes a C API with C++ bindings for embedding in host applications.

## Build requirements
## Requirements

* GCC >= 4.7 or Clang >= 3.3
- CMake 3.24+, C++17 (GCC or Clang)
- Optional: [RtAudio](https://www.music.mcgill.ca/~gary/rtaudio/) for audio I/O (`-DMETHCLA_ENABLE_RTAUDIO=ON`)
- Optional: [libsndfile](https://libsndfile.github.io/libsndfile/) for soundfile support on Linux

## Building the sound engine
## Build

Our build system is written in Haskell using the [Shake](https://github.com/ndmitchell/shake) library and you need to install the latest [Haskell platform](http://www.haskell.org/platform/) before building Methcla.
```sh
cmake --preset debug # configure (or: release)
cmake --build build/debug # build
ctest --test-dir build/debug --output-on-failure # test
```

First off, don't forget to
## Usage

git submodule update --init --recursive
```cpp
#include <methcla/engine.hpp>
#include <methcla/plugins/sine.h>

after pulling from Methcla's repository.
Methcla::EngineOptions options;
options.addLibrary(methcla_plugins_sine);

To build a specific target (see below for a list of possible targets):
Methcla::Engine engine(options);
engine.start();

./shake TARGET
// Create a sine synth (freq=440 Hz, amp=0.5) on hardware output bus 0
Methcla::Request request(&engine);
request.openBundle();
auto synth = request.synth(METHCLA_PLUGINS_SINE_URI, engine.root(), {440.f, 0.5f});
request.activate(synth);
request.mapOutput(synth, 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
request.closeBundle();
request.send();

To clean everything
// Free the synth when done
Methcla::Request stop(&engine);
stop.openBundle();
stop.free(synth);
stop.closeBundle();
stop.send();
```

./shake clean
See [`docs/osc-api.md`](docs/osc-api.md) for the full command protocol and [`docs/architecture.md`](docs/architecture.md) for an overview of audio routing.

Use the `-j` flag for parallel builds:
## Integration

./shake -j4 test
**add_subdirectory:**

The build script automatically passes the number of core in your build machine, use `-j1` to force a sequential build.
```cmake
add_subdirectory(path/to/methcla)
target_link_libraries(myapp PRIVATE methcla::methcla)
```

The `-c` flag allows to select a build configuration (*release* or *debug*):
**FetchContent:**

./shake -c release test
```cmake
include(FetchContent)
FetchContent_Declare(methcla
GIT_REPOSITORY https://github.com/samplecount/methcla.git
GIT_TAG develop)
FetchContent_MakeAvailable(methcla)
target_link_libraries(myapp PRIVATE methcla::methcla)
```

Display the list of Shake command line options:
**find_package** (after `cmake --install`):

./shake -h

All built files are put in the `build` directory.

Here's a non-exhaustive list of targets:

* `test`: Run the test suite; this should be first thing to do when porting to a new platform.
* `desktop`: Build a shared library for the host operating system
* `iphoneos`: Build a static library for iOS devices
* `iphone-universal`: Build a static library for iOS devices and simulator
* `android`: Build a static library for Android
* `pnacl`: Build a static library for Pepper/PNaCl
```cmake
find_package(methcla REQUIRED)
target_link_libraries(myapp PRIVATE methcla::methcla)
```

## Examples

[thADDeus](https://github.com/samplecount/methcla/tree/develop/engine/examples/thADDeus) is an example project that builds the engine for iOS and Android devices and provides a simple multitouch sine synthesizer.
See [`examples/`](examples/) for sample applications.

## Contributing

The [sampler](https://github.com/samplecount/methcla/tree/develop/engine/examples/sampler) example is a simple multitouch sampler application.
See [`CONTRIBUTING.md`](CONTRIBUTING.md).
1 change: 0 additions & 1 deletion VERSION

This file was deleted.

Loading
Loading