An open API service indexing awesome lists of open source software.

https://github.com/adamico/picotron-mml-parser

A Macro Music Language parser for Picotron
https://github.com/adamico/picotron-mml-parser

lua mml music parser-api picotron

Last synced: about 1 month ago
JSON representation

A Macro Music Language parser for Picotron

Awesome Lists containing this project

README

          

# Picotron MML Parser

A lightweight **Music Macro Language (MML)** parser and sequencer for [Picotron](https://www.lexaloffle.com/picotron.php), designed for compatibility with the [Pyxel MML specification](https://kitao.github.io/pyxel/wasm/mml-studio/mml-commands.html).

This library allows you to play complex musical sequences in your Picotron games using simple strings, supporting features like nested loops, custom tempos, and precise timing.

## Features

- **Pyxel Compatibility**: Supports standard MML commands used by the Pyxel game engine.
- **Nested Loops**: Arbitrary nesting of sequences using `[...]` syntax.
- **Coroutine-Based Playback**: Integrates seamlessly into your `_update()` loop without blocking.
- **Precise Timing**: Uses sub-tick accumulation for stable playback even at high tempos and non-integer durations.
- **Automatic Silence**: Correctly handles rests (`r`) and ensures the channel is silenced when the sequence ends.
- **Volume Scaling**: Automatically maps MML volume (0-15) to Picotron's internal volume range (0-7).

## Installation

Simply copy `mml_parser.lua` into your Picotron project folder (e.g., `/drive/lib/`).

## Quick Start

```lua
local mml_parser = require("lib/mml_parser")

-- 1. Compile your MML string
local mml_string = "t120 l8 o3 c d e [f g [a b]2]2 r4 c2"
local result = mml_parser:compile(mml_string)

-- 2. Create a player coroutine (Channel 0, Instrument 0, 30 ticks per beat)
local music_co = cocreate(mml_parser:create_player(result, 0, 0, 30))

function _update()
-- 3. Resume the coroutine every frame
if music_co and costatus(music_co) ~= "dead" then
coresume(music_co)
end
end
```

## Supported Commands

| Command | Description | Example |
| :--- | :--- | :--- |
| `c`, `d`, `e`, `f`, `g`, `a`, `b` | Play a note. Use `#` or `+` for sharp, `-` for flat. | `c4 d#8 g+16` |
| `r` | Rest (silence). | `r4` |
| `o` | Set octave (0-8). Default is 3. | `o4` |
| `<` / `>` | Decrease / Increase octave. | `> c < b` |
| `t` | Set tempo (BPM). Default is 120. | `t150` |
| `v` | Set volume (0-15). Default is 12. | `v8` |
| `l` | Set default note length (1, 2, 4, 8, 16...). Default is 4. | `l8` |
| `[...]n` | Loop the bracketed sequence `n` times. | `[c d e]2` |

## API Reference

### `mml_parser:compile(mml_string)`

Parses the MML string and returns a table containing:

- `notes`: A list of compiled note events.
- `tempo`: The initial tempo.
- `duration`: The total duration of the sequence in beats.

### `mml_parser:create_player(result, channel, instrument, ticks_per_beat)`

Returns a function intended to be wrapped in a `cocreate()`.

- `result`: The output from `compile()`.
- `channel`: (0-15) Target audio channel.
- `instrument`: (0-127) Instrument index.
- `ticks_per_beat`: Adjust this based on your game's FPS and tempo (default 30).

## License

This project is released under the MIT License.