{"id":13906604,"url":"https://github.com/LingDong-/legumes","last_synced_at":"2025-07-18T04:32:09.236Z","repository":{"id":84534679,"uuid":"367747122","full_name":"LingDong-/legumes","owner":"LingDong-","description":"🎼 A sheet music to polylines renderer","archived":false,"fork":false,"pushed_at":"2021-05-16T19:52:10.000Z","size":20223,"stargazers_count":231,"open_issues_count":0,"forks_count":10,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-11-19T00:57:20.385Z","etag":null,"topics":["hershey-fonts","polylines","renderer","sheet-music","vector-graphics"],"latest_commit_sha":null,"homepage":"https://legumes.netlify.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LingDong-.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-05-15T23:17:22.000Z","updated_at":"2024-09-22T00:54:23.000Z","dependencies_parsed_at":"2024-04-16T06:37:50.582Z","dependency_job_id":null,"html_url":"https://github.com/LingDong-/legumes","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LingDong-%2Flegumes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LingDong-%2Flegumes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LingDong-%2Flegumes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LingDong-%2Flegumes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LingDong-","download_url":"https://codeload.github.com/LingDong-/legumes/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226344724,"owners_count":17610193,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hershey-fonts","polylines","renderer","sheet-music","vector-graphics"],"created_at":"2024-08-06T23:01:39.020Z","updated_at":"2024-11-25T14:32:00.133Z","avatar_url":"https://github.com/LingDong-.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# legumes\n\n🎼 *A sheet music to polylines renderer*\n\n**[Samples](./samples) | [Online Editor](https://legumes.netlify.app/) | [API](API.md) | [Syntax](SYNTAX.md)**\n\n\u003cimg src=\"screenshots/000.png\" width=\"400\"/\u003e\n\nIn goes a midi file or a [simple markup format](SYNTAX.md), and out comes ✨polylines✨, which can then be used for animation, plotting and various procedural drawing fun.\n\n\u003e 🚧 This project is a work in progress and currently supports a subset of sheet music notation. Errors and ugliness might occur from time to time\u003csup\u003e*\u003c/sup\u003e. For professional quality scorewriting, check out https://en.wikipedia.org/wiki/List_of_scorewriters instead. 🚧\n\n## Features\n\n- Supports most everyday classical music symbols;\n- Exports polylines, svg, pdf, gif, midi and more;\n- Lightweight: \u003c 150KB minified; No dependencies;\n- Uses [Hershey Fonts](http://paulbourke.net/dataformats/hershey/) for text and symbols; You can load custom hershey fonts for rendering unicode etc;\n- Includes basic animation and handdrawn effects generator;\n- Use as browser/node.js library or commandline interface.\n\nFor examples, below are the first couple measures of Grieg's \"Solitary Wanderer\", typeset in legumes, with regular, animated and hand-drawn styles:\n\n![](screenshots/001.svg)\n![](screenshots/002.gif)\n![](screenshots/003.svg)\n\nYou can find at the bottom of this document the full score, or better yet,  **Checkout the [samples](./samples) folder** for a more comprehensive showcase featuring music by various composers!\n\n\u003csub\u003e*legumes is an acronym for *Lingdong's Erratic and Generally Useless Musical Engraving System*.\u003c/sub\u003e\n\n## Usage\n\nThe easiest way to try out the project is by using the [Online Editor](https://legumes.netlify.app/), which supports syntax highlighting and midi playback. For more advanced usage, there're commandline and programming interfaces, described below:\n\n### Commandline\n\nThe [`legc` executable](./legc) included in the repo is a shebang'ed node.js script. You can easily invoke it in the commandline via `./legc` (or `legc` if placed/aliased in PATH) if you have node.js installed.\n\nMinimal example, rendering a score to SVG:\n\n```\nlegc --format svg samples/minuet_G.txt \u003e output.svg\n```\n\nAnother example, render a score to an animated svg, specifying some rendering options:\n\n```\nlegc --format svg-anim \\\n  --stem-length 3 --title-text-size 28 --page-margin-x 120\\\n  samples/minuet_G.txt \u003e output.svg\n```\n\nThe commandline tool supports some 50+ rendering/export options, view the full list by typing:\n\n```\nlegc --help\n```\n\n### Programming\n\nBuilt JavaScript files acn be found in `dist/` folder. Import them via\n\n```html\n\u003cscript src=\"dist/legumes.min.js\"\u003e\u003c/script\u003e\n```\n\nor\n\n```js\nconst legumes = require(\"dist/legumes\");\n```\n\nYou can find the full API doc [here](API.md), but here's a minimal example:\n\n```js\nconst txt = fs.readFileSync(\"samples/minuet_G.txt\").toString();\n\n// build a score from the text-based markup\nconst score = legumes.parse_txt(txt);\n\n// compile the score to pre-compute properties for drawing\nlegumes.compile_score(score);\n\n// draw the score\nlet drawing = legumes.render_score(score);\n\n// export drawing to SVG format\nlet svg = legumes.export_svg(drawing)\n\nfs.writeFileSync(\"output.svg\",svg);\n// document.body.innerHTML = svg;\n```\n\nYou can configure rendering options via the `CONFIG` object, e.g. :\n\n```js\nlegumes.CONFIG.STEM_LENGTH = 3;\nlegumes.CONFIG.DURATION_BASED_SPACING = 0.07;\nlegumes.CONFIG.LYRIC_SCALE = 0.8;\n```\n\nMidi files can also be rendered, but note that midi is not a suitable format storing sheet music, and educated guesses has to be made converting it to one:\n\n```js\nlet bytes_in = Array.from(new Uint8Array(fs.readFileSync(\"input.mid\")));\nlet midi_file = legumes.parse_midi(bytes_in);\nlet score = legumes.score_from_midi(midi_file);\nlegumes.compile_score(score);\nfs.writeFileSync(\"output.svg\", legumes.export_svg(drawing));\n```\n\nWhat one could do, is read a midi file, and export it as markup text, make improvements by hand, and render the latter instead:\n\n```js\nlet bytes_in = Array.from(new Uint8Array(fs.readFileSync(\"input.mid\")));\nlet midi_file = legumes.parse_midi(bytes_in);\nlet score = legumes.score_from_midi(midi_file);\nlet txt = legumes.export_txt(score);\nfs.writeFileSync(\"score.txt\", txt);\n```\n\nIn addition to the supported input file formats, you can construct your own score object to feed into legumes, as long as it conforms to the interface:\n\n```ts\ninterface Score_itf{\n  title:       string[];\n  composer:    string[];\n  tempo?:      Tempo_itf;\n  instruments: Instrument_group_itf[];\n  slurs:       Slur_itf[];\n  measures:    Measure_itf[];\n  crescs:      Cresc_itf[];\n}\n```\nYou can find more details about these interfaces in [API doc](API.md) and `src/common.ts`.\n\n\n\n![](screenshots/004.svg)\n\n\nlegumes render with several stages. You can unplug the final polylines output and write a custom renderer that interprets the computed element layout. For example, visualize the elements with `export_mock_svg` routine:\n\n```js\nlet drawing = legumes.render_score(score,{compute_polylines:false});\nlet svg = legumes.export_mock_svg(drawing)\n```\n\n![](screenshots/005.svg)\n\nMore details can be found in `src/drawing.ts`.\n\n\n----\n\nSpecial thanks to my friend [@jiangzoi](https://github.com/jiangzoi) (Computational music major at CMU) and my mother (piano teacher) for advice and help on sheet music, of which I came to realize I know little as I progress with the project.\n\nIssues \u0026 Pull request are welcome.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLingDong-%2Flegumes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLingDong-%2Flegumes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLingDong-%2Flegumes/lists"}