{"id":13862817,"url":"https://github.com/pelevesque/MIDI-Make","last_synced_at":"2025-07-14T13:32:34.989Z","repository":{"id":50267058,"uuid":"518647792","full_name":"pelevesque/MIDI-Make","owner":"pelevesque","description":"A Raku module to make MIDI files.","archived":false,"fork":false,"pushed_at":"2024-11-19T15:51:45.000Z","size":156,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-19T16:49:08.630Z","etag":null,"topics":["composition","midi","music","sequencer"],"latest_commit_sha":null,"homepage":"","language":"Raku","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/pelevesque.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","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":"2022-07-28T00:18:23.000Z","updated_at":"2024-11-19T15:51:50.000Z","dependencies_parsed_at":"2024-04-13T17:04:36.969Z","dependency_job_id":"dbca3e44-fc4d-4ff6-b3f3-5d8bacd5558e","html_url":"https://github.com/pelevesque/MIDI-Make","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelevesque%2FMIDI-Make","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelevesque%2FMIDI-Make/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelevesque%2FMIDI-Make/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelevesque%2FMIDI-Make/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pelevesque","download_url":"https://codeload.github.com/pelevesque/MIDI-Make/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225980898,"owners_count":17554919,"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":["composition","midi","music","sequencer"],"created_at":"2024-08-05T06:01:53.269Z","updated_at":"2024-11-22T23:30:28.583Z","avatar_url":"https://github.com/pelevesque.png","language":"Raku","funding_links":[],"categories":["Raku"],"sub_categories":[],"readme":"[![Actions Status](https://github.com/pelevesque/MIDI-Make/actions/workflows/test.yml/badge.svg)](https://github.com/pelevesque/MIDI-Make/actions)\n\n# MIDI::Make\n\nA [Raku](https://www.raku.org) module to make MIDI files.\n\n## Synopsis\n\n```raku\nuse MIDI::Make;\n\nmy \\t = Track.new;\nt.copyright:      'c 2022 anonymous';\nt.name:           'melody';\nt.instrument:     'piano';\nt.controller:     8, 100;\nt.program-name:   'electric piano';\nt.port:           'MIDI Out 1';\nt.channel         1;\nt.program-change: 100;\nt.aftertouch:     100;\nt.pitch-bend:     0;\nt.marker:                 'section I';\nt.text:           'Lorem ipsum dolor sit amet.';\nt.key-signature:  2♭, minor;\nt.tempo:          ♩80;\nt.time-signature: 3\\2;\nt.aftertouch:     100, 53;\nt.note-on:        60;\nt.lyric:          'one';\nt.delta-time:         128;\nt.note-off:       60;\nt.cue:            'door slam';\nt.velocity-on:    80;\nt.velocity-off:   10;\nt.note-on:        72;\nt.lyric:          'two';\nt.delta-time:         128;\nt.note-off:       72;\nt.sysex:          \u003c0A 29 1E\u003e;\nt.add-bytes:      \u003c00 F0 0A 29 1E F7\u003e;\n\nmy \\s = Song.new(:PPQ(96));\ns.add-track(t.render);\n\n    # Print the MIDI contents.\nsay s.render;\n\n    # Save the MIDI contents to file.\nspurt 'file.mid', s.render;\n```\n\n## Versioning\n\nMIDI::Make uses [Semantic Versioning](https://semver.org).\n\n## Installation\n\nYou can install MIDI::Make using [Zef](https://github.com/ugexe/zef).\n\n```\n➤ zef install MIDI::Make\n```\n\n## Import\n\n```raku\nuse MIDI::Make;\n```\n\n## Usage\n\nMIDI::Make works by creating the Song class and then populating it\nwith zero or more tracks created using the Track class. The resulting\nMIDI information can be outputed using the Song class's render method.\n\n## The Song class\n\nThe Song class is used to store and modify MIDI information in order\nto create a MIDI file. It has some optional parameters, the add-track\nmethod to add tracks, and the render method to output the MIDI\ninformation created up to that point.\n\n```raku\n    # Instantiating without parameters.\nmy \\s = Song.new;\n```\n\n### Parameters\n\nParameters can be set on instantiation, or anytime afterwards.\n\n#### format\n\nThe format parameter specifies the type of MIDI file format to use.\n\nIt can have three values: 0, 1, or 2. The default is 1.\n\n-  0 - All data is merged on a single track.\n-  1 - Tracks are separated, and played together.\n-  2 - Tracks are separated, and played one after the other.\n\n```raku\n    # Set on instantiation.\nmy \\s = Song.new(:format(0));\n```\n\n```raku\n    # Set after instantiation.\nmy \\s = Song.new;\ns.format: 0;\n```\n\n#### time-division\n\nThe time-division parameter defines how MIDI time will be divided.\n\nIt can have two values: quarter for quarter notes, and frame. The\ndefault is quarter.\n\n```raku\n    # Set on instantiation.\nmy \\s = Song.new(:time-division('frame'));\n```\n\n```raku\n    # Set after instantiation.\nmy \\s = Song.new;\ns.time-division: 'frame';\n```\n\n#### PPQ (pulses per quarter note)\n\nThe PPQ parameter sets the pulses per quarter note of the\ntime-division parameter when the latter is set to quarter. If\ntime-division is set to frame, PPQ is ignored.\n\nThe PPQ value is from 0 to 32767. The default is 48.\n\n```raku\n    # Set on instantiation.\nmy \\s = Song.new(:PPQ(96));\n```\n\n```raku\n    # Set after instantiation.\nmy \\s = Song.new;\ns.PPQ: 96;\n```\n\n#### FPS (frames per second)\n\nThe FPS parameter sets the frames per second of the time-division\nparameter when the latter is set to frame. If time-division is set to\nquarter, FPS is ignored.\n\nFPS can have four values: 24, 25, 29.97, or 30. The default is 24.\n\n```raku\n    # Set on instantiation.\nmy \\s = Song.new(:time-division('frame'), :FPS(30));\n```\n\n```raku\n    # Set after instantiation.\nmy \\s = Song.new;\ns.time-division: 'frame';\ns.FPS: 30;\n```\n\n#### PPF (pulses per frame)\n\nThe PPF parameter sets the pulses per frame of the time-division\nparameter when the latter is set to frame. If time-division is set to\nquarter, PPF is ignored.\n\nThe PPF value is from 0 to 255. The default is 4.\n\n```raku\n    # Set on instantiation.\nmy \\s = Song.new(:time-division('frame'), :PPF(8));\n```\n\n```raku\n    # Set after instantiation.\nmy \\s = Song.new;\ns.time-division: 'frame';\ns.PPF: 8;\n```\n\n### Methods\n\n#### add-track\n\nThe add-track method accepts a rendered track, and adds it to the Song\nclass.\n\n```raku\n    # Create a track.\nmy \\t = Track.new;\nt.note-on:    60;\nt.delta-time:     100;\nt.note-off:   60;\n\n    # Add it to the Song class.\nmy \\s = Song.new;\ns.add-track(t.render);\n```\n\n#### render\n\nThe render method renders the MIDI file information gathered up to\nthat point.\n\n```raku\nmy \\s = Song.new;\nsay s.render;\n```\n\n## Operators\n\nMIDI::Make creates two operators that serve as helpers for the Track\nclass described below.\n\n### ♩\n\nThe quarter notes per minute operator transforms quarter notes per\nminute to microseconds per quarter note.\n\nThis permits specifying tempo in a musical human-readable way.\n\n```raku\n    # 60 QPM using microseconds per quarter note.\nmy \\t = Track.new;\nt.tempo: 1000000;\n\n    # 60 QPM using the MIDI::Make operator.\nmy \\t = Track.new;\nt.tempo: ♩60;\n```\n\n### \\\n\nThe time-signature operator is used to specify a time-signature for\nthe Track class's time-signature method.\n\n```raku\nmy \\t = Track.new;\nt.time-signature: 3\\8;\n```\n\n## The Track class\n\nThe Track class is used to create a MIDI track which can then be added\nto the Song class.\n\n```raku\n    # Instantiating without parameters.\nmy \\t = Track.new;\n```\n\n### Parameters\n\nParameters can be set on instantiation, or anytime afterwards.\n\n#### copyright\n\nThe copyright parameter lets you set the MIDI file's copyright using\nASCII characters.\n\nNote: This copyright is usually placed at time 0 of the first track\nin the sequence.\n\n```raku\n    # Set on instantiation.\nmy \\t = Track.new(:copyright('c 2022 anonymous'));\n```\n\n```raku\n    # Set after instantiation.\nmy \\t = Track.new;\nt.copyright: 'c 2022 anonymous';\n```\n\n#### name\n\nThe name parameter lets you set the track's name using\nASCII characters.\n\n```raku\n    # Set on instantiation.\nmy \\t = Track.new(:name('melody'));\n```\n\n```raku\n    # Set after instantiation.\nmy \\t = Track.new;\nt.name: 'melody';\n```\n\n#### delta-time\n\nDelta time sets the time in MIDI pulses between MIDI events.\n\nThe delta-time value is from O to 268435455. The default is 0.\n\nNote: Although it's possible to instantiate delta-time to a value\nother than 0, usually you will start a MIDI file with a MIDI event,\nand not a period of time.\n\n```raku\n    # Set on instantiation.\nmy \\t = Track.new(:delta-time(100));\n```\n\n```raku\n    # Set after instantiation.\nmy \\t = Track.new;\nt.delta-time: 100;\n```\n\nDelta-time is automatically set to 0 after each of the MIDI events\nimplemented in the Track class. This is done so that you can enter\nmany MIDI events consecutively before setting a new delta-time.\n\n```raku\nmy \\t = Track.new;\nt.note-on:    60;\nt.delta-time:     100; # Wait 100 MIDI pulses before following events.\nt.note-off:   60;\nt.note-on:    62;\nt.note-on:    64;\nt.delta-time:     200; # Wait 200 MIDI pulses before following events.\nt.note-off:   62;\nt.note-off:   64;\n```\n\n#### channel\n\nChannel sets the MIDI channel to use.\n\nThe channel value is from 0 to 15. The default is 0.\n\n```raku\n    # Set on instantiation.\nmy \\t = Track.new(:channel(1));\n```\n\n```raku\n    # Set after instantiation.\nmy \\t = Track.new;\nt.channel: 1;\n```\n\n#### velocity-off\n\nvelocity-off sets the note-off velocity.\n\nThe velocity-off value is from 0 to 127. The default is 0.\n\nNote: A velocity for a note-off seems weird, but it can change the\nsound on certain instruments like an organ on which notes can be\ndepressed at different speeds.\n\n```raku\n    # Set on instantiation.\nmy \\t = Track.new(:velocity-off(10));\n```\n\n```raku\n    # Set after instantiation.\nmy \\t = Track.new;\nt.velocity-off: 10;\n```\n\n#### velocity-on\n\nvelocity-on sets the note-on velocity.\n\nThe velocity-on value is from 0 to 127. The default is 0.\n\n```raku\n    # Set on instantiation.\nmy \\t = Track.new(:velocity-on(60));\n```\n\n```raku\n    # Set after instantiation.\nmy \\t = Track.new;\nt.velocity-on: 60;\n```\n\n### Methods\n\n#### text\n\nThe text method adds any type of text to a track.\n\n```raku\nmy \\t = Track.new;\nt.text: 'Lorem ipsum dolor sit amet.';\n```\n\n#### instrument\n\nThe instrument method lets you set the track's instrument using\nASCII characters.\n\n```raku\nmy \\t = Track.new;\nt.instrument: 'piano';\n```\n\n#### lyric\n\nThe lyric method adds a lyric anywhere on the track.\n\n```raku\nmy \\t = Track.new;\nt.lyric: 'one';\n```\n\n#### marker\n\nThe marker method allows you to mark the beginning of important\nsequences in a track. E.g. section I, section II, outro, etc.\n\n```raku\nmy \\t = Track.new;\nt.marker: 'section I';\n```\n\n#### cue\n\nThe cue method adds a cue anywhere on the track.\n\n```raku\nmy \\t = Track.new;\nt.cue: 'door slam';\n```\n\n#### program-name\n\nThe program-name method adds a program name anywhere on the track.\n\n```raku\nmy \\t = Track.new;\nt.program-name: 'electric piano';\n```\n\n#### port\n\nThe port method adds a MIDI port name anywhere on the track.\n\n```raku\nmy \\t = Track.new;\nt.port: 'MIDI Out 1';\n```\n\n#### tempo\n\nThe tempo method sets the MIDI tempo. It accepts one argument: The\ntempo in microseconds per quarter note. You can either set it with a\nvalue from 0 to 16777215, or use the quarter notes per minute operator\ndefined earlier in this file. The default value is 500000 which is\nequivalent to a tempo of 120 quarter notes per minute.\n\n```raku\nmy \\t = Track.new;\nt.tempo: 1000000; # Set the tempo to 60 quarter notes per minute.\nt.tempo: ♩120;    # Set the tempo to 120 quarter notes per minute.\n```\n\n#### time-signature\n\nThe time-signature method sets the MIDI time-signature. It accepts\nthree optional arguments:\n\n1. The time-signature set using the time-signature operator defined\n   earlier in this file. The default is 4\\4.\n\n2. The pulses per metronome click (PPMC). This value can be from\n   0 to 255. The default is 24.\n\n3. 32nds per quarter note. This value can be from 0 to 255.\n   The default is 8.\n\n```raku\nmy \\t = Track.new;\nt.time-signature: 3\\4;\nt.time-signature: 4\\4, 48;\nt.time-signature: 2\\8, 32, 12;\n```\n\n#### key-signature\n\nThe key-signature method sets the key-signature of the piece. It\naccepts two optional arguments:\n\n1. The key which is defined as the number of accidentals. This value\n   can be from -7 to 7 where -1 to -7 is the number of flats, and\n   1 to 7 is the number of sharps. It is also possible to use\n   1♭, 2♭ ... 7♭ instead of -1 to -7 for flats, and 1♯, 2♯ ... 7♯\n   instead of 1 to 7 for sharps. You can also use 0♭ or 0♯ instead of\n   0.\n\n2. The mode which is either 0 for major, or 1 for minor. MIDI::Make\n   provides you with the Modes enums \u003cmajor minor\u003e that you may use\n   instead of 0 and 1.\n\n```raku\nmy \\t = Track.new;\nt.key-signature: -2, 1;     # G minor\nt.key-signature: 2♭, 1;     # G minor with unicode number of flats.\nt.key-signature: 2♭, minor: # G minor with Modes enum.\n```\n\n#### note-off\n\nThe note-off method creates a note off. It accepts two arguments: The\nnote number from 0 to 127 (required), and the velocity-off from\n0 to 127 (optional). The default velocity-off is the one set by\nthe velocity-off parameter.\n\n```raku\nmy \\t = Track.new;\nt.note-off: 60;     # velocity-off == 0\nt.note-off: 62, 10; # velocity-off == 10\nt.note-off: 64;     # velocity-off == 0\nt.velocity-off: 10;\nt.note-off: 66;     # velocity-off == 10\n```\n\n#### note-on\n\nThe note-on method creates a note on. It accepts two arguments: The\nnote number from 0 to 127 (required), and the velocity-on from\n0 to 127 (optional). The default velocity-on is the one set by\nthe velocity-on parameter.\n\n```raku\nmy \\t = Track.new;\nt.note-on: 60;      # velocity-on == 127\nt.note-on: 62, 100; # velocity-on == 100\nt.note-on: 64;      # velocity-on == 127\nt.velocity-on: 100;\nt.note-on: 66;      # velocity-on == 100\n```\n\n#### aftertouch\n\nThe aftertouch method is a multi method for both note aftertouch, and\nchannel aftertouch.\n\nFor a note aftertouch, you provide two arguments: The aftertouch\namount from 0 to 127, and the note number from 0 to 127.\n\nFor a channel aftertouch, you simply provide the aftertouch amount.\n\n```raku\nmy \\t = Track.new;\nt.aftertouch: 100, 53; # note aftertouch\nt.aftertouch: 100;     # channel aftertouch\n```\n\n#### controller\n\nThe controller method is used to set a controller MIDI event.\n\nThe first argument is the controller number from 0 to 127. The second\nargument is the controller value also from 0 to 127.\n\n```raku\nmy \\t = Track.new;\nt.controller: 8, 100; # balance_MSB of 100.\n```\n\nYou can also call specific controllers using the following methods:\n\n| #       | method                 | value   | use         | definition                             |\n|:--------|:-----------------------|:--------|:------------|:---------------------------------------|\n| 0       | bank-select_MSB        | 0-127   | MSB         | Change patch banks.                    |\n| 1       | modulation_MSB         | 0-127   | MSB         | Create a vibrato effect.               |\n| 2       | breath_MSB             | 0-127   | MSB         | Breath controller.                     |\n| 3       | -                      | -       | -           | -                                      |\n| 4       | foot-pedal_MSB         | 0-127   | MSB         | Foot pedal data.                       |\n| 5       | portamento-time_MSB    | 0-127   | MSB         | Control portamento rate.               |\n| 6       | data-entry_MSB         | 0-127   | MSB         | Control value for NRPN/RPN parameters. |\n| 7       | channel-volume_MSB     | 0-127   | MSB         | Control the channel volume.            |\n| 8       | balance_MSB            | 0-127   | MSB         | Control left/right balance for stereo. |\n| 9       | -                      | -       | -           | -                                      |\n| 10      | pan_MSB                | 0-127   | MSB         | Control left/right balance for mono.   |\n| 11      | expression_MSB         | 0-127   | MSB         | Expression is a percentage of volume.  |\n| 12      | effect-control_1_MSB   | 0-127   | MSB         | Control an effect parameter.           |\n| 13      | effect-control_2_MSB   | 0-127   | MSB         | Control an effect parameter.           |\n| 14-15   | -                      | -       | -           | -                                      |\n| 16      | general-control_1_MSB  | 0-127   | MSB         | General purpose controller.            |\n| 17      | general-control_2_MSB  | 0-127   | MSB         | General purpose controller.            |\n| 18      | general-control_3_MSB  | 0-127   | MSB         | General purpose controller.            |\n| 19      | general-control_4_MSB  | 0-127   | MSB         | General purpose controller.            |\n| 20-31   | -                      | -       | -           | -                                      |\n| 32      | bank-select_LSB        | 0-127   | LSB         | Change patch banks.                    |\n| 33      | modulation_LSB         | 0-127   | LSB         | Create a vibrato effect.               |\n| 34      | breath_LSB             | 0-127   | LSB         | Breath controller.                     |\n| 35      | -                      | -       | -           | -                                      |\n| 36      | foot-pedal_LSB         | 0-127   | LSB         | Foot pedal data.                       |\n| 37      | portamento-time_LSB    | 0-127   | LSB         | Control portamento rate.               |\n| 38      | data-entry_LSB         | 0-127   | LSB         | Control value for NRPN/RPN parameters. |\n| 39      | channel-volume_LSB     | 0-127   | LSB         | Control the channel volume.            |\n| 40      | balance_LSB            | 0-127   | LSB         | Control left/right balance for stereo. |\n| 41      | -                      | -       | -           | -                                      |\n| 42      | pan_LSB                | 0-127   | LSB         | Control left/right balance for mono.   |\n| 43      | expression_LSB         | 0-127   | LSB         | Expression is a percentage of volume.  |\n| 44      | effect-control_1_LSB   | 0-127   | LSB         | Control an effect parameter.           |\n| 45      | effect-control_2_LSB   | 0-127   | LSB         | Control an effect parameter.           |\n| 46-47   | -                      | -       | -           | -                                      |\n| 48      | general-control_1_LSB  | 0-127   | LSB         | General purpose controller.            |\n| 49      | general-control_2_LSB  | 0-127   | LSB         | General purpose controller.            |\n| 50      | general-control_3_LSB  | 0-127   | LSB         | General purpose controller.            |\n| 51      | general-control_4_LSB  | 0-127   | LSB         | General purpose controller.            |\n| 52-63   | -                      | -       | -           | -                                      |\n| 64      | hold_1-pedal           | \u003c63=off | 64\u003e=0n      | Sustain pedal 1 on/off switch.         |\n| 65      | portamento             | \u003c63=off | 64\u003e=0n      | Portmento on/off switch.               |\n| 66      | sostenuto              | \u003c63=off | 64\u003e=0n      | Sostenuto on/off switch.               |\n| 67      | soft-pedal             | \u003c63=off | 64\u003e=0n      | Soft pedal on/off switch.              |\n| 68      | legato-footswitch      | \u003c63=off | 64\u003e=0n      | Legato on/off switch.                  |\n| 69      | hold_2-pedal           | \u003c63=off | 64\u003e=0n      | Sustain pedal 2 on/off switch.         |\n| 70      | sound-control_1        | 0-127   | LSB         | Sound control. (variation)             |\n| 71      | sound-control_2        | 0-127   | LSB         | Sound control. (resonance)             |\n| 72      | sound-control_3        | 0-127   | LSB         | Sound control. (release time)          |\n| 73      | sound-control_4        | 0-127   | LSB         | Sound control. (attack time)           |\n| 74      | sound-control_5        | 0-127   | LSB         | Sound control. (cutoff frequency)      |\n| 75      | sound-control_6        | 0-127   | LSB         | Generic sound control.                 |\n| 76      | sound-control_7        | 0-127   | LSB         | Generic sound control.                 |\n| 77      | sound-control_8        | 0-127   | LSB         | Generic sound control.                 |\n| 78      | sound-control_9        | 0-127   | LSB         | Generic sound control.                 |\n| 79      | sound-control_10       | 0-127   | LSB         | Generic sound control.                 |\n| 80      | general-control_5      | 0-127   | LSB         | Generic or decay on/off switch.        |\n| 81      | general-control_6      | 0-127   | LSB         | Generic or hi-pass on/off switch.      |\n| 82      | general-control_7      | 0-127   | LSB         | Generic on/off switch.                 |\n| 83      | general-control_8      | 0-127   | LSB         | Generic on/off switch.                 |\n| 84      | portamento-control     | 0-127   | note        | Control portamento amount.             |\n| 85-87   | -                      | -       | -           | -                                      |\n| 88      | hi-res-velocity-prefix | 0-127   | MSB         | Extend the range of velocities.        |\n| 89-90   | -                      | -       | -           | -                                      |\n| 91      | effect_1-depth         | 0-127   | LSB         | Effect control. (reverb)               |\n| 92      | effect_2-depth         | 0-127   | LSB         | Effect control. (tremolo)              |\n| 93      | effect_3-depth         | 0-127   | LSB         | Effect control. (chorus)               |\n| 94      | effect_4-depth         | 0-127   | LSB         | Effect control. (detune)               |\n| 95      | effect_5-depth         | 0-127   | LSB         | Effect control. (phaser)               |\n| 96      | data-increment         | N/A     | N/A         | Increment data for NRPN/RPN messages.  |\n| 97      | data-decrement         | N/A     | N/A         | Decrement data for NRPN/RPN messages.  |\n| 98      | NRPN_LSB               | 0-127   | LSB         | NRPN for controllers: 6, 38, 96, 97    |\n| 99      | NRPN_MSB               | 0-127   | MSB         | NRPN for controllers: 6, 38, 96, 97    |\n| 100     | RPN_LSB                | 0-127   | LSB         | RPN for controllers: 6, 38, 96, 97     |\n| 101     | RPN_MSB                | 0-127   | MSB         | RPN for controllers: 6, 38, 96, 97     |\n| 102-119 | -                      | -       | -           | -                                      |\n| 120     | all-sounds-off         | 0       | -           | Mute all sounds.                       |\n| 121     | reset-controllers      | 0       | -           | Reset all controllers to defaults.     |\n| 122     | local-switch           | 0=off   | 127=on      | MIDI workstation on/off switch.        |\n| 123     | all-notes-off          | 0       | -           | Mute all sounding notes.               |\n| 124     | omni-mode-off          | 0       | -           | Set to omni mode off.                  |\n| 125     | omni-mode-on           | 0       | -           | Set to omni mode on.                   |\n| 126     | mono-mode              | 0-127   | num-channel | Set device mode to monophonic.         |\n| 127     | poly-mode              | 0       | -           | Set device mode to polyphonic.         |\n\nEx:\n\n```raku\nmy \\t = Track.new;\nt.pan_MSB: 64;\n```\n\nIt's also possible to call the MSB and LSB counterparts (controllers\nin the range of 0-63) with one function. This permits specifying a\nvalue between 0 and 16383 in one go.\n\n| method            | value   | definition                             |\n|:------------------|:--------|:---------------------------------------|\n| bank-select       | 0-16383 | Change patch banks.                    |\n| modulation        | 0-16383 | Create a vibrato effect.               |\n| breath            | 0-16383 | Breath controller.                     |\n| foot-pedal        | 0-16383 | Foot pedal data.                       |\n| portamento-time   | 0-16383 | Control portamento rate.               |\n| data-entry        | 0-16383 | Control value for NRPN/RPN parameters. |\n| channel-volume    | 0-16383 | Control the channel volume.            |\n| balance           | 0-16383 | Control left/right balance for stereo. |\n| pan               | 0-16383 | Control left/right balance for mono.   |\n| expression        | 0-16383 | Expression is a percentage of volume.  |\n| effect-control_1  | 0-16383 | Control an effect parameter.           |\n| effect-control_2  | 0-16383 | Control an effect parameter.           |\n| general-control_1 | 0-16383 | General purpose controller.            |\n| general-control_2 | 0-16383 | General purpose controller.            |\n| general-control_3 | 0-16383 | General purpose controller.            |\n| general-control_4 | 0-16383 | General purpose controller.            |\n\nEx:\n\n```raku\nmy \\t = Track.new;\nt.pan: 3489;\n```\n\n#### program-change\n\nChanges the program of the current channel.\n\nIt has one argument, the program number from 0 to 127.\n\n```raku\nmy \\t = Track.new;\nt.program-change: 100; # Effect 5 in General MIDI.\n```\n\n#### pitch-bend\n\nThe pitch-bend method applies a pitch bend to the current channel. It\ntakes an optional argument from 0 to 16383. Values below 8192 bend the\npitch downwards, and values above 8192 bend the pitch upwards. If no\nargument is given, the pitch bend returns to its default value of 8192\nwhich is no pitch bend. The pitch range may vary from instrument to\ninstrument, but is usually +/- 2 semitones.\n\n```raku\nmy \\t = Track.new;\nt.pitch-bend: 0; # Bends the pitch as low as possible.\nt.pitch-bend;    # Removes pitch bend by applying the default: 8192.\n```\n\n#### sysex\n\nThe sysex method implements a simple sysex message. It takes a list\nof dataBytes, and surrounds them with sysex start and end bytes:\nF0 \u003cdataBytes\u003e F7\n\n```raku\nmy \\t = Track.new;\nt.sysex: \u003c0A 29 1E\u003e;\n```\n\n#### add-bytes\n\nThe add-bytes method lets you add arbitrary bytes to the track. Unlike\nother methods, it does not add delta-time nor does it reset delta-time\nto 0. add-bytes is mostly useful for testing purposes.\n\n```raku\nmy \\t = Track.new;\nt.add-bytes: \u003c00 F0 0A 29 1E F7\u003e;\n```\n\n#### render\n\nThe render method renders the MIDI track information gathered up to\nthat point. It is used to pass the track's MIDI data to the Song\nclass.\n\n```raku\nmy \\t = Track.new;\nt.note-on:    60;\nt.delta-time:     128;\nt.note-off:   60;\n\nmy \\s = Song.new;\ns.add-track(t.render);\n```\n\n## Running Tests\n\nTo run all tests, simply use the following command in the root of\nMIDI::Make.\n\n```\n➤ raku -Ilib t/all.rakutest\n```\n\nAlternatively, you can use\n[Test::Selector](https://raku.land/zef:lucs/Test::Selector) to\nselectively run tests.\n\n```\n➤ tsel     :: Run all tests.\n➤ tsel s1  :: Run the s1 test.\n➤ tsel s\\* :: Run all s tests.\n```\n\n## Resources\n\n- [Official MIDI Specification](https://www.midi.org/specifications)\n- [One-pager MIDI Specification](https://github.com/colxi/midi-parser-js/wiki/MIDI-File-Format-Specifications)\n- [MIDI Files Specification](http://www.somascape.org/midi/tech/mfile.html)\n- [MIDI Beat Time Considerations](https://majicdesigns.github.io/MD_MIDIFile/page_timing.html)\n- [MIDI Timing](https://paxstellar.fr/2020/09/11/midi-timing)\n\n## License\n\nMIT\\\nCopyright 2022 Pierre-Emmanuel Lévesque\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpelevesque%2FMIDI-Make","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpelevesque%2FMIDI-Make","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpelevesque%2FMIDI-Make/lists"}