{"id":15623577,"url":"https://github.com/jacoby6000/maestro-midi","last_synced_at":"2025-03-29T16:30:04.365Z","repository":{"id":57720329,"uuid":"99259816","full_name":"Jacoby6000/maestro-midi","owner":"Jacoby6000","description":"Just parses midi files. Nothing fancy. Useful if you want to do some stuff with a midi file.","archived":false,"fork":false,"pushed_at":"2017-08-22T23:08:47.000Z","size":254,"stargazers_count":1,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-04T17:47:31.784Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","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/Jacoby6000.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}},"created_at":"2017-08-03T17:45:19.000Z","updated_at":"2020-09-10T04:46:55.000Z","dependencies_parsed_at":"2022-08-25T15:50:47.904Z","dependency_job_id":null,"html_url":"https://github.com/Jacoby6000/maestro-midi","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/Jacoby6000%2Fmaestro-midi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jacoby6000%2Fmaestro-midi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jacoby6000%2Fmaestro-midi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jacoby6000%2Fmaestro-midi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jacoby6000","download_url":"https://codeload.github.com/Jacoby6000/maestro-midi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246212828,"owners_count":20741591,"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":[],"created_at":"2024-10-03T09:57:42.196Z","updated_at":"2025-03-29T16:30:04.341Z","avatar_url":"https://github.com/Jacoby6000.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Maestro Midi\n\nJust some simple tools for parsing midi files. Maestro Midi does nothing to infer or coerce the midi \nfile in any way. It'll give you a format mirroring 1:1 with the file that was provided.\n\n## Usage\n\nAdd as a dependency with \n```scala\nlibraryDependencies += \"com.github.jacoby6000\" %% \"maestro-midi\" % \"0.1.1\"\n```\n\nThen use:\n```scala\nimport com.github.jacoby6000.maestro.midi._\nimport java.nio.file.Files\nimport java.nio.file.Paths\n\nval midiData: Either[scodec.Err, StandardMidi] = decodeMidi(Files.readAllBytes(Paths.get(\"path/to/midi/file.mid\")))\n```\n\n`decodeMidi` is overloaded to work for `Array[Byte]`, `scodec.BitVector`, and `scodec.ByteVector`.\n\n## Understanding\n\nTo make use of this library, it is best to have some familiarity with [the midi spec](https://www.csie.ntu.edu.tw/~r92092/ref/midi/). \nThis library will handle things like \"Running Status\" for you, and everything else is just mapped to\nthe events that you will read in the specification.\n\nSome consequences of the structure returned being a mirror of the file, is that there are some \nevents which you might not expect.  `NoteOn(channel, pitch, velocity = 0)` is exactly the same as \n`NoteOff(channel, pitch, 40)` and many applications will export midi using `NoteOn` actions \nwith `velocity` set to `0` instead of `NoteOff` actions. This helps shorten the midi file because of \nthe whole \"Running Status\" thing. `midiFile.normalizeOnOff` will fix this and give you what \nyou probably expect. `midiFile.denormalizeOnOff` will do the opposite. \n\n## Extensions\n\nIf you read the specification, you'll note that the Midi specification leaves room for custom \nevents.  To use these, just create a `midi.extensions.MidiExtension` instance, and then run \n`decodeMidiExtended(bytes, extension)` to get an instance of a midi file with the extension events \nproperly decoded.  I don't currently have any of these, because I've only ever needed standard midi \nevents. If you come up with one, let me know and I'll add some docs around it.\n\n## Caveats \n\nIf you hold on to instances of `midi.decode.fileCodec`, be wary that the individual instances are \n_not_ thread safe. This is because I'm bad and the way way I'm dealing with \"Running Status\" in the \n`eventCodec` uses state.  If you parallelize on calls to `midi.decodeMidi` you will be fine, \nhowever. Each call to `decodeMidi` gets its own instance of `midi.decode.fileCodec`.\n\n### Extras\n\nMonocle Lense Library\n```\nlibraryDependencies += \"com.github.jacoby6000\" %% \"maestro-midi-lenses\" % \"0.1.1\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacoby6000%2Fmaestro-midi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjacoby6000%2Fmaestro-midi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacoby6000%2Fmaestro-midi/lists"}