{"id":15714143,"url":"https://github.com/nbw/opz","last_synced_at":"2025-05-05T21:44:27.722Z","repository":{"id":47958098,"uuid":"309095902","full_name":"nbw/opz","owner":"nbw","description":"MIDI parser for OP-Z sequencer by teenage engineering","archived":false,"fork":false,"pushed_at":"2021-05-14T03:20:25.000Z","size":99,"stargazers_count":61,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-31T00:01:50.440Z","etag":null,"topics":["javascript","midi","opz"],"latest_commit_sha":null,"homepage":"https://opz.nathanwillson.com","language":"JavaScript","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/nbw.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":"2020-11-01T12:56:24.000Z","updated_at":"2025-03-19T19:18:56.000Z","dependencies_parsed_at":"2022-08-12T15:10:37.521Z","dependency_job_id":null,"html_url":"https://github.com/nbw/opz","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fopz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fopz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fopz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fopz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nbw","download_url":"https://codeload.github.com/nbw/opz/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252582245,"owners_count":21771634,"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":["javascript","midi","opz"],"created_at":"2024-10-03T21:34:52.665Z","updated_at":"2025-05-05T21:44:27.661Z","avatar_url":"https://github.com/nbw.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OPZ.js\n\nParser for midi received from [teenage engineering's OP-Z sequencer](https://teenage.engineering/products/op-z).\n\nDecodes events from the [Web MIDI API](https://www.w3.org/TR/webmidi/). Also refer to [Mozilla's documentation](https://developer.mozilla.org/en-US/docs/Web/API/MIDIAccess)\n\n[TEENAGE ENGINEERING OPZ MIDI DOCS](https://teenage.engineering/guides/op-z/midi)\n\n**Assumes you have an OP-Z.**\n\n![op-z](https://teenage.engineering/_img/5bc066ec1a41630004a9ce50_512.png)\n\n## Table of Contents\n\n* [Examples](#examples)\n* [Starter](#starter)\n* [Installation](#installation)\n  * [Install with NPM](#install-with-npm)\n  * [Install for Browser](#install-for-browser)\n* [Documentation](#documentation)\n  * [Functions](#functions)\n  * [Table of Values](#table-of-values)\n    * [Control values](#control-values)\n    * [Buttons that do NOT send MIDI](#buttons-that-do-not-send-midi)\n* [Usage](#usage)\n  * [OP\\-Z Setup](#op-z-setup)\n  * [Code Examples](#code-examples)\n    * [Node Example](#node-example)\n    * [Browser Example](#browser-example)\n* [Notes](#notes)\n  * [Step components](#step-components)\n* [Contributions](#contributions)\n* [Contact](#contact)\n* [Credit](#credit)\n* [License](#license)\n\n\n## Examples\n\n1. [MIDI TETRIS](http://tetris.nathanwillson.com/): (https://github.com/nbw/tetris)\n\n1. [SHAPES](http://shapes.nathanwillson.com/): (https://github.com/nbw/shapes)\n\n1. [SINUSOID](http://sinusoid.nathanwillson.com/): (https://github.com/nbw/sinusoid)\n\n1. [SKETCH](http://sketch.nathanwillson.com/): (https://github.com/nbw/sketch)\n\n## Starter\n\n[OP-Z Starter Repo](https://github.com/nbw/opz-starter)\n\nUseful just as a reference to get started.\n\n## Installation\n\n### Install with NPM\n\n```\nnpm install opzjs\n```\n\n### Install for Browser\n\n**Option 1:** Download  [opz.js](/opz.js) from dist folder.\n\n```\n\u003cscript src=\"[path to opz.js file]\u003e\u003cscript\u003e\n```\n\n**Option 2:** Build distribution.\n  1. Clone repo\n  2. `npm run build`\n  3. Copy new file saved in dist\n\n  Note: run `Make install` if you're missing js-yaml\n\n```\n\u003cscript src=\"[path to opz.js file]\u003e\u003cscript\u003e\n```\n\n## Documentation\n### Functions\n\n* `decode(data)`: data is an array of integer values (ex. [252], [123, 45, 0], etc.)\n\nReturns an Object.\n```\n{\n  track: ...,\n  action: ...,\n  velocity: ...,\n  value: ...\n}\n```\n\n* `velocity (data)`: data is an array of integer values (ex. [252], [123,45,0], etc.)\n\nReturns an Integer between 0 to 127.\n\n### Table of Values\n\n| field                     | value                                                                                                        |\n|---------------------------|--------------------------------------------------------------------------------------------------------------|\n| track                     | kick, snare, perc, sample, bass, lead, arp, chord,  fx1, fx2, tape, master,  perform, module, lights, motion |\n| action                    | keys, dial, pitch bend                                                                                       |\n| velocity                  | 0-127                                                                                                        |\n| value (action=key)        | ``` { value: 101   note: F } ```                                                                             |\n| value (action=dial)       | ``` { dial: 0, dialColor: \"green\", page: 3, pageColor: \"yellow\" }```                                         |\n| value (action=pitch_bend) | ``` { absolute: 0, // 0 - 128   relative: 64, // 0 - 128 } ```                                               |\n\n#### Control values\n\n| field        | value              |\n|--------------|--------------------|\n| track        | clock, start, stop |\n| action       | clock, start, stop |                                                                                       |\n| velocity     | -1                 |\n| value        | ``` {} ```         |\n\n#### Buttons that do NOT send MIDI\n\nThe following buttons do not send midi. However, a number of them can be \"inferred\" through the context\nof the keyboard key or the dials. Example, pressing the kick track button on it's own will not send midi\nbut pressing a keyboard key while using the kick track will (and then there's enough information to\nglean that it was a kick).\n\n* track buttons\n* play\n* stop\n* +/- octave shift\n* project, mixer, tempo, screen\n\n#### Dial kill (stop button)\n\nWhen the OP-Z is playing and the stop key is pressed [a series of midi notes](https://github.com/nbw/opz/issues/1) are sent to quiet the dials. As it's unclear\nwhich page (or color) these messages apply to, they've been labeled as \"kill\".\n\nExample:\n```js\n{\n  track: \"kick\",\n  action: \"dial\",\n  velocity: 0,\n  value: {\n    dial: 2\n    dialColor: \"kill\"\n    page: 30\n    pageColor: \"kill\"\n  }\n}\n```\n\n## Usage\n### OP-Z Setup\n\n1. Plug OP-Z into computer\n2. Ensure \"MIDI OUT ENABLE\" is ON (use the app or refer to teenage engineering docs)\n\n### Code Examples\n#### Node Example\n\nThe following example uses [justinlatimer's node-midi library](https://github.com/justinlatimer/node-midi). Comments have been removed. Please refer to the docs for more information.\n\n```javascript\nconst midi = require('midi');\nconst opz = require('opzjs');\n\n// Set up a new input.\nconst input = new midi.Input();\n\n// Count the available input ports.\nconsole.log(\"port count: \", input.getPortCount());\n\n// Get the name of a specified input port.\nif (input.getPortCount() \u003e 0){\n  console.log(input.getPortName(0));\n  // Configure a callback.\n  input.on('message', (deltaTime, message) =\u003e {\n    console.log(`m: ${message} d: ${deltaTime}`);\n    console.log(opz.decode(message)); // \u003c--------- OPZ.\n    /*\n    {\n      track: \"kick\",\n      action: \"keys\",\n      velocity: 100,\n      value: {\n        value: 101,\n        note: \"F\"\n      }\n    }\n    */\n  });\n\n  // Open the first available input port.\n  input.openPort(0);\n\n  // Close the port when done.\n  setTimeout(function() {\n    input.closePort();\n  }, 100000);\n}\n```\n\n#### Browser Example\n\n1. Setup/listen for a midi input\n\nThe following listens for midi input from ALL input sources. If you want to specifically filter midi from the OP-Z then look into `midiAccess.inputs` or find an example online.\n\nAssumes you've put opz.js in the same folder.\n\n```html\n\u003cscript src=\"/opz.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n\nif (navigator.requestMIDIAccess) {\n    console.log('This browser supports WebMIDI!');\n} else {\n    console.log('WebMIDI is not supported in this browser.');\n}\n\nnavigator.requestMIDIAccess()\n    .then(onMIDISuccess, onMIDIFailure);\n\nfunction onMIDIFailure() {\n    console.log('Could not access your MIDI devices.');\n}\n\nfunction onMIDISuccess(midiAccess) {\n  // midiAccess.data is an array of values [255], [120,0,100], etc.\n  const input = OPZ.decode(midiAccess.data)\n  /*\n    Example:\n    input =  {\n      track: \"kick\",\n      action: \"keys\",\n      velocity: 100,\n      value: {\n        value: 101,\n        note: \"F\"\n      }\n    }\n  */\n}\n\u003c/script\u003e\n```\n\n## Notes\n### Step components\n\nStep components are not sent explicitly as midi notes. Though, for example, in the case of trippling a note (x2 component) three notes are sent.\n\n## Contributions\n\nContributions or suggestions are welcome.\n\n## Contact\n\n[@nathanwillson](https://twitter.com/nathanwillson)\n\n## Credit\n\nOP-Z photo from teenage engineering's website.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnbw%2Fopz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnbw%2Fopz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnbw%2Fopz/lists"}