This work is licensed under CC BY-SA 4.0.
Helpers for some MIDI stuff common to my usb_midi_clocker and Microlidian projects.
- Handle MIDI clock and timing, helper functions/macros to find the current MIDI time/position
- Optionally (define #USE_UCLOCK) use uClock for accurate & solid timing
- Supports Teensy 4.0/4.1 and RP2040 platforms
- Functions to find the name of a MIDI note number (eg C5, D#3, etc)
- Keys and scales, with quantising and chord-building
- mymenu widgets for:
- displaying/adjusting BPM
- showing track position
- switching clock sources between Internal/External/None.
- adjusting root key, scale, chords and inversions
- parameters library uses features of this for the 1v/oct tracking quantisation etc
- Defines for GM drum note numbers
- For RP2040 boards, set up MIDI USB with TinyUSB
- vortigont/LinkedList library
- (if using USE_UCLOCK mode) midiliab/uClock library (version 2.0.0 or above)
- add -DUSE_TINYUSB
- define -DUSB_MIDI_VID=0x1337 vendor ID
- define -DUSB_MIDI_PID=0xBEEF product ID
- define -DUSB_MIDI_MANUFACTURER=""TyrellCorp"" manufacturer string
- define -DUSB_MIDI_PRODUCT=""FunkyDevice"" product string
- define -DUSE_DINMIDI
- define -DMIDI_SERIAL_SPIO
- define -DMIDI_SERIAL_OUT_PIN=D6 or whatever pin you're using for output
- a class to make it simple to track which notes are held by an input or output
chord inversions- fix envelopes
- 'hold' stage doesnt work properly when inverted
Tests live in test/native/ and run on the host (no hardware needed) via PlatformIO's native environment.
# From the midihelpers/ directory:
pio test -e native
# Or use the helper script (works from any directory):
bash scripts/run_tests.sh
# Verbose output (shows individual PASS/FAIL lines):
pio test -e native -vvThe test binary is built, run, and results printed automatically.
All test_*.cpp files in test/native/ are discovered automatically by PlatformIO.
| Path | Purpose |
|---|---|
platformio.ini |
Defines the native env: build flags, include paths, saveloadlib dep |
test/native/arranger_test_stubs.cpp |
Global variable definitions needed by saveloadlib and bpm.h |
test/native/stubs/Arduino.h |
Arduino types (String, SerialStub, F(), constrain()) |
test/native/stubs/bpm.h |
Forwarder → real include/bpm.h (already native-compatible) |
test/native/stubs/LinkedList.h |
std::vector-backed LinkedList stub |
test/native/stubs/functional-vlpp.h |
std::function-backed vl::Func stub |
test/native/stubs/scales.h |
Unused (real scales.h guards Arduino includes itself) |
-
Add a
void test_my_feature()function intest/native/test_arranger.cpp
(or create a newtest/native/test_foo.cppfor a different class). -
Use Unity assertion macros:
TEST_ASSERT_EQUAL_INT(expected, actual); TEST_ASSERT_EQUAL_UINT8(expected, actual); TEST_ASSERT_TRUE(expr); TEST_ASSERT_FALSE(expr); TEST_ASSERT_NULL(ptr); TEST_ASSERT_NOT_NULL(ptr);
-
Register it in
main():RUN_TEST(test_my_feature); -
Use the
tick_bars(Arranger* a, int n)helper to advance time:void test_my_feature() { Arranger a; a.setup_saveable_settings(); // configure a.song_sections / a.playlist as needed a.on_restart(); // sets playlist_position=0, applies section 0 tick_bars(&a, 4); // advance 4 bars (calls on_bar() 4 times) TEST_ASSERT_EQUAL_INT(1, a.playlist_position); }
-
setUp()(called before every test) resetsticks,ts_phase_offset, and
current_time_signatureto defaults automatically — no manual cleanup needed.
-DENABLE_STORAGE -DENABLE_ARRANGER -DENABLE_TIME_SIGNATURE -DENABLE_SCALES
Add further -DENABLE_* flags there if testing code guarded by other defines.