├── .github └── workflows │ └── test.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── LICENSE ├── README.md ├── config ├── eslint │ ├── config.json │ ├── src.json │ └── test.json ├── karma │ └── config-unit.js ├── lint-staged │ └── config.json ├── prettier │ └── config.json ├── rollup │ └── bundle.mjs ├── tslint │ └── src.json └── webpack │ ├── worker-es2019.js │ └── worker-es5.mjs ├── package-lock.json ├── package.json ├── src ├── module.ts ├── tsconfig.json └── worker │ └── worker.ts └── test ├── fixtures ├── 26-2.json ├── 26-2.mid ├── 98137.json ├── 98137.mid ├── A_F_NO7_01.json ├── A_F_NO7_01.mid ├── MIDIOkFormat1-lyrics.json ├── MIDIOkFormat1-lyrics.mid ├── MIDIOkFormat2.json ├── MIDIOkFormat2.mid ├── MorozovS07.json ├── MorozovS07.mid ├── SubTractor 1.json ├── SubTractor 1.mid ├── SubTractor 2.json ├── SubTractor 2.mid ├── TheEntertainer.json ├── TheEntertainer.mid ├── because.json ├── because.mid ├── californication.json ├── californication.mid ├── minute_waltz.json ├── minute_waltz.mid ├── rachmaninov3.json ├── rachmaninov3.mid ├── scale.json ├── scale.mid ├── test.json ├── test.mid ├── test8bars.json └── test8bars.mid ├── helper ├── filenames.js └── load-fixture.js └── unit └── module.js /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | matrix: 17 | node-version: [20.x] 18 | target: [chrome, safari] 19 | type: [unit] 20 | max-parallel: 3 21 | 22 | steps: 23 | - name: Checkout repository 24 | uses: actions/checkout@v4 25 | 26 | - name: Install Node.js ${{ matrix.node-version }} 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: ${{ matrix.node-version }} 30 | 31 | - name: Cache node modules 32 | uses: actions/cache@v4 33 | with: 34 | path: ~/.npm 35 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 36 | restore-keys: | 37 | ${{ runner.os }}-node- 38 | 39 | - name: Install dependencies 40 | run: npm ci 41 | 42 | - env: 43 | SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} 44 | SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} 45 | TARGET: ${{ matrix.target }} 46 | TYPE: ${{ matrix.type }} 47 | name: Run ${{ matrix.type }} tests 48 | run: npm test 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | node_modules/ 3 | /build/ 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | commitlint --edit --extends @commitlint/config-angular 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | lint-staged --config config/lint-staged/config.json && npm run lint 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Christoph Guttandin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # json-midi-encoder 2 | 3 | **This module encodes a JSON representation of MIDI data into a binary MIDI file.** 4 | 5 | [![version](https://img.shields.io/npm/v/json-midi-encoder.svg?style=flat-square)](https://www.npmjs.com/package/json-midi-encoder) 6 | 7 | By using this module it is possible to encode a JSON representation of a MIDI file into its binary 8 | counterpart. That JSON representation can either be created from scratch or produced by parsing an 9 | existing file with the [midi-json-parser](https://github.com/chrisguttandin/midi-json-parser). 10 | 11 | ## Usage 12 | 13 | This module is distributed as package on [npm](https://www.npmjs.com/package/json-midi-encoder). It 14 | can be installed by running the following command: 15 | 16 | ```shell 17 | npm install json-midi-encoder 18 | ``` 19 | 20 | The only exported function is called `encode()`. It expects to receive a JSON representation as its 21 | only parameter. It returns a Promise which hopefully resolves with an ArrayBuffer containing the 22 | binary MIDI file. Here is a little example. 23 | 24 | ```js 25 | import { encode } from 'json-midi-encoder'; 26 | 27 | const json = { 28 | division: 480, 29 | format: 1, 30 | tracks: [ 31 | [ 32 | { 33 | delta: 0, 34 | trackName: 'example' 35 | }, 36 | // ... there are probably more events ... 37 | { 38 | delta: 0, 39 | endOfTrack: true 40 | } 41 | ] 42 | // ... maybe there are more tracks ... 43 | ] 44 | }; 45 | 46 | encode(json).then((midiFile) => { 47 | // midiFile is an ArrayBuffer containing the binary data. 48 | }); 49 | ``` 50 | 51 | To see what kind of events this module can handle, you may want to have a look at the 52 | [JSON files](https://github.com/chrisguttandin/json-midi-encoder/tree/master/test/fixtures) used 53 | to test this module. There is also a 54 | [TypeScript interface](https://github.com/chrisguttandin/midi-json-parser-worker/blob/master/src/interfaces/midi-file.ts) 55 | which describes the JSON representation. 56 | -------------------------------------------------------------------------------- /config/eslint/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true 4 | }, 5 | "extends": "eslint-config-holy-grail", 6 | "rules": { 7 | "no-sync": "off", 8 | "node/no-missing-require": "off" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /config/eslint/src.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "extends": "eslint-config-holy-grail" 6 | } 7 | -------------------------------------------------------------------------------- /config/eslint/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "mocha": true 5 | }, 6 | "extends": "eslint-config-holy-grail", 7 | "globals": { 8 | "expect": "readonly" 9 | }, 10 | "rules": { 11 | "no-unused-expressions": "off", 12 | "node/file-extension-in-import": "off", 13 | "node/no-missing-require": "off" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/karma/config-unit.js: -------------------------------------------------------------------------------- 1 | const { env } = require('process'); 2 | const { DefinePlugin } = require('webpack'); 3 | 4 | module.exports = (config) => { 5 | config.set({ 6 | basePath: '../../', 7 | 8 | browserDisconnectTimeout: 100000, 9 | 10 | browserNoActivityTimeout: 100000, 11 | 12 | client: { 13 | mocha: { 14 | bail: true, 15 | timeout: 20000 16 | } 17 | }, 18 | 19 | concurrency: 1, 20 | 21 | files: [ 22 | { 23 | included: false, 24 | pattern: 'src/**', 25 | served: false, 26 | watched: true 27 | }, 28 | { 29 | included: false, 30 | pattern: 'test/fixtures/**', 31 | served: true, 32 | watched: true 33 | }, 34 | 'test/unit/**/*.js' 35 | ], 36 | 37 | frameworks: ['mocha', 'sinon-chai'], 38 | 39 | preprocessors: { 40 | 'test/unit/**/*.js': 'webpack' 41 | }, 42 | 43 | reporters: ['dots'], 44 | 45 | webpack: { 46 | mode: 'development', 47 | module: { 48 | rules: [ 49 | { 50 | test: /\.ts?$/, 51 | use: { 52 | loader: 'ts-loader', 53 | options: { 54 | compilerOptions: { 55 | declaration: false, 56 | declarationMap: false 57 | } 58 | } 59 | } 60 | } 61 | ] 62 | }, 63 | plugins: [ 64 | new DefinePlugin({ 65 | 'process.env': { 66 | CI: JSON.stringify(env.CI) 67 | } 68 | }) 69 | ], 70 | resolve: { 71 | extensions: ['.js', '.ts'], 72 | fallback: { util: false } 73 | } 74 | }, 75 | 76 | webpackMiddleware: { 77 | noInfo: true 78 | } 79 | }); 80 | 81 | if (env.CI) { 82 | config.set({ 83 | browsers: 84 | env.TARGET === 'chrome' 85 | ? ['ChromeSauceLabs'] 86 | : env.TARGET === 'firefox' 87 | ? ['FirefoxSauceLabs'] 88 | : env.TARGET === 'safari' 89 | ? ['SafariSauceLabs'] 90 | : ['ChromeSauceLabs', 'FirefoxSauceLabs', 'SafariSauceLabs'], 91 | 92 | captureTimeout: 300000, 93 | 94 | customLaunchers: { 95 | ChromeSauceLabs: { 96 | base: 'SauceLabs', 97 | browserName: 'chrome', 98 | captureTimeout: 300, 99 | platform: 'macOS 12' 100 | }, 101 | FirefoxSauceLabs: { 102 | base: 'SauceLabs', 103 | browserName: 'firefox', 104 | captureTimeout: 300, 105 | geckodriverVersion: '0.30.0', 106 | platform: 'macOS 12' 107 | }, 108 | SafariSauceLabs: { 109 | base: 'SauceLabs', 110 | browserName: 'safari', 111 | captureTimeout: 300, 112 | platform: 'macOS 12' 113 | } 114 | }, 115 | 116 | sauceLabs: { 117 | recordVideo: false 118 | } 119 | }); 120 | } else { 121 | config.set({ 122 | browsers: ['ChromeCanaryHeadless', 'ChromeHeadless', 'FirefoxDeveloperHeadless', 'FirefoxHeadless', 'Safari'] 123 | }); 124 | } 125 | }; 126 | -------------------------------------------------------------------------------- /config/lint-staged/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "*": "prettier --config config/prettier/config.json --ignore-unknown --write" 3 | } 4 | -------------------------------------------------------------------------------- /config/prettier/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "printWidth": 140, 4 | "quoteProps": "consistent", 5 | "singleQuote": true, 6 | "tabWidth": 4, 7 | "trailingComma": "none" 8 | } 9 | -------------------------------------------------------------------------------- /config/rollup/bundle.mjs: -------------------------------------------------------------------------------- 1 | import { join, resolve as resolvePath } from 'path'; 2 | import { readFile, readFileSync, readlink, stat } from 'fs'; 3 | import babel from '@rollup/plugin-babel'; 4 | import { fs } from 'memfs'; 5 | import replace from '@rollup/plugin-replace'; 6 | import webpack from 'webpack'; 7 | // eslint-disable-next-line node/file-extension-in-import 8 | import webpackConfig from '../webpack/worker-es5.mjs'; 9 | 10 | const workerFile = readFileSync('src/worker/worker.ts', 'utf8'); 11 | const result = /export\sconst\sworker\s=\s`(?.*)`;/g.exec(workerFile); 12 | 13 | if (result === null) { 14 | throw new Error('The worker file could not be parsed.'); 15 | } 16 | 17 | const virtualPath = resolvePath(import.meta.dirname, '../../src/worker.js'); 18 | const workerString = result.groups.workerString; 19 | 20 | // eslint-disable-next-line import/no-default-export 21 | export default new Promise((resolve, reject) => { 22 | const compiler = webpack(webpackConfig); 23 | 24 | compiler.inputFileSystem = { 25 | readFile(path, ...args) { 26 | if (path === virtualPath) { 27 | args.pop()(null, "import 'json-midi-encoder-worker';"); 28 | 29 | return; 30 | } 31 | 32 | return readFile(path, ...args); 33 | }, 34 | readlink(path, callback) { 35 | if (path === virtualPath) { 36 | return readlink(import.meta.filename, callback); 37 | } 38 | 39 | return readlink(path, callback); 40 | }, 41 | stat(path, ...args) { 42 | if (path === virtualPath) { 43 | args.pop()(null, { 44 | isFile() { 45 | return true; 46 | } 47 | }); 48 | 49 | return; 50 | } 51 | 52 | return stat(path, ...args); 53 | } 54 | }; 55 | compiler.outputFileSystem = { ...fs, join }; 56 | compiler.run((err, stats) => { 57 | if (err !== null) { 58 | reject(err); 59 | } else if (stats.hasErrors() || stats.hasWarnings()) { 60 | reject(new Error(stats.toString({ errorDetails: true, warnings: true }))); 61 | } else { 62 | const transpiledWorkerString = fs // eslint-disable-line node/no-sync 63 | .readFileSync('/worker.js', 'utf8') 64 | .replace(/\\/g, '\\\\') 65 | .replace(/`/g, '\\`') 66 | .replace(/\${/g, '\\${'); 67 | 68 | resolve({ 69 | input: 'build/es2019/module.js', 70 | output: { 71 | file: 'build/es5/bundle.js', 72 | format: 'umd', 73 | name: 'jsonMidiEncoder' 74 | }, 75 | plugins: [ 76 | replace({ 77 | delimiters: ['`', '`'], 78 | include: 'build/es2019/worker/worker.js', 79 | values: { 80 | // V8 does only accept substrings with a maximum length of 32767 characters. Otherwise it throws a SyntaxError. 81 | [workerString.slice(0, 32767)]: `\`${transpiledWorkerString}\``, 82 | [workerString.slice(32767)]: '' 83 | } 84 | }), 85 | babel({ 86 | babelHelpers: 'runtime', 87 | exclude: 'node_modules/**', 88 | plugins: ['@babel/plugin-external-helpers', '@babel/plugin-transform-runtime'], 89 | presets: [ 90 | [ 91 | '@babel/preset-env', 92 | { 93 | modules: false 94 | } 95 | ] 96 | ] 97 | }) 98 | ] 99 | }); 100 | } 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /config/tslint/src.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint-config-holy-grail" 3 | } 4 | -------------------------------------------------------------------------------- /config/webpack/worker-es2019.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path'); 2 | const TerserPlugin = require('terser-webpack-plugin'); 3 | const { RawSource } = require('webpack-sources'); 4 | 5 | module.exports = { 6 | entry: { 7 | worker: './node_modules/json-midi-encoder-worker/build/es2019/module.js' 8 | }, 9 | mode: 'production', 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.js$/, 14 | use: { 15 | loader: 'babel-loader', 16 | options: { 17 | plugins: ['@babel/plugin-external-helpers', '@babel/plugin-transform-runtime'], 18 | presets: [ 19 | [ 20 | '@babel/preset-env', 21 | { 22 | include: ['transform-template-literals'], 23 | targets: { 24 | browsers: [ 25 | 'last 2 Chrome major versions', 26 | 'last 2 ChromeAndroid major versions', 27 | 'last 2 Edge major versions', 28 | 'last 2 Firefox major versions', 29 | 'last 2 FirefoxAndroid major versions', 30 | 'last 2 iOS major versions', 31 | 'last 2 Opera major versions', 32 | 'last 2 Safari major versions' 33 | ] 34 | } 35 | } 36 | ] 37 | ] 38 | } 39 | } 40 | } 41 | ] 42 | }, 43 | optimization: { 44 | minimizer: [ 45 | new TerserPlugin({ 46 | extractComments: { 47 | banner: false, 48 | condition: /^\**!|@preserve|@license|@cc_on/, 49 | filename: '3rdpartylicenses.txt' 50 | }, 51 | test: /\.ts$/ 52 | }) 53 | ] 54 | }, 55 | output: { 56 | filename: '[name].ts', 57 | path: resolve('src/worker/') 58 | }, 59 | plugins: [ 60 | { 61 | apply(compiler) { 62 | compiler.hooks.compilation.tap('WrapperPlugin', (compilation) => { 63 | compilation.hooks.processAssets.tap( 64 | { 65 | name: 'WrapperPlugin', 66 | stage: 700 67 | }, 68 | () => { 69 | for (const chunk of compilation.chunks) { 70 | for (const file of chunk.files) { 71 | compilation.updateAsset(file, (asset) => { 72 | const workerString = asset.source().replace(/\\/g, '\\\\').replace(/\${/g, '\\${'); 73 | 74 | return new RawSource(`// This is the minified and stringified code of the json-midi-encoder-worker package. 75 | export const worker = \`${workerString}\`; // tslint:disable-line:max-line-length 76 | `); 77 | }); 78 | } 79 | } 80 | } 81 | ); 82 | }); 83 | } 84 | } 85 | ], 86 | target: 'webworker' 87 | }; 88 | -------------------------------------------------------------------------------- /config/webpack/worker-es5.mjs: -------------------------------------------------------------------------------- 1 | import TerserPlugin from 'terser-webpack-plugin'; 2 | 3 | // eslint-disable-next-line import/no-default-export 4 | export default { 5 | entry: { 6 | worker: './src/worker.js' 7 | }, 8 | mode: 'production', 9 | module: { 10 | rules: [ 11 | { 12 | exclude: /node_modules/, 13 | test: /\.js$/, 14 | use: { 15 | loader: 'babel-loader', 16 | options: { 17 | plugins: ['@babel/plugin-external-helpers', '@babel/plugin-transform-runtime'], 18 | presets: ['@babel/preset-env'] 19 | } 20 | } 21 | } 22 | ] 23 | }, 24 | optimization: { 25 | minimizer: [ 26 | new TerserPlugin({ 27 | extractComments: { 28 | banner: false, 29 | condition: /^\**!|@preserve|@license|@cc_on/, 30 | filename: '3rdpartylicenses.txt' 31 | } 32 | }) 33 | ] 34 | }, 35 | output: { 36 | filename: '[name].js', 37 | path: '/' 38 | }, 39 | resolve: { 40 | mainFields: ['browser', 'main'] 41 | }, 42 | target: 'webworker' 43 | }; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Christoph Guttandin", 3 | "bugs": { 4 | "url": "https://github.com/chrisguttandin/json-midi-encoder/issues" 5 | }, 6 | "config": { 7 | "commitizen": { 8 | "path": "cz-conventional-changelog" 9 | } 10 | }, 11 | "dependencies": { 12 | "@babel/runtime": "^7.27.1", 13 | "json-midi-encoder-broker": "^4.0.123", 14 | "json-midi-encoder-worker": "^7.0.7", 15 | "tslib": "^2.8.1" 16 | }, 17 | "description": "This module encodes a JSON representation of MIDI data into a binary MIDI file.", 18 | "devDependencies": { 19 | "@babel/core": "^7.27.1", 20 | "@babel/plugin-external-helpers": "^7.27.1", 21 | "@babel/plugin-transform-runtime": "^7.27.1", 22 | "@babel/preset-env": "^7.27.2", 23 | "@commitlint/cli": "^19.8.1", 24 | "@commitlint/config-angular": "^19.8.1", 25 | "@rollup/plugin-babel": "^6.0.4", 26 | "@rollup/plugin-replace": "^6.0.2", 27 | "babel-loader": "^10.0.0", 28 | "chai": "^4.3.10", 29 | "commitizen": "^4.3.1", 30 | "cz-conventional-changelog": "^3.3.0", 31 | "eslint": "^8.57.0", 32 | "eslint-config-holy-grail": "^60.0.34", 33 | "husky": "^9.1.7", 34 | "karma": "^6.4.4", 35 | "karma-chrome-launcher": "^3.2.0", 36 | "karma-firefox-launcher": "^2.1.3", 37 | "karma-mocha": "^2.0.1", 38 | "karma-sauce-launcher": "^4.3.6", 39 | "karma-sinon-chai": "^2.0.2", 40 | "karma-webkit-launcher": "^2.6.0", 41 | "karma-webpack": "^5.0.1", 42 | "lint-staged": "^15.5.0", 43 | "memfs": "^4.17.1", 44 | "mocha": "^11.2.2", 45 | "prettier": "^3.5.3", 46 | "rimraf": "^6.0.1", 47 | "rollup": "^4.40.2", 48 | "sinon": "^17.0.2", 49 | "sinon-chai": "^3.7.0", 50 | "terser-webpack-plugin": "^5.3.14", 51 | "ts-loader": "^9.5.2", 52 | "tsconfig-holy-grail": "^15.0.2", 53 | "tslint": "^6.1.3", 54 | "tslint-config-holy-grail": "^56.0.6", 55 | "typescript": "^5.8.3", 56 | "webpack": "^5.99.8", 57 | "webpack-cli": "^6.0.1" 58 | }, 59 | "files": [ 60 | "build/es2019/", 61 | "build/es5/", 62 | "src/" 63 | ], 64 | "homepage": "https://github.com/chrisguttandin/json-midi-encoder", 65 | "keywords": [ 66 | "MIDI" 67 | ], 68 | "license": "MIT", 69 | "main": "build/es5/bundle.js", 70 | "module": "build/es2019/module.js", 71 | "name": "json-midi-encoder", 72 | "repository": { 73 | "type": "git", 74 | "url": "https://github.com/chrisguttandin/json-midi-encoder.git" 75 | }, 76 | "scripts": { 77 | "build": "rimraf build/* && webpack --config config/webpack/worker-es2019.js && tsc --project src/tsconfig.json && rollup --config config/rollup/bundle.mjs", 78 | "lint": "npm run lint:config && npm run lint:src && npm run lint:test", 79 | "lint:config": "eslint --config config/eslint/config.json --ext .cjs --ext .js --ext .mjs --report-unused-disable-directives config/", 80 | "lint:src": "tslint --config config/tslint/src.json --project src/tsconfig.json src/*.ts src/**/*.ts", 81 | "lint:test": "eslint --config config/eslint/test.json --ext .js --report-unused-disable-directives test/", 82 | "prepare": "husky", 83 | "prepublishOnly": "npm run build", 84 | "test": "npm run lint && npm run build && npm run test:unit", 85 | "test:unit": "if [ \"$TYPE\" = \"\" -o \"$TYPE\" = \"unit\" ]; then karma start config/karma/config-unit.js --single-run; fi" 86 | }, 87 | "types": "build/es2019/module.d.ts", 88 | "version": "5.1.61" 89 | } 90 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import { load } from 'json-midi-encoder-broker'; 2 | import { worker } from './worker/worker'; 3 | 4 | const blob: Blob = new Blob([worker], { type: 'application/javascript; charset=utf-8' }); 5 | 6 | const url: string = URL.createObjectURL(blob); 7 | 8 | const jsonMidiEncoder: ReturnType = load(url); 9 | 10 | export const encode: typeof jsonMidiEncoder.encode = jsonMidiEncoder.encode; 11 | 12 | URL.revokeObjectURL(url); 13 | -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "isolatedModules": true 4 | }, 5 | "extends": "tsconfig-holy-grail/src/tsconfig-browser" 6 | } 7 | -------------------------------------------------------------------------------- /src/worker/worker.ts: -------------------------------------------------------------------------------- 1 | // This is the minified and stringified code of the json-midi-encoder-worker package. 2 | export const worker = `(()=>{var e={455:function(e,t){!function(e){"use strict";var t=function(e){return function(t){var r=e(t);return t.add(r),r}},r=function(e){return function(t,r){return e.set(t,r),r}},n=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,s=536870912,a=2*s,i=function(e,t){return function(r){var i=t.get(r),o=void 0===i?r.size:in)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;r.has(o);)o=Math.floor(Math.random()*n);return e(r,o)}},o=new WeakMap,f=r(o),c=i(f,o),u=t(c);e.addUniqueNumber=u,e.generateUniqueNumber=c}(t)}},t={};function r(n){var s=t[n];if(void 0!==s)return s.exports;var a=t[n]={exports:{}};return e[n].call(a.exports,a,a.exports,r),a.exports}(()=>{"use strict";const e=-32603,t=-32602,n=-32601,s=(e,t)=>Object.assign(new Error(e),{status:t}),a=t=>s('The handler of the method called "'.concat(t,'" returned an unexpected result.'),e),i=(t,r)=>async({data:{id:i,method:o,params:f}})=>{const c=r[o];try{if(void 0===c)throw(e=>s('The requested method called "'.concat(e,'" is not supported.'),n))(o);const r=void 0===f?c():c(f);if(void 0===r)throw(t=>s('The handler of the method called "'.concat(t,'" returned no required result.'),e))(o);const u=r instanceof Promise?await r:r;if(null===i){if(void 0!==u.result)throw a(o)}else{if(void 0===u.result)throw a(o);const{result:e,transferables:r=[]}=u;t.postMessage({id:i,result:e},r)}}catch(e){const{message:r,status:n=-32603}=e;t.postMessage({error:{code:n,message:r},id:i})}};var o=r(455);const f=new Map,c=(e,r,n)=>({...r,connect:({port:t})=>{t.start();const n=e(t,r),s=(0,o.generateUniqueNumber)(f);return f.set(s,(()=>{n(),t.close(),f.delete(s)})),{result:s}},disconnect:({portId:e})=>{const r=f.get(e);if(void 0===r)throw(e=>s('The specified parameter called "portId" with the given value "'.concat(e,'" does not identify a port connected to this worker.'),t))(e);return r(),{result:null}},isSupported:async()=>{if(await new Promise((e=>{const t=new ArrayBuffer(0),{port1:r,port2:n}=new MessageChannel;r.onmessage=({data:t})=>e(null!==t),n.postMessage(t,[t])}))){const e=n();return{result:e instanceof Promise?await e:e}}return{result:!1}}}),u=(e,t,r=()=>!0)=>{const n=c(u,t,r),s=i(e,n);return e.addEventListener("message",s),()=>e.removeEventListener("message",s)},d=e=>{const t=new ArrayBuffer(e);return{arrayBuffer:t,dataView:new DataView(t)}},l=e=>{const t=new ArrayBuffer(e);return{arrayBuffer:t,dataView:new DataView(t)}},m=e=>{const t=e.reduce(((e,t)=>e+t.byteLength),0),[,r]=e.reduce((([e,t],r)=>(t.set(new Uint8Array(r),e),[e+r.byteLength,t])),[0,new Uint8Array(t)]);return r.buffer},h=(e=>t=>{const r=Math.max(1,Math.floor(Math.log(t)/Math.log(2)/7)+1),{arrayBuffer:n,dataView:s}=e(r);for(let e=1;e>7*e&127|128);return s.setUint8(r-1,127&t),n})(l),U=((e,t,r,n)=>s=>{if((e=>void 0!==e.channelPrefix)(s)){const{arrayBuffer:t,dataView:r}=e(4);return r.setUint8(0,255),r.setUint8(1,32),r.setUint8(2,1),r.setUint8(3,s.channelPrefix),t}if((e=>void 0!==e.channelPressure)(s)){const{arrayBuffer:t,dataView:r}=e(2);return r.setUint8(0,13|15&s.channel),r.setUint8(1,s.channelPressure.pressure),t}if((e=>void 0!==e.controlChange)(s)){const{arrayBuffer:t,dataView:r}=e(3);return r.setUint8(0,176|15&s.channel),r.setUint8(1,s.controlChange.type),r.setUint8(2,s.controlChange.value),t}if((e=>void 0!==e.copyrightNotice)(s))return t(s,2,"copyrightNotice");if((e=>void 0!==e.cuePoint&&void 0===e.metaTypeByte)(s))return t(s,7,"cuePoint");if((e=>void 0!==e.deviceName)(s))return t(s,9,"deviceName");if((e=>void 0!==e.endOfTrack)(s)){const{arrayBuffer:t,dataView:r}=e(3);return r.setUint8(0,255),r.setUint8(1,47),r.setUint8(2,0),t}if((e=>void 0!==e.instrumentName)(s))return t(s,4,"instrumentName");if((e=>void 0!==e.keyPressure)(s)){const{arrayBuffer:t,dataView:r}=e(3);return r.setUint8(0,10|15&s.channel),r.setUint8(1,s.keyPressure.noteNumber),r.setUint8(2,s.keyPressure.pressure),t}if((e=>void 0!==e.keySignature)(s)){const{arrayBuffer:t,dataView:r}=e(5);return r.setUint8(0,255),r.setUint8(1,89),r.setUint8(2,2),r.setUint8(3,s.keySignature.key),r.setUint8(4,s.keySignature.scale),t}if((e=>void 0!==e.lyric)(s))return t(s,5,"lyric");if((e=>void 0!==e.marker)(s))return t(s,6,"marker");if((e=>void 0!==e.midiPort)(s)){const{arrayBuffer:t,dataView:r}=e(4);return r.setUint8(0,255),r.setUint8(1,33),r.setUint8(2,1),r.setUint8(3,s.midiPort),t}if((e=>void 0!==e.noteOff)(s)){const{arrayBuffer:t,dataView:r}=e(3);return r.setUint8(0,128|15&s.channel),r.setUint8(1,s.noteOff.noteNumber),r.setUint8(2,s.noteOff.velocity),t}if((e=>void 0!==e.noteOn)(s)){const{arrayBuffer:t,dataView:r}=e(3);return r.setUint8(0,144|15&s.channel),r.setUint8(1,s.noteOn.noteNumber),r.setUint8(2,s.noteOn.velocity),t}if((e=>void 0!==e.pitchBend)(s)){const{arrayBuffer:t,dataView:r}=e(3);return r.setUint8(0,224|15&s.channel),r.setUint8(1,127&s.pitchBend),r.setUint8(2,s.pitchBend>>7),t}if((e=>void 0!==e.programChange)(s)){const{arrayBuffer:t,dataView:r}=e(2);return r.setUint8(0,192|15&s.channel),r.setUint8(1,s.programChange.programNumber),t}if((e=>void 0!==e.programName)(s))return t(s,8,"programName");if((e=>void 0!==e.sequencerSpecificData)(s)){const{arrayBuffer:t,dataView:a}=e(2);a.setUint8(0,255),a.setUint8(1,127);const i=s.sequencerSpecificData.length/2,o=n(i),{arrayBuffer:f,dataView:c}=e(i);for(let e=0;evoid 0!==e.setTempo)(s)){const{arrayBuffer:t,dataView:r}=e(6);return r.setUint8(0,255),r.setUint8(1,81),r.setUint8(2,3),r.setUint8(3,s.setTempo.microsecondsPerQuarter>>16),r.setUint8(4,s.setTempo.microsecondsPerQuarter>>8),r.setUint8(5,s.setTempo.microsecondsPerQuarter),t}if((e=>void 0!==e.smpteOffset)(s)){const{arrayBuffer:t,dataView:r}=e(8);let n;if(24===s.smpteOffset.frameRate)n=0;else if(25===s.smpteOffset.frameRate)n=32;else if(29===s.smpteOffset.frameRate)n=64;else{if(30!==s.smpteOffset.frameRate)throw new Error;n=96}return r.setUint8(0,255),r.setUint8(1,84),r.setUint8(2,5),r.setUint8(3,s.smpteOffset.hour|n),r.setUint8(4,s.smpteOffset.minutes),r.setUint8(5,s.smpteOffset.seconds),r.setUint8(6,s.smpteOffset.frame),r.setUint8(7,s.smpteOffset.subFrame),t}if((e=>void 0!==e.sysex)(s)){const{arrayBuffer:t,dataView:a}=e(1);a.setUint8(0,240);const i=s.sysex.length/2,o=n(i),{arrayBuffer:f,dataView:c}=e(i);for(let e=0;evoid 0!==e.timeSignature)(s)){const{arrayBuffer:t,dataView:r}=e(7);let n=s.timeSignature.denominator,a=0;for(;n>1;)n/=2,a+=1;return r.setUint8(0,255),r.setUint8(1,88),r.setUint8(2,4),r.setUint8(3,s.timeSignature.numerator),r.setUint8(4,a),r.setUint8(5,s.timeSignature.metronome),r.setUint8(6,s.timeSignature.thirtyseconds),t}if((e=>void 0!==e.metaTypeByte)(s))return t(s,parseInt(s.metaTypeByte,16),"text");if((e=>void 0!==e.text&&void 0===e.metaTypeByte)(s))return t(s,1,"text");if((e=>void 0!==e.trackName)(s))return t(s,3,"trackName");throw new Error('Unencodable event with a delta of "'.concat(s.delta,'".'))})(l,((e,t,r,n)=>(s,a,i)=>{const{arrayBuffer:o,dataView:f}=e(2);f.setUint8(0,255),f.setUint8(1,a);const c=r.encode(s[i]).buffer,u=n(c.byteLength);return t([o,u,c])})(l,m,new TextEncoder,h),m,h),y=e=>{const t=e.reduce(((e,t)=>e+t.byteLength),0),{uint8Array:r}=e.reduce((({offset:e,uint8Array:t},r)=>(t.set(new Uint8Array(r),e),{offset:e+r.byteLength,uint8Array:t})),{offset:0,uint8Array:new Uint8Array(t)});return r.buffer},w=e=>{const{arrayBuffer:t,dataView:r}=d(8),n=[t];let s=0;r.setUint32(0,1297379947);for(const t of e){const r=h(t.delta);try{const e=U(t);s+=r.byteLength+e.byteLength,n.push(r,e)}catch(r){if(r.message.match(/Unencodable\\smessage\\swith\\sa\\sdelta\\sof\\s[0-9]+\\./)){const r=e.indexOf(t);throw new Error("Unencodable message at index ".concat(r,"."))}throw r}}return r.setUint32(4,s),y(n)},p=({division:e,format:t,tracks:r})=>{const n=[];try{n.push(((e,t,r)=>{const{arrayBuffer:n,dataView:s}=d(14);return s.setUint32(0,1297377380),s.setUint32(4,6),s.setUint16(8,t),s.setUint16(10,r.length),s.setUint16(12,e),n})(e,t,r))}catch(e){throw new Error("The given JSON object seems to be invalid.")}for(const e of r)try{n.push(w(e))}catch(t){if(t.message.match(/Unencodable\\sevent\\sat\\sposition\\s[0-9]+\\./)){const n=r.indexOf(e);throw new Error("".concat(t.message.slice(0,-1)," of the track at index ").concat(n,"."))}throw t}return y(n)};u(self,{encode:({midiFile:e})=>{const t=p(e);return{result:t,transferables:[t]}}})})()})();`; // tslint:disable-line:max-line-length 3 | -------------------------------------------------------------------------------- /test/fixtures/26-2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/26-2.mid -------------------------------------------------------------------------------- /test/fixtures/98137.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/98137.mid -------------------------------------------------------------------------------- /test/fixtures/A_F_NO7_01.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/A_F_NO7_01.mid -------------------------------------------------------------------------------- /test/fixtures/MIDIOkFormat1-lyrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "division": 96, 3 | "format": 1, 4 | "tracks": [ 5 | [ 6 | { 7 | "delta": 0, 8 | "text": "Hello karaoke" 9 | }, 10 | { 11 | "channel": 1, 12 | "delta": 0, 13 | "programChange": { 14 | "programNumber": 0 15 | } 16 | }, 17 | { 18 | "delta": 0, 19 | "lyric": "He" 20 | }, 21 | { 22 | "channel": 1, 23 | "delta": 0, 24 | "noteOn": { 25 | "noteNumber": 86, 26 | "velocity": 121 27 | } 28 | }, 29 | { 30 | "channel": 1, 31 | "delta": 64, 32 | "noteOn": { 33 | "noteNumber": 86, 34 | "velocity": 0 35 | } 36 | }, 37 | { 38 | "delta": 64, 39 | "lyric": "llo" 40 | }, 41 | { 42 | "channel": 1, 43 | "delta": 0, 44 | "noteOn": { 45 | "noteNumber": 96, 46 | "velocity": 121 47 | } 48 | }, 49 | { 50 | "channel": 1, 51 | "delta": 95, 52 | "noteOn": { 53 | "noteNumber": 96, 54 | "velocity": 0 55 | } 56 | }, 57 | { 58 | "delta": 0, 59 | "lyric": "\\Ka" 60 | }, 61 | { 62 | "channel": 1, 63 | "delta": 0, 64 | "noteOn": { 65 | "noteNumber": 93, 66 | "velocity": 121 67 | } 68 | }, 69 | { 70 | "channel": 1, 71 | "delta": 64, 72 | "noteOn": { 73 | "noteNumber": 93, 74 | "velocity": 0 75 | } 76 | }, 77 | { 78 | "delta": 0, 79 | "lyric": "ra" 80 | }, 81 | { 82 | "channel": 1, 83 | "delta": 0, 84 | "noteOn": { 85 | "noteNumber": 84, 86 | "velocity": 121 87 | } 88 | }, 89 | { 90 | "channel": 1, 91 | "delta": 64, 92 | "noteOn": { 93 | "noteNumber": 84, 94 | "velocity": 0 95 | } 96 | }, 97 | { 98 | "delta": 0, 99 | "lyric": "o" 100 | }, 101 | { 102 | "channel": 1, 103 | "delta": 0, 104 | "noteOn": { 105 | "noteNumber": 88, 106 | "velocity": 121 107 | } 108 | }, 109 | { 110 | "channel": 1, 111 | "delta": 64, 112 | "noteOn": { 113 | "noteNumber": 88, 114 | "velocity": 0 115 | } 116 | }, 117 | { 118 | "delta": 0, 119 | "lyric": "ke" 120 | }, 121 | { 122 | "channel": 1, 123 | "delta": 0, 124 | "noteOn": { 125 | "noteNumber": 95, 126 | "velocity": 121 127 | } 128 | }, 129 | { 130 | "channel": 1, 131 | "delta": 64, 132 | "noteOn": { 133 | "noteNumber": 95, 134 | "velocity": 0 135 | } 136 | }, 137 | { 138 | "delta": 0, 139 | "endOfTrack": true 140 | } 141 | ] 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /test/fixtures/MIDIOkFormat1-lyrics.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/MIDIOkFormat1-lyrics.mid -------------------------------------------------------------------------------- /test/fixtures/MIDIOkFormat2.json: -------------------------------------------------------------------------------- 1 | { 2 | "division": 96, 3 | "format": 2, 4 | "tracks": [ 5 | [ 6 | { 7 | "delta": 0, 8 | "text": "A complete scale" 9 | }, 10 | { 11 | "delta": 0, 12 | "endOfTrack": true 13 | } 14 | ], 15 | [ 16 | { 17 | "delta": 0, 18 | "text": "c" 19 | }, 20 | { 21 | "channel": 1, 22 | "delta": 0, 23 | "programChange": { 24 | "programNumber": 5 25 | } 26 | }, 27 | { 28 | "channel": 1, 29 | "delta": 0, 30 | "noteOn": { 31 | "noteNumber": 48, 32 | "velocity": 121 33 | } 34 | }, 35 | { 36 | "channel": 1, 37 | "delta": 95, 38 | "noteOn": { 39 | "noteNumber": 48, 40 | "velocity": 0 41 | } 42 | }, 43 | { 44 | "delta": 0, 45 | "endOfTrack": true 46 | } 47 | ], 48 | [ 49 | { 50 | "delta": 0, 51 | "text": "d" 52 | }, 53 | { 54 | "channel": 1, 55 | "delta": 0, 56 | "programChange": { 57 | "programNumber": 5 58 | } 59 | }, 60 | { 61 | "channel": 1, 62 | "delta": 0, 63 | "noteOn": { 64 | "noteNumber": 50, 65 | "velocity": 121 66 | } 67 | }, 68 | { 69 | "channel": 1, 70 | "delta": 95, 71 | "noteOn": { 72 | "noteNumber": 50, 73 | "velocity": 0 74 | } 75 | }, 76 | { 77 | "delta": 0, 78 | "endOfTrack": true 79 | } 80 | ], 81 | [ 82 | { 83 | "delta": 0, 84 | "text": "e" 85 | }, 86 | { 87 | "channel": 1, 88 | "delta": 0, 89 | "programChange": { 90 | "programNumber": 5 91 | } 92 | }, 93 | { 94 | "channel": 1, 95 | "delta": 0, 96 | "noteOn": { 97 | "noteNumber": 52, 98 | "velocity": 121 99 | } 100 | }, 101 | { 102 | "channel": 1, 103 | "delta": 95, 104 | "noteOn": { 105 | "noteNumber": 52, 106 | "velocity": 0 107 | } 108 | }, 109 | { 110 | "delta": 0, 111 | "endOfTrack": true 112 | } 113 | ], 114 | [ 115 | { 116 | "delta": 0, 117 | "text": "f" 118 | }, 119 | { 120 | "channel": 1, 121 | "delta": 0, 122 | "programChange": { 123 | "programNumber": 5 124 | } 125 | }, 126 | { 127 | "channel": 1, 128 | "delta": 0, 129 | "noteOn": { 130 | "noteNumber": 53, 131 | "velocity": 89 132 | } 133 | }, 134 | { 135 | "channel": 1, 136 | "delta": 95, 137 | "noteOn": { 138 | "noteNumber": 53, 139 | "velocity": 0 140 | } 141 | }, 142 | { 143 | "delta": 0, 144 | "endOfTrack": true 145 | } 146 | ], 147 | [ 148 | { 149 | "delta": 0, 150 | "text": "g" 151 | }, 152 | { 153 | "channel": 1, 154 | "delta": 0, 155 | "programChange": { 156 | "programNumber": 5 157 | } 158 | }, 159 | { 160 | "channel": 1, 161 | "delta": 0, 162 | "noteOn": { 163 | "noteNumber": 55, 164 | "velocity": 121 165 | } 166 | }, 167 | { 168 | "channel": 1, 169 | "delta": 95, 170 | "noteOn": { 171 | "noteNumber": 55, 172 | "velocity": 0 173 | } 174 | }, 175 | { 176 | "delta": 0, 177 | "endOfTrack": true 178 | } 179 | ], 180 | [ 181 | { 182 | "delta": 0, 183 | "text": "a" 184 | }, 185 | { 186 | "channel": 1, 187 | "delta": 0, 188 | "programChange": { 189 | "programNumber": 5 190 | } 191 | }, 192 | { 193 | "channel": 1, 194 | "delta": 0, 195 | "noteOn": { 196 | "noteNumber": 57, 197 | "velocity": 121 198 | } 199 | }, 200 | { 201 | "channel": 1, 202 | "delta": 95, 203 | "noteOn": { 204 | "noteNumber": 57, 205 | "velocity": 0 206 | } 207 | }, 208 | { 209 | "delta": 0, 210 | "endOfTrack": true 211 | } 212 | ], 213 | [ 214 | { 215 | "delta": 0, 216 | "text": "b" 217 | }, 218 | { 219 | "channel": 1, 220 | "delta": 0, 221 | "programChange": { 222 | "programNumber": 5 223 | } 224 | }, 225 | { 226 | "channel": 1, 227 | "delta": 0, 228 | "noteOn": { 229 | "noteNumber": 59, 230 | "velocity": 121 231 | } 232 | }, 233 | { 234 | "channel": 1, 235 | "delta": 95, 236 | "noteOn": { 237 | "noteNumber": 59, 238 | "velocity": 0 239 | } 240 | }, 241 | { 242 | "delta": 0, 243 | "endOfTrack": true 244 | } 245 | ], 246 | [ 247 | { 248 | "delta": 0, 249 | "text": "c" 250 | }, 251 | { 252 | "channel": 1, 253 | "delta": 0, 254 | "programChange": { 255 | "programNumber": 5 256 | } 257 | }, 258 | { 259 | "channel": 1, 260 | "delta": 0, 261 | "noteOn": { 262 | "noteNumber": 60, 263 | "velocity": 121 264 | } 265 | }, 266 | { 267 | "channel": 1, 268 | "delta": 95, 269 | "noteOn": { 270 | "noteNumber": 60, 271 | "velocity": 0 272 | } 273 | }, 274 | { 275 | "delta": 0, 276 | "endOfTrack": true 277 | } 278 | ] 279 | ] 280 | } 281 | -------------------------------------------------------------------------------- /test/fixtures/MIDIOkFormat2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/MIDIOkFormat2.mid -------------------------------------------------------------------------------- /test/fixtures/MorozovS07.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/MorozovS07.mid -------------------------------------------------------------------------------- /test/fixtures/SubTractor 1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/SubTractor 1.mid -------------------------------------------------------------------------------- /test/fixtures/SubTractor 2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/SubTractor 2.mid -------------------------------------------------------------------------------- /test/fixtures/TheEntertainer.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/TheEntertainer.mid -------------------------------------------------------------------------------- /test/fixtures/because.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/because.mid -------------------------------------------------------------------------------- /test/fixtures/californication.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/californication.mid -------------------------------------------------------------------------------- /test/fixtures/minute_waltz.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/minute_waltz.mid -------------------------------------------------------------------------------- /test/fixtures/rachmaninov3.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/rachmaninov3.mid -------------------------------------------------------------------------------- /test/fixtures/scale.json: -------------------------------------------------------------------------------- 1 | { 2 | "division": 480, 3 | "format": 1, 4 | "tracks": [ 5 | [ 6 | { 7 | "delta": 0, 8 | "trackName": "scale" 9 | }, 10 | { 11 | "delta": 0, 12 | "setTempo": { 13 | "microsecondsPerQuarter": 500000 14 | } 15 | }, 16 | { 17 | "delta": 0, 18 | "timeSignature": { 19 | "denominator": 4, 20 | "metronome": 24, 21 | "numerator": 4, 22 | "thirtyseconds": 8 23 | } 24 | }, 25 | { 26 | "delta": 0, 27 | "endOfTrack": true 28 | } 29 | ], 30 | [ 31 | { 32 | "delta": 0, 33 | "trackName": "scale" 34 | }, 35 | { 36 | "channel": 0, 37 | "delta": 0, 38 | "noteOn": { 39 | "noteNumber": 36, 40 | "velocity": 100 41 | } 42 | }, 43 | { 44 | "channel": 0, 45 | "delta": 240, 46 | "noteOff": { 47 | "noteNumber": 36, 48 | "velocity": 64 49 | } 50 | }, 51 | { 52 | "channel": 0, 53 | "delta": 0, 54 | "noteOn": { 55 | "noteNumber": 37, 56 | "velocity": 100 57 | } 58 | }, 59 | { 60 | "channel": 0, 61 | "delta": 240, 62 | "noteOff": { 63 | "noteNumber": 37, 64 | "velocity": 64 65 | } 66 | }, 67 | { 68 | "channel": 0, 69 | "delta": 0, 70 | "noteOn": { 71 | "noteNumber": 38, 72 | "velocity": 100 73 | } 74 | }, 75 | { 76 | "channel": 0, 77 | "delta": 240, 78 | "noteOff": { 79 | "noteNumber": 38, 80 | "velocity": 64 81 | } 82 | }, 83 | { 84 | "channel": 0, 85 | "delta": 0, 86 | "noteOn": { 87 | "noteNumber": 39, 88 | "velocity": 100 89 | } 90 | }, 91 | { 92 | "channel": 0, 93 | "delta": 240, 94 | "noteOff": { 95 | "noteNumber": 39, 96 | "velocity": 64 97 | } 98 | }, 99 | { 100 | "channel": 0, 101 | "delta": 0, 102 | "noteOn": { 103 | "noteNumber": 40, 104 | "velocity": 100 105 | } 106 | }, 107 | { 108 | "channel": 0, 109 | "delta": 240, 110 | "noteOff": { 111 | "noteNumber": 40, 112 | "velocity": 64 113 | } 114 | }, 115 | { 116 | "channel": 0, 117 | "delta": 0, 118 | "noteOn": { 119 | "noteNumber": 41, 120 | "velocity": 100 121 | } 122 | }, 123 | { 124 | "channel": 0, 125 | "delta": 240, 126 | "noteOff": { 127 | "noteNumber": 41, 128 | "velocity": 64 129 | } 130 | }, 131 | { 132 | "channel": 0, 133 | "delta": 0, 134 | "noteOn": { 135 | "noteNumber": 42, 136 | "velocity": 100 137 | } 138 | }, 139 | { 140 | "channel": 0, 141 | "delta": 240, 142 | "noteOff": { 143 | "noteNumber": 42, 144 | "velocity": 64 145 | } 146 | }, 147 | { 148 | "channel": 0, 149 | "delta": 0, 150 | "noteOn": { 151 | "noteNumber": 43, 152 | "velocity": 100 153 | } 154 | }, 155 | { 156 | "channel": 0, 157 | "delta": 240, 158 | "noteOff": { 159 | "noteNumber": 43, 160 | "velocity": 64 161 | } 162 | }, 163 | { 164 | "channel": 0, 165 | "delta": 0, 166 | "noteOn": { 167 | "noteNumber": 44, 168 | "velocity": 100 169 | } 170 | }, 171 | { 172 | "channel": 0, 173 | "delta": 240, 174 | "noteOff": { 175 | "noteNumber": 44, 176 | "velocity": 64 177 | } 178 | }, 179 | { 180 | "channel": 0, 181 | "delta": 0, 182 | "noteOn": { 183 | "noteNumber": 45, 184 | "velocity": 100 185 | } 186 | }, 187 | { 188 | "channel": 0, 189 | "delta": 240, 190 | "noteOff": { 191 | "noteNumber": 45, 192 | "velocity": 64 193 | } 194 | }, 195 | { 196 | "channel": 0, 197 | "delta": 0, 198 | "noteOn": { 199 | "noteNumber": 46, 200 | "velocity": 100 201 | } 202 | }, 203 | { 204 | "channel": 0, 205 | "delta": 240, 206 | "noteOff": { 207 | "noteNumber": 46, 208 | "velocity": 64 209 | } 210 | }, 211 | { 212 | "channel": 0, 213 | "delta": 0, 214 | "noteOn": { 215 | "noteNumber": 47, 216 | "velocity": 100 217 | } 218 | }, 219 | { 220 | "channel": 0, 221 | "delta": 240, 222 | "noteOff": { 223 | "noteNumber": 47, 224 | "velocity": 64 225 | } 226 | }, 227 | { 228 | "channel": 0, 229 | "delta": 0, 230 | "noteOn": { 231 | "noteNumber": 48, 232 | "velocity": 100 233 | } 234 | }, 235 | { 236 | "channel": 0, 237 | "delta": 240, 238 | "noteOff": { 239 | "noteNumber": 48, 240 | "velocity": 64 241 | } 242 | }, 243 | { 244 | "channel": 0, 245 | "delta": 0, 246 | "noteOn": { 247 | "noteNumber": 49, 248 | "velocity": 100 249 | } 250 | }, 251 | { 252 | "channel": 0, 253 | "delta": 240, 254 | "noteOff": { 255 | "noteNumber": 49, 256 | "velocity": 64 257 | } 258 | }, 259 | { 260 | "channel": 0, 261 | "delta": 0, 262 | "noteOn": { 263 | "noteNumber": 50, 264 | "velocity": 100 265 | } 266 | }, 267 | { 268 | "channel": 0, 269 | "delta": 240, 270 | "noteOff": { 271 | "noteNumber": 50, 272 | "velocity": 64 273 | } 274 | }, 275 | { 276 | "channel": 0, 277 | "delta": 0, 278 | "noteOn": { 279 | "noteNumber": 51, 280 | "velocity": 100 281 | } 282 | }, 283 | { 284 | "channel": 0, 285 | "delta": 240, 286 | "noteOff": { 287 | "noteNumber": 51, 288 | "velocity": 64 289 | } 290 | }, 291 | { 292 | "channel": 0, 293 | "delta": 0, 294 | "noteOn": { 295 | "noteNumber": 52, 296 | "velocity": 100 297 | } 298 | }, 299 | { 300 | "channel": 0, 301 | "delta": 240, 302 | "noteOff": { 303 | "noteNumber": 52, 304 | "velocity": 64 305 | } 306 | }, 307 | { 308 | "channel": 0, 309 | "delta": 0, 310 | "noteOn": { 311 | "noteNumber": 53, 312 | "velocity": 100 313 | } 314 | }, 315 | { 316 | "channel": 0, 317 | "delta": 240, 318 | "noteOff": { 319 | "noteNumber": 53, 320 | "velocity": 64 321 | } 322 | }, 323 | { 324 | "channel": 0, 325 | "delta": 0, 326 | "noteOn": { 327 | "noteNumber": 54, 328 | "velocity": 100 329 | } 330 | }, 331 | { 332 | "channel": 0, 333 | "delta": 240, 334 | "noteOff": { 335 | "noteNumber": 54, 336 | "velocity": 64 337 | } 338 | }, 339 | { 340 | "channel": 0, 341 | "delta": 0, 342 | "noteOn": { 343 | "noteNumber": 55, 344 | "velocity": 100 345 | } 346 | }, 347 | { 348 | "channel": 0, 349 | "delta": 240, 350 | "noteOff": { 351 | "noteNumber": 55, 352 | "velocity": 64 353 | } 354 | }, 355 | { 356 | "channel": 0, 357 | "delta": 0, 358 | "noteOn": { 359 | "noteNumber": 56, 360 | "velocity": 100 361 | } 362 | }, 363 | { 364 | "channel": 0, 365 | "delta": 240, 366 | "noteOff": { 367 | "noteNumber": 56, 368 | "velocity": 64 369 | } 370 | }, 371 | { 372 | "channel": 0, 373 | "delta": 0, 374 | "noteOn": { 375 | "noteNumber": 57, 376 | "velocity": 100 377 | } 378 | }, 379 | { 380 | "channel": 0, 381 | "delta": 240, 382 | "noteOff": { 383 | "noteNumber": 57, 384 | "velocity": 64 385 | } 386 | }, 387 | { 388 | "channel": 0, 389 | "delta": 0, 390 | "noteOn": { 391 | "noteNumber": 58, 392 | "velocity": 100 393 | } 394 | }, 395 | { 396 | "channel": 0, 397 | "delta": 240, 398 | "noteOff": { 399 | "noteNumber": 58, 400 | "velocity": 64 401 | } 402 | }, 403 | { 404 | "channel": 0, 405 | "delta": 0, 406 | "noteOn": { 407 | "noteNumber": 59, 408 | "velocity": 100 409 | } 410 | }, 411 | { 412 | "channel": 0, 413 | "delta": 240, 414 | "noteOff": { 415 | "noteNumber": 59, 416 | "velocity": 64 417 | } 418 | }, 419 | { 420 | "channel": 0, 421 | "delta": 0, 422 | "noteOn": { 423 | "noteNumber": 60, 424 | "velocity": 100 425 | } 426 | }, 427 | { 428 | "channel": 0, 429 | "delta": 240, 430 | "noteOff": { 431 | "noteNumber": 60, 432 | "velocity": 64 433 | } 434 | }, 435 | { 436 | "channel": 0, 437 | "delta": 0, 438 | "noteOn": { 439 | "noteNumber": 61, 440 | "velocity": 100 441 | } 442 | }, 443 | { 444 | "channel": 0, 445 | "delta": 240, 446 | "noteOff": { 447 | "noteNumber": 61, 448 | "velocity": 64 449 | } 450 | }, 451 | { 452 | "channel": 0, 453 | "delta": 0, 454 | "noteOn": { 455 | "noteNumber": 62, 456 | "velocity": 100 457 | } 458 | }, 459 | { 460 | "channel": 0, 461 | "delta": 240, 462 | "noteOff": { 463 | "noteNumber": 62, 464 | "velocity": 64 465 | } 466 | }, 467 | { 468 | "channel": 0, 469 | "delta": 0, 470 | "noteOn": { 471 | "noteNumber": 63, 472 | "velocity": 100 473 | } 474 | }, 475 | { 476 | "channel": 0, 477 | "delta": 240, 478 | "noteOff": { 479 | "noteNumber": 63, 480 | "velocity": 64 481 | } 482 | }, 483 | { 484 | "channel": 0, 485 | "delta": 0, 486 | "noteOn": { 487 | "noteNumber": 64, 488 | "velocity": 100 489 | } 490 | }, 491 | { 492 | "channel": 0, 493 | "delta": 240, 494 | "noteOff": { 495 | "noteNumber": 64, 496 | "velocity": 64 497 | } 498 | }, 499 | { 500 | "channel": 0, 501 | "delta": 0, 502 | "noteOn": { 503 | "noteNumber": 65, 504 | "velocity": 100 505 | } 506 | }, 507 | { 508 | "channel": 0, 509 | "delta": 240, 510 | "noteOff": { 511 | "noteNumber": 65, 512 | "velocity": 64 513 | } 514 | }, 515 | { 516 | "channel": 0, 517 | "delta": 0, 518 | "noteOn": { 519 | "noteNumber": 66, 520 | "velocity": 100 521 | } 522 | }, 523 | { 524 | "channel": 0, 525 | "delta": 240, 526 | "noteOff": { 527 | "noteNumber": 66, 528 | "velocity": 64 529 | } 530 | }, 531 | { 532 | "channel": 0, 533 | "delta": 0, 534 | "noteOn": { 535 | "noteNumber": 67, 536 | "velocity": 100 537 | } 538 | }, 539 | { 540 | "channel": 0, 541 | "delta": 240, 542 | "noteOff": { 543 | "noteNumber": 67, 544 | "velocity": 64 545 | } 546 | }, 547 | { 548 | "channel": 0, 549 | "delta": 0, 550 | "noteOn": { 551 | "noteNumber": 68, 552 | "velocity": 100 553 | } 554 | }, 555 | { 556 | "channel": 0, 557 | "delta": 240, 558 | "noteOff": { 559 | "noteNumber": 68, 560 | "velocity": 64 561 | } 562 | }, 563 | { 564 | "channel": 0, 565 | "delta": 0, 566 | "noteOn": { 567 | "noteNumber": 69, 568 | "velocity": 100 569 | } 570 | }, 571 | { 572 | "channel": 0, 573 | "delta": 240, 574 | "noteOff": { 575 | "noteNumber": 69, 576 | "velocity": 64 577 | } 578 | }, 579 | { 580 | "channel": 0, 581 | "delta": 0, 582 | "noteOn": { 583 | "noteNumber": 70, 584 | "velocity": 100 585 | } 586 | }, 587 | { 588 | "channel": 0, 589 | "delta": 240, 590 | "noteOff": { 591 | "noteNumber": 70, 592 | "velocity": 64 593 | } 594 | }, 595 | { 596 | "channel": 0, 597 | "delta": 0, 598 | "noteOn": { 599 | "noteNumber": 71, 600 | "velocity": 100 601 | } 602 | }, 603 | { 604 | "channel": 0, 605 | "delta": 240, 606 | "noteOff": { 607 | "noteNumber": 71, 608 | "velocity": 64 609 | } 610 | }, 611 | { 612 | "channel": 0, 613 | "delta": 0, 614 | "noteOn": { 615 | "noteNumber": 72, 616 | "velocity": 100 617 | } 618 | }, 619 | { 620 | "channel": 0, 621 | "delta": 240, 622 | "noteOff": { 623 | "noteNumber": 72, 624 | "velocity": 64 625 | } 626 | }, 627 | { 628 | "channel": 0, 629 | "delta": 0, 630 | "noteOn": { 631 | "noteNumber": 73, 632 | "velocity": 100 633 | } 634 | }, 635 | { 636 | "channel": 0, 637 | "delta": 240, 638 | "noteOff": { 639 | "noteNumber": 73, 640 | "velocity": 64 641 | } 642 | }, 643 | { 644 | "channel": 0, 645 | "delta": 0, 646 | "noteOn": { 647 | "noteNumber": 74, 648 | "velocity": 100 649 | } 650 | }, 651 | { 652 | "channel": 0, 653 | "delta": 240, 654 | "noteOff": { 655 | "noteNumber": 74, 656 | "velocity": 64 657 | } 658 | }, 659 | { 660 | "channel": 0, 661 | "delta": 0, 662 | "noteOn": { 663 | "noteNumber": 75, 664 | "velocity": 100 665 | } 666 | }, 667 | { 668 | "channel": 0, 669 | "delta": 240, 670 | "noteOff": { 671 | "noteNumber": 75, 672 | "velocity": 64 673 | } 674 | }, 675 | { 676 | "channel": 0, 677 | "delta": 0, 678 | "noteOn": { 679 | "noteNumber": 36, 680 | "velocity": 100 681 | } 682 | }, 683 | { 684 | "channel": 0, 685 | "delta": 1920, 686 | "noteOff": { 687 | "noteNumber": 36, 688 | "velocity": 64 689 | } 690 | }, 691 | { 692 | "channel": 0, 693 | "delta": 0, 694 | "noteOn": { 695 | "noteNumber": 48, 696 | "velocity": 100 697 | } 698 | }, 699 | { 700 | "channel": 0, 701 | "delta": 1920, 702 | "noteOff": { 703 | "noteNumber": 48, 704 | "velocity": 64 705 | } 706 | }, 707 | { 708 | "channel": 0, 709 | "delta": 0, 710 | "noteOn": { 711 | "noteNumber": 72, 712 | "velocity": 100 713 | } 714 | }, 715 | { 716 | "channel": 0, 717 | "delta": 1920, 718 | "noteOff": { 719 | "noteNumber": 72, 720 | "velocity": 64 721 | } 722 | }, 723 | { 724 | "channel": 0, 725 | "delta": 0, 726 | "noteOn": { 727 | "noteNumber": 36, 728 | "velocity": 100 729 | } 730 | }, 731 | { 732 | "channel": 0, 733 | "delta": 240, 734 | "noteOff": { 735 | "noteNumber": 36, 736 | "velocity": 64 737 | } 738 | }, 739 | { 740 | "channel": 0, 741 | "delta": 0, 742 | "noteOn": { 743 | "noteNumber": 37, 744 | "velocity": 100 745 | } 746 | }, 747 | { 748 | "channel": 0, 749 | "delta": 240, 750 | "noteOff": { 751 | "noteNumber": 37, 752 | "velocity": 64 753 | } 754 | }, 755 | { 756 | "channel": 0, 757 | "delta": 0, 758 | "noteOn": { 759 | "noteNumber": 38, 760 | "velocity": 100 761 | } 762 | }, 763 | { 764 | "channel": 0, 765 | "delta": 240, 766 | "noteOff": { 767 | "noteNumber": 38, 768 | "velocity": 64 769 | } 770 | }, 771 | { 772 | "channel": 0, 773 | "delta": 0, 774 | "noteOn": { 775 | "noteNumber": 39, 776 | "velocity": 100 777 | } 778 | }, 779 | { 780 | "channel": 0, 781 | "delta": 240, 782 | "noteOff": { 783 | "noteNumber": 39, 784 | "velocity": 64 785 | } 786 | }, 787 | { 788 | "channel": 0, 789 | "delta": 0, 790 | "noteOn": { 791 | "noteNumber": 40, 792 | "velocity": 100 793 | } 794 | }, 795 | { 796 | "channel": 0, 797 | "delta": 240, 798 | "noteOff": { 799 | "noteNumber": 40, 800 | "velocity": 64 801 | } 802 | }, 803 | { 804 | "channel": 0, 805 | "delta": 0, 806 | "noteOn": { 807 | "noteNumber": 41, 808 | "velocity": 100 809 | } 810 | }, 811 | { 812 | "channel": 0, 813 | "delta": 240, 814 | "noteOff": { 815 | "noteNumber": 41, 816 | "velocity": 64 817 | } 818 | }, 819 | { 820 | "channel": 0, 821 | "delta": 0, 822 | "noteOn": { 823 | "noteNumber": 42, 824 | "velocity": 100 825 | } 826 | }, 827 | { 828 | "channel": 0, 829 | "delta": 240, 830 | "noteOff": { 831 | "noteNumber": 42, 832 | "velocity": 64 833 | } 834 | }, 835 | { 836 | "channel": 0, 837 | "delta": 0, 838 | "noteOn": { 839 | "noteNumber": 43, 840 | "velocity": 100 841 | } 842 | }, 843 | { 844 | "channel": 0, 845 | "delta": 240, 846 | "noteOff": { 847 | "noteNumber": 43, 848 | "velocity": 64 849 | } 850 | }, 851 | { 852 | "channel": 0, 853 | "delta": 0, 854 | "noteOn": { 855 | "noteNumber": 44, 856 | "velocity": 100 857 | } 858 | }, 859 | { 860 | "channel": 0, 861 | "delta": 240, 862 | "noteOff": { 863 | "noteNumber": 44, 864 | "velocity": 64 865 | } 866 | }, 867 | { 868 | "channel": 0, 869 | "delta": 0, 870 | "noteOn": { 871 | "noteNumber": 45, 872 | "velocity": 100 873 | } 874 | }, 875 | { 876 | "channel": 0, 877 | "delta": 240, 878 | "noteOff": { 879 | "noteNumber": 45, 880 | "velocity": 64 881 | } 882 | }, 883 | { 884 | "channel": 0, 885 | "delta": 0, 886 | "noteOn": { 887 | "noteNumber": 46, 888 | "velocity": 100 889 | } 890 | }, 891 | { 892 | "channel": 0, 893 | "delta": 240, 894 | "noteOff": { 895 | "noteNumber": 46, 896 | "velocity": 64 897 | } 898 | }, 899 | { 900 | "channel": 0, 901 | "delta": 0, 902 | "noteOn": { 903 | "noteNumber": 47, 904 | "velocity": 100 905 | } 906 | }, 907 | { 908 | "channel": 0, 909 | "delta": 240, 910 | "noteOff": { 911 | "noteNumber": 47, 912 | "velocity": 64 913 | } 914 | }, 915 | { 916 | "channel": 0, 917 | "delta": 0, 918 | "noteOn": { 919 | "noteNumber": 48, 920 | "velocity": 100 921 | } 922 | }, 923 | { 924 | "channel": 0, 925 | "delta": 240, 926 | "noteOff": { 927 | "noteNumber": 48, 928 | "velocity": 64 929 | } 930 | }, 931 | { 932 | "channel": 0, 933 | "delta": 0, 934 | "noteOn": { 935 | "noteNumber": 49, 936 | "velocity": 100 937 | } 938 | }, 939 | { 940 | "channel": 0, 941 | "delta": 240, 942 | "noteOff": { 943 | "noteNumber": 49, 944 | "velocity": 64 945 | } 946 | }, 947 | { 948 | "channel": 0, 949 | "delta": 0, 950 | "noteOn": { 951 | "noteNumber": 50, 952 | "velocity": 100 953 | } 954 | }, 955 | { 956 | "channel": 0, 957 | "delta": 240, 958 | "noteOff": { 959 | "noteNumber": 50, 960 | "velocity": 64 961 | } 962 | }, 963 | { 964 | "channel": 0, 965 | "delta": 0, 966 | "noteOn": { 967 | "noteNumber": 51, 968 | "velocity": 100 969 | } 970 | }, 971 | { 972 | "channel": 0, 973 | "delta": 240, 974 | "noteOff": { 975 | "noteNumber": 51, 976 | "velocity": 64 977 | } 978 | }, 979 | { 980 | "channel": 0, 981 | "delta": 0, 982 | "noteOn": { 983 | "noteNumber": 52, 984 | "velocity": 100 985 | } 986 | }, 987 | { 988 | "channel": 0, 989 | "delta": 240, 990 | "noteOff": { 991 | "noteNumber": 52, 992 | "velocity": 64 993 | } 994 | }, 995 | { 996 | "channel": 0, 997 | "delta": 0, 998 | "noteOn": { 999 | "noteNumber": 53, 1000 | "velocity": 100 1001 | } 1002 | }, 1003 | { 1004 | "channel": 0, 1005 | "delta": 240, 1006 | "noteOff": { 1007 | "noteNumber": 53, 1008 | "velocity": 64 1009 | } 1010 | }, 1011 | { 1012 | "channel": 0, 1013 | "delta": 0, 1014 | "noteOn": { 1015 | "noteNumber": 54, 1016 | "velocity": 100 1017 | } 1018 | }, 1019 | { 1020 | "channel": 0, 1021 | "delta": 240, 1022 | "noteOff": { 1023 | "noteNumber": 54, 1024 | "velocity": 64 1025 | } 1026 | }, 1027 | { 1028 | "channel": 0, 1029 | "delta": 0, 1030 | "noteOn": { 1031 | "noteNumber": 55, 1032 | "velocity": 100 1033 | } 1034 | }, 1035 | { 1036 | "channel": 0, 1037 | "delta": 240, 1038 | "noteOff": { 1039 | "noteNumber": 55, 1040 | "velocity": 64 1041 | } 1042 | }, 1043 | { 1044 | "channel": 0, 1045 | "delta": 0, 1046 | "noteOn": { 1047 | "noteNumber": 56, 1048 | "velocity": 100 1049 | } 1050 | }, 1051 | { 1052 | "channel": 0, 1053 | "delta": 240, 1054 | "noteOff": { 1055 | "noteNumber": 56, 1056 | "velocity": 64 1057 | } 1058 | }, 1059 | { 1060 | "channel": 0, 1061 | "delta": 0, 1062 | "noteOn": { 1063 | "noteNumber": 57, 1064 | "velocity": 100 1065 | } 1066 | }, 1067 | { 1068 | "channel": 0, 1069 | "delta": 240, 1070 | "noteOff": { 1071 | "noteNumber": 57, 1072 | "velocity": 64 1073 | } 1074 | }, 1075 | { 1076 | "channel": 0, 1077 | "delta": 0, 1078 | "noteOn": { 1079 | "noteNumber": 58, 1080 | "velocity": 100 1081 | } 1082 | }, 1083 | { 1084 | "channel": 0, 1085 | "delta": 240, 1086 | "noteOff": { 1087 | "noteNumber": 58, 1088 | "velocity": 64 1089 | } 1090 | }, 1091 | { 1092 | "channel": 0, 1093 | "delta": 0, 1094 | "noteOn": { 1095 | "noteNumber": 59, 1096 | "velocity": 100 1097 | } 1098 | }, 1099 | { 1100 | "channel": 0, 1101 | "delta": 240, 1102 | "noteOff": { 1103 | "noteNumber": 59, 1104 | "velocity": 64 1105 | } 1106 | }, 1107 | { 1108 | "channel": 0, 1109 | "delta": 0, 1110 | "noteOn": { 1111 | "noteNumber": 60, 1112 | "velocity": 100 1113 | } 1114 | }, 1115 | { 1116 | "channel": 0, 1117 | "delta": 240, 1118 | "noteOff": { 1119 | "noteNumber": 60, 1120 | "velocity": 64 1121 | } 1122 | }, 1123 | { 1124 | "channel": 0, 1125 | "delta": 0, 1126 | "noteOn": { 1127 | "noteNumber": 61, 1128 | "velocity": 100 1129 | } 1130 | }, 1131 | { 1132 | "channel": 0, 1133 | "delta": 240, 1134 | "noteOff": { 1135 | "noteNumber": 61, 1136 | "velocity": 64 1137 | } 1138 | }, 1139 | { 1140 | "channel": 0, 1141 | "delta": 0, 1142 | "noteOn": { 1143 | "noteNumber": 62, 1144 | "velocity": 100 1145 | } 1146 | }, 1147 | { 1148 | "channel": 0, 1149 | "delta": 240, 1150 | "noteOff": { 1151 | "noteNumber": 62, 1152 | "velocity": 64 1153 | } 1154 | }, 1155 | { 1156 | "channel": 0, 1157 | "delta": 0, 1158 | "noteOn": { 1159 | "noteNumber": 63, 1160 | "velocity": 100 1161 | } 1162 | }, 1163 | { 1164 | "channel": 0, 1165 | "delta": 240, 1166 | "noteOff": { 1167 | "noteNumber": 63, 1168 | "velocity": 64 1169 | } 1170 | }, 1171 | { 1172 | "channel": 0, 1173 | "delta": 0, 1174 | "noteOn": { 1175 | "noteNumber": 64, 1176 | "velocity": 100 1177 | } 1178 | }, 1179 | { 1180 | "channel": 0, 1181 | "delta": 240, 1182 | "noteOff": { 1183 | "noteNumber": 64, 1184 | "velocity": 64 1185 | } 1186 | }, 1187 | { 1188 | "channel": 0, 1189 | "delta": 0, 1190 | "noteOn": { 1191 | "noteNumber": 65, 1192 | "velocity": 100 1193 | } 1194 | }, 1195 | { 1196 | "channel": 0, 1197 | "delta": 240, 1198 | "noteOff": { 1199 | "noteNumber": 65, 1200 | "velocity": 64 1201 | } 1202 | }, 1203 | { 1204 | "channel": 0, 1205 | "delta": 0, 1206 | "noteOn": { 1207 | "noteNumber": 66, 1208 | "velocity": 100 1209 | } 1210 | }, 1211 | { 1212 | "channel": 0, 1213 | "delta": 240, 1214 | "noteOff": { 1215 | "noteNumber": 66, 1216 | "velocity": 64 1217 | } 1218 | }, 1219 | { 1220 | "channel": 0, 1221 | "delta": 0, 1222 | "noteOn": { 1223 | "noteNumber": 67, 1224 | "velocity": 100 1225 | } 1226 | }, 1227 | { 1228 | "channel": 0, 1229 | "delta": 240, 1230 | "noteOff": { 1231 | "noteNumber": 67, 1232 | "velocity": 64 1233 | } 1234 | }, 1235 | { 1236 | "channel": 0, 1237 | "delta": 0, 1238 | "noteOn": { 1239 | "noteNumber": 68, 1240 | "velocity": 100 1241 | } 1242 | }, 1243 | { 1244 | "channel": 0, 1245 | "delta": 240, 1246 | "noteOff": { 1247 | "noteNumber": 68, 1248 | "velocity": 64 1249 | } 1250 | }, 1251 | { 1252 | "channel": 0, 1253 | "delta": 0, 1254 | "noteOn": { 1255 | "noteNumber": 69, 1256 | "velocity": 100 1257 | } 1258 | }, 1259 | { 1260 | "channel": 0, 1261 | "delta": 240, 1262 | "noteOff": { 1263 | "noteNumber": 69, 1264 | "velocity": 64 1265 | } 1266 | }, 1267 | { 1268 | "channel": 0, 1269 | "delta": 0, 1270 | "noteOn": { 1271 | "noteNumber": 70, 1272 | "velocity": 100 1273 | } 1274 | }, 1275 | { 1276 | "channel": 0, 1277 | "delta": 240, 1278 | "noteOff": { 1279 | "noteNumber": 70, 1280 | "velocity": 64 1281 | } 1282 | }, 1283 | { 1284 | "channel": 0, 1285 | "delta": 0, 1286 | "noteOn": { 1287 | "noteNumber": 71, 1288 | "velocity": 100 1289 | } 1290 | }, 1291 | { 1292 | "channel": 0, 1293 | "delta": 240, 1294 | "noteOff": { 1295 | "noteNumber": 71, 1296 | "velocity": 64 1297 | } 1298 | }, 1299 | { 1300 | "channel": 0, 1301 | "delta": 0, 1302 | "noteOn": { 1303 | "noteNumber": 72, 1304 | "velocity": 100 1305 | } 1306 | }, 1307 | { 1308 | "channel": 0, 1309 | "delta": 240, 1310 | "noteOff": { 1311 | "noteNumber": 72, 1312 | "velocity": 64 1313 | } 1314 | }, 1315 | { 1316 | "channel": 0, 1317 | "delta": 0, 1318 | "noteOn": { 1319 | "noteNumber": 73, 1320 | "velocity": 100 1321 | } 1322 | }, 1323 | { 1324 | "channel": 0, 1325 | "delta": 240, 1326 | "noteOff": { 1327 | "noteNumber": 73, 1328 | "velocity": 64 1329 | } 1330 | }, 1331 | { 1332 | "channel": 0, 1333 | "delta": 0, 1334 | "noteOn": { 1335 | "noteNumber": 74, 1336 | "velocity": 100 1337 | } 1338 | }, 1339 | { 1340 | "channel": 0, 1341 | "delta": 240, 1342 | "noteOff": { 1343 | "noteNumber": 74, 1344 | "velocity": 64 1345 | } 1346 | }, 1347 | { 1348 | "channel": 0, 1349 | "delta": 0, 1350 | "noteOn": { 1351 | "noteNumber": 75, 1352 | "velocity": 100 1353 | } 1354 | }, 1355 | { 1356 | "channel": 0, 1357 | "delta": 240, 1358 | "noteOff": { 1359 | "noteNumber": 75, 1360 | "velocity": 64 1361 | } 1362 | }, 1363 | { 1364 | "channel": 0, 1365 | "delta": 0, 1366 | "noteOn": { 1367 | "noteNumber": 36, 1368 | "velocity": 100 1369 | } 1370 | }, 1371 | { 1372 | "channel": 0, 1373 | "delta": 1920, 1374 | "noteOff": { 1375 | "noteNumber": 36, 1376 | "velocity": 64 1377 | } 1378 | }, 1379 | { 1380 | "channel": 0, 1381 | "delta": 0, 1382 | "noteOn": { 1383 | "noteNumber": 48, 1384 | "velocity": 100 1385 | } 1386 | }, 1387 | { 1388 | "channel": 0, 1389 | "delta": 1920, 1390 | "noteOff": { 1391 | "noteNumber": 48, 1392 | "velocity": 64 1393 | } 1394 | }, 1395 | { 1396 | "channel": 0, 1397 | "delta": 0, 1398 | "noteOn": { 1399 | "noteNumber": 72, 1400 | "velocity": 100 1401 | } 1402 | }, 1403 | { 1404 | "channel": 0, 1405 | "delta": 1920, 1406 | "noteOff": { 1407 | "noteNumber": 72, 1408 | "velocity": 64 1409 | } 1410 | }, 1411 | { 1412 | "delta": 0, 1413 | "endOfTrack": true 1414 | } 1415 | ] 1416 | ] 1417 | } 1418 | -------------------------------------------------------------------------------- /test/fixtures/scale.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/scale.mid -------------------------------------------------------------------------------- /test/fixtures/test.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/test.mid -------------------------------------------------------------------------------- /test/fixtures/test8bars.json: -------------------------------------------------------------------------------- 1 | { 2 | "division": 480, 3 | "format": 0, 4 | "tracks": [ 5 | [ 6 | { 7 | "delta": 0, 8 | "trackName": "Inst 1" 9 | }, 10 | { 11 | "delta": 0, 12 | "instrumentName": "Steinway Grand Piano" 13 | }, 14 | { 15 | "delta": 0, 16 | "timeSignature": { 17 | "denominator": 4, 18 | "metronome": 24, 19 | "numerator": 4, 20 | "thirtyseconds": 8 21 | } 22 | }, 23 | { 24 | "delta": 0, 25 | "keySignature": { 26 | "key": 0, 27 | "scale": 0 28 | } 29 | }, 30 | { 31 | "delta": 0, 32 | "smpteOffset": { 33 | "frame": 0, 34 | "frameRate": 25, 35 | "hour": 1, 36 | "minutes": 0, 37 | "seconds": 0, 38 | "subFrame": 0 39 | } 40 | }, 41 | { 42 | "delta": 0, 43 | "setTempo": { 44 | "microsecondsPerQuarter": 500000 45 | } 46 | }, 47 | { 48 | "channel": 0, 49 | "delta": 4, 50 | "noteOn": { 51 | "noteNumber": 36, 52 | "velocity": 72 53 | } 54 | }, 55 | { 56 | "channel": 0, 57 | "controlChange": { 58 | "type": 64, 59 | "value": 34 60 | }, 61 | "delta": 135 62 | }, 63 | { 64 | "channel": 0, 65 | "controlChange": { 66 | "type": 64, 67 | "value": 80 68 | }, 69 | "delta": 11 70 | }, 71 | { 72 | "channel": 0, 73 | "controlChange": { 74 | "type": 64, 75 | "value": 127 76 | }, 77 | "delta": 12 78 | }, 79 | { 80 | "channel": 0, 81 | "delta": 294, 82 | "noteOn": { 83 | "noteNumber": 36, 84 | "velocity": 0 85 | } 86 | }, 87 | { 88 | "channel": 0, 89 | "delta": 15, 90 | "noteOn": { 91 | "noteNumber": 43, 92 | "velocity": 55 93 | } 94 | }, 95 | { 96 | "channel": 0, 97 | "delta": 52, 98 | "noteOn": { 99 | "noteNumber": 43, 100 | "velocity": 0 101 | } 102 | }, 103 | { 104 | "channel": 0, 105 | "controlChange": { 106 | "type": 64, 107 | "value": 82 108 | }, 109 | "delta": 190 110 | }, 111 | { 112 | "channel": 0, 113 | "controlChange": { 114 | "type": 64, 115 | "value": 36 116 | }, 117 | "delta": 12 118 | }, 119 | { 120 | "channel": 0, 121 | "controlChange": { 122 | "type": 64, 123 | "value": 0 124 | }, 125 | "delta": 11 126 | }, 127 | { 128 | "channel": 0, 129 | "delta": 3, 130 | "noteOn": { 131 | "noteNumber": 58, 132 | "velocity": 77 133 | } 134 | }, 135 | { 136 | "channel": 0, 137 | "delta": 9, 138 | "noteOn": { 139 | "noteNumber": 72, 140 | "velocity": 74 141 | } 142 | }, 143 | { 144 | "channel": 0, 145 | "delta": 14, 146 | "noteOn": { 147 | "noteNumber": 53, 148 | "velocity": 41 149 | } 150 | }, 151 | { 152 | "channel": 0, 153 | "delta": 3, 154 | "noteOn": { 155 | "noteNumber": 65, 156 | "velocity": 58 157 | } 158 | }, 159 | { 160 | "channel": 0, 161 | "delta": 9, 162 | "noteOn": { 163 | "noteNumber": 67, 164 | "velocity": 64 165 | } 166 | }, 167 | { 168 | "channel": 0, 169 | "delta": 14, 170 | "noteOn": { 171 | "noteNumber": 48, 172 | "velocity": 35 173 | } 174 | }, 175 | { 176 | "channel": 0, 177 | "controlChange": { 178 | "type": 64, 179 | "value": 54 180 | }, 181 | "delta": 352 182 | }, 183 | { 184 | "channel": 0, 185 | "controlChange": { 186 | "type": 64, 187 | "value": 116 188 | }, 189 | "delta": 12 190 | }, 191 | { 192 | "channel": 0, 193 | "controlChange": { 194 | "type": 64, 195 | "value": 127 196 | }, 197 | "delta": 11 198 | }, 199 | { 200 | "channel": 0, 201 | "delta": 130, 202 | "noteOn": { 203 | "noteNumber": 53, 204 | "velocity": 0 205 | } 206 | }, 207 | { 208 | "channel": 0, 209 | "delta": 15, 210 | "noteOn": { 211 | "noteNumber": 48, 212 | "velocity": 0 213 | } 214 | }, 215 | { 216 | "channel": 0, 217 | "delta": 60, 218 | "noteOn": { 219 | "noteNumber": 58, 220 | "velocity": 0 221 | } 222 | }, 223 | { 224 | "channel": 0, 225 | "delta": 47, 226 | "noteOn": { 227 | "noteNumber": 67, 228 | "velocity": 0 229 | } 230 | }, 231 | { 232 | "channel": 0, 233 | "delta": 34, 234 | "noteOn": { 235 | "noteNumber": 65, 236 | "velocity": 0 237 | } 238 | }, 239 | { 240 | "channel": 0, 241 | "delta": 3, 242 | "noteOn": { 243 | "noteNumber": 72, 244 | "velocity": 0 245 | } 246 | }, 247 | { 248 | "channel": 0, 249 | "delta": 491, 250 | "noteOn": { 251 | "noteNumber": 60, 252 | "velocity": 61 253 | } 254 | }, 255 | { 256 | "channel": 0, 257 | "controlChange": { 258 | "type": 64, 259 | "value": 70 260 | }, 261 | "delta": 3 262 | }, 263 | { 264 | "channel": 0, 265 | "delta": 0, 266 | "noteOn": { 267 | "noteNumber": 70, 268 | "velocity": 64 269 | } 270 | }, 271 | { 272 | "channel": 0, 273 | "delta": 3, 274 | "noteOn": { 275 | "noteNumber": 74, 276 | "velocity": 63 277 | } 278 | }, 279 | { 280 | "channel": 0, 281 | "delta": 3, 282 | "noteOn": { 283 | "noteNumber": 55, 284 | "velocity": 61 285 | } 286 | }, 287 | { 288 | "channel": 0, 289 | "delta": 0, 290 | "noteOn": { 291 | "noteNumber": 67, 292 | "velocity": 47 293 | } 294 | }, 295 | { 296 | "channel": 0, 297 | "delta": 5, 298 | "noteOn": { 299 | "noteNumber": 50, 300 | "velocity": 50 301 | } 302 | }, 303 | { 304 | "channel": 0, 305 | "controlChange": { 306 | "type": 64, 307 | "value": 16 308 | }, 309 | "delta": 3 310 | }, 311 | { 312 | "channel": 0, 313 | "controlChange": { 314 | "type": 64, 315 | "value": 0 316 | }, 317 | "delta": 9 318 | }, 319 | { 320 | "channel": 0, 321 | "controlChange": { 322 | "type": 64, 323 | "value": 56 324 | }, 325 | "delta": 543 326 | }, 327 | { 328 | "channel": 0, 329 | "controlChange": { 330 | "type": 64, 331 | "value": 127 332 | }, 333 | "delta": 11 334 | }, 335 | { 336 | "channel": 0, 337 | "delta": 318, 338 | "noteOn": { 339 | "noteNumber": 60, 340 | "velocity": 0 341 | } 342 | }, 343 | { 344 | "channel": 0, 345 | "delta": 43, 346 | "noteOn": { 347 | "noteNumber": 55, 348 | "velocity": 0 349 | } 350 | }, 351 | { 352 | "channel": 0, 353 | "delta": 61, 354 | "noteOn": { 355 | "noteNumber": 50, 356 | "velocity": 0 357 | } 358 | }, 359 | { 360 | "channel": 0, 361 | "delta": 31, 362 | "noteOn": { 363 | "noteNumber": 70, 364 | "velocity": 0 365 | } 366 | }, 367 | { 368 | "channel": 0, 369 | "delta": 21, 370 | "noteOn": { 371 | "noteNumber": 74, 372 | "velocity": 0 373 | } 374 | }, 375 | { 376 | "channel": 0, 377 | "delta": 17, 378 | "noteOn": { 379 | "noteNumber": 67, 380 | "velocity": 0 381 | } 382 | }, 383 | { 384 | "channel": 0, 385 | "controlChange": { 386 | "type": 64, 387 | "value": 108 388 | }, 389 | "delta": 776 390 | }, 391 | { 392 | "channel": 0, 393 | "controlChange": { 394 | "type": 64, 395 | "value": 60 396 | }, 397 | "delta": 12 398 | }, 399 | { 400 | "channel": 0, 401 | "controlChange": { 402 | "type": 64, 403 | "value": 20 404 | }, 405 | "delta": 12 406 | }, 407 | { 408 | "channel": 0, 409 | "controlChange": { 410 | "type": 64, 411 | "value": 0 412 | }, 413 | "delta": 11 414 | }, 415 | { 416 | "channel": 0, 417 | "delta": 43, 418 | "noteOn": { 419 | "noteNumber": 79, 420 | "velocity": 51 421 | } 422 | }, 423 | { 424 | "channel": 0, 425 | "delta": 3, 426 | "noteOn": { 427 | "noteNumber": 70, 428 | "velocity": 55 429 | } 430 | }, 431 | { 432 | "channel": 0, 433 | "delta": 9, 434 | "noteOn": { 435 | "noteNumber": 36, 436 | "velocity": 57 437 | } 438 | }, 439 | { 440 | "channel": 0, 441 | "delta": 12, 442 | "noteOn": { 443 | "noteNumber": 43, 444 | "velocity": 59 445 | } 446 | }, 447 | { 448 | "channel": 0, 449 | "delta": 5, 450 | "noteOn": { 451 | "noteNumber": 67, 452 | "velocity": 41 453 | } 454 | }, 455 | { 456 | "channel": 0, 457 | "delta": 3, 458 | "noteOn": { 459 | "noteNumber": 48, 460 | "velocity": 44 461 | } 462 | }, 463 | { 464 | "channel": 0, 465 | "controlChange": { 466 | "type": 64, 467 | "value": 14 468 | }, 469 | "delta": 110 470 | }, 471 | { 472 | "channel": 0, 473 | "controlChange": { 474 | "type": 64, 475 | "value": 78 476 | }, 477 | "delta": 12 478 | }, 479 | { 480 | "channel": 0, 481 | "controlChange": { 482 | "type": 64, 483 | "value": 127 484 | }, 485 | "delta": 11 486 | }, 487 | { 488 | "channel": 0, 489 | "delta": 3, 490 | "noteOn": { 491 | "noteNumber": 36, 492 | "velocity": 0 493 | } 494 | }, 495 | { 496 | "channel": 0, 497 | "delta": 32, 498 | "noteOn": { 499 | "noteNumber": 43, 500 | "velocity": 0 501 | } 502 | }, 503 | { 504 | "channel": 0, 505 | "delta": 28, 506 | "noteOn": { 507 | "noteNumber": 48, 508 | "velocity": 0 509 | } 510 | }, 511 | { 512 | "channel": 0, 513 | "delta": 211, 514 | "noteOn": { 515 | "noteNumber": 70, 516 | "velocity": 0 517 | } 518 | }, 519 | { 520 | "channel": 0, 521 | "delta": 38, 522 | "noteOn": { 523 | "noteNumber": 79, 524 | "velocity": 0 525 | } 526 | }, 527 | { 528 | "channel": 0, 529 | "delta": 37, 530 | "noteOn": { 531 | "noteNumber": 67, 532 | "velocity": 0 533 | } 534 | }, 535 | { 536 | "channel": 0, 537 | "delta": 208, 538 | "noteOn": { 539 | "noteNumber": 58, 540 | "velocity": 71 541 | } 542 | }, 543 | { 544 | "channel": 0, 545 | "delta": 0, 546 | "noteOn": { 547 | "noteNumber": 72, 548 | "velocity": 61 549 | } 550 | }, 551 | { 552 | "channel": 0, 553 | "delta": 6, 554 | "noteOn": { 555 | "noteNumber": 79, 556 | "velocity": 51 557 | } 558 | }, 559 | { 560 | "channel": 0, 561 | "delta": 6, 562 | "noteOn": { 563 | "noteNumber": 67, 564 | "velocity": 51 565 | } 566 | }, 567 | { 568 | "channel": 0, 569 | "controlChange": { 570 | "type": 64, 571 | "value": 125 572 | }, 573 | "delta": 5 574 | }, 575 | { 576 | "channel": 0, 577 | "delta": 6, 578 | "noteOn": { 579 | "noteNumber": 53, 580 | "velocity": 57 581 | } 582 | }, 583 | { 584 | "channel": 0, 585 | "controlChange": { 586 | "type": 64, 587 | "value": 82 588 | }, 589 | "delta": 6 590 | }, 591 | { 592 | "channel": 0, 593 | "delta": 6, 594 | "noteOn": { 595 | "noteNumber": 48, 596 | "velocity": 43 597 | } 598 | }, 599 | { 600 | "channel": 0, 601 | "controlChange": { 602 | "type": 64, 603 | "value": 24 604 | }, 605 | "delta": 6 606 | }, 607 | { 608 | "channel": 0, 609 | "controlChange": { 610 | "type": 64, 611 | "value": 0 612 | }, 613 | "delta": 11 614 | }, 615 | { 616 | "channel": 0, 617 | "controlChange": { 618 | "type": 64, 619 | "value": 46 620 | }, 621 | "delta": 196 622 | }, 623 | { 624 | "channel": 0, 625 | "controlChange": { 626 | "type": 64, 627 | "value": 98 628 | }, 629 | "delta": 12 630 | }, 631 | { 632 | "channel": 0, 633 | "controlChange": { 634 | "type": 64, 635 | "value": 127 636 | }, 637 | "delta": 11 638 | }, 639 | { 640 | "channel": 0, 641 | "delta": 44, 642 | "noteOn": { 643 | "noteNumber": 53, 644 | "velocity": 0 645 | } 646 | }, 647 | { 648 | "channel": 0, 649 | "delta": 26, 650 | "noteOn": { 651 | "noteNumber": 48, 652 | "velocity": 0 653 | } 654 | }, 655 | { 656 | "channel": 0, 657 | "delta": 0, 658 | "noteOn": { 659 | "noteNumber": 58, 660 | "velocity": 0 661 | } 662 | }, 663 | { 664 | "channel": 0, 665 | "delta": 337, 666 | "noteOn": { 667 | "noteNumber": 67, 668 | "velocity": 0 669 | } 670 | }, 671 | { 672 | "channel": 0, 673 | "delta": 9, 674 | "noteOn": { 675 | "noteNumber": 72, 676 | "velocity": 0 677 | } 678 | }, 679 | { 680 | "channel": 0, 681 | "delta": 32, 682 | "noteOn": { 683 | "noteNumber": 79, 684 | "velocity": 0 685 | } 686 | }, 687 | { 688 | "channel": 0, 689 | "delta": 254, 690 | "noteOn": { 691 | "noteNumber": 74, 692 | "velocity": 53 693 | } 694 | }, 695 | { 696 | "channel": 0, 697 | "delta": 6, 698 | "noteOn": { 699 | "noteNumber": 67, 700 | "velocity": 59 701 | } 702 | }, 703 | { 704 | "channel": 0, 705 | "delta": 5, 706 | "noteOn": { 707 | "noteNumber": 60, 708 | "velocity": 59 709 | } 710 | }, 711 | { 712 | "channel": 0, 713 | "delta": 3, 714 | "noteOn": { 715 | "noteNumber": 50, 716 | "velocity": 52 717 | } 718 | }, 719 | { 720 | "channel": 0, 721 | "delta": 0, 722 | "noteOn": { 723 | "noteNumber": 55, 724 | "velocity": 57 725 | } 726 | }, 727 | { 728 | "channel": 0, 729 | "controlChange": { 730 | "type": 64, 731 | "value": 100 732 | }, 733 | "delta": 9 734 | }, 735 | { 736 | "channel": 0, 737 | "delta": 9, 738 | "noteOn": { 739 | "noteNumber": 79, 740 | "velocity": 48 741 | } 742 | }, 743 | { 744 | "channel": 0, 745 | "controlChange": { 746 | "type": 64, 747 | "value": 54 748 | }, 749 | "delta": 2 750 | }, 751 | { 752 | "channel": 0, 753 | "controlChange": { 754 | "type": 64, 755 | "value": 2 756 | }, 757 | "delta": 12 758 | }, 759 | { 760 | "channel": 0, 761 | "controlChange": { 762 | "type": 64, 763 | "value": 0 764 | }, 765 | "delta": 12 766 | }, 767 | { 768 | "channel": 0, 769 | "controlChange": { 770 | "type": 64, 771 | "value": 54 772 | }, 773 | "delta": 230 774 | }, 775 | { 776 | "channel": 0, 777 | "controlChange": { 778 | "type": 64, 779 | "value": 120 780 | }, 781 | "delta": 12 782 | }, 783 | { 784 | "channel": 0, 785 | "controlChange": { 786 | "type": 64, 787 | "value": 127 788 | }, 789 | "delta": 12 790 | }, 791 | { 792 | "channel": 0, 793 | "delta": 747, 794 | "noteOn": { 795 | "noteNumber": 60, 796 | "velocity": 0 797 | } 798 | }, 799 | { 800 | "channel": 0, 801 | "delta": 18, 802 | "noteOn": { 803 | "noteNumber": 55, 804 | "velocity": 0 805 | } 806 | }, 807 | { 808 | "channel": 0, 809 | "delta": 31, 810 | "noteOn": { 811 | "noteNumber": 50, 812 | "velocity": 0 813 | } 814 | }, 815 | { 816 | "channel": 0, 817 | "delta": 24, 818 | "noteOn": { 819 | "noteNumber": 79, 820 | "velocity": 0 821 | } 822 | }, 823 | { 824 | "channel": 0, 825 | "delta": 8, 826 | "noteOn": { 827 | "noteNumber": 67, 828 | "velocity": 0 829 | } 830 | }, 831 | { 832 | "channel": 0, 833 | "delta": 29, 834 | "noteOn": { 835 | "noteNumber": 74, 836 | "velocity": 0 837 | } 838 | }, 839 | { 840 | "channel": 0, 841 | "delta": 733, 842 | "noteOn": { 843 | "noteNumber": 43, 844 | "velocity": 61 845 | } 846 | }, 847 | { 848 | "channel": 0, 849 | "controlChange": { 850 | "type": 64, 851 | "value": 120 852 | }, 853 | "delta": 104 854 | }, 855 | { 856 | "channel": 0, 857 | "controlChange": { 858 | "type": 64, 859 | "value": 66 860 | }, 861 | "delta": 12 862 | }, 863 | { 864 | "channel": 0, 865 | "controlChange": { 866 | "type": 64, 867 | "value": 18 868 | }, 869 | "delta": 11 870 | }, 871 | { 872 | "channel": 0, 873 | "controlChange": { 874 | "type": 64, 875 | "value": 0 876 | }, 877 | "delta": 12 878 | }, 879 | { 880 | "channel": 0, 881 | "delta": 92, 882 | "noteOn": { 883 | "noteNumber": 43, 884 | "velocity": 0 885 | } 886 | }, 887 | { 888 | "channel": 0, 889 | "delta": 17, 890 | "noteOn": { 891 | "noteNumber": 36, 892 | "velocity": 83 893 | } 894 | }, 895 | { 896 | "channel": 0, 897 | "controlChange": { 898 | "type": 64, 899 | "value": 38 900 | }, 901 | "delta": 99 902 | }, 903 | { 904 | "channel": 0, 905 | "controlChange": { 906 | "type": 64, 907 | "value": 82 908 | }, 909 | "delta": 11 910 | }, 911 | { 912 | "channel": 0, 913 | "controlChange": { 914 | "type": 64, 915 | "value": 127 916 | }, 917 | "delta": 9 918 | }, 919 | { 920 | "channel": 0, 921 | "delta": 245, 922 | "noteOn": { 923 | "noteNumber": 36, 924 | "velocity": 0 925 | } 926 | }, 927 | { 928 | "channel": 0, 929 | "delta": 358, 930 | "noteOn": { 931 | "noteNumber": 58, 932 | "velocity": 77 933 | } 934 | }, 935 | { 936 | "channel": 0, 937 | "delta": 23, 938 | "noteOn": { 939 | "noteNumber": 53, 940 | "velocity": 53 941 | } 942 | }, 943 | { 944 | "channel": 0, 945 | "delta": 3, 946 | "noteOn": { 947 | "noteNumber": 48, 948 | "velocity": 53 949 | } 950 | }, 951 | { 952 | "channel": 0, 953 | "controlChange": { 954 | "type": 64, 955 | "value": 72 956 | }, 957 | "delta": 18 958 | }, 959 | { 960 | "channel": 0, 961 | "controlChange": { 962 | "type": 64, 963 | "value": 2 964 | }, 965 | "delta": 11 966 | }, 967 | { 968 | "channel": 0, 969 | "controlChange": { 970 | "type": 64, 971 | "value": 0 972 | }, 973 | "delta": 12 974 | }, 975 | { 976 | "channel": 0, 977 | "controlChange": { 978 | "type": 64, 979 | "value": 50 980 | }, 981 | "delta": 161 982 | }, 983 | { 984 | "channel": 0, 985 | "controlChange": { 986 | "type": 64, 987 | "value": 103 988 | }, 989 | "delta": 12 990 | }, 991 | { 992 | "channel": 0, 993 | "controlChange": { 994 | "type": 64, 995 | "value": 127 996 | }, 997 | "delta": 11 998 | }, 999 | { 1000 | "channel": 0, 1001 | "delta": 145, 1002 | "noteOn": { 1003 | "noteNumber": 53, 1004 | "velocity": 0 1005 | } 1006 | }, 1007 | { 1008 | "channel": 0, 1009 | "delta": 23, 1010 | "noteOn": { 1011 | "noteNumber": 65, 1012 | "velocity": 53 1013 | } 1014 | }, 1015 | { 1016 | "channel": 0, 1017 | "delta": 3, 1018 | "noteOn": { 1019 | "noteNumber": 48, 1020 | "velocity": 0 1021 | } 1022 | }, 1023 | { 1024 | "channel": 0, 1025 | "delta": 20, 1026 | "noteOn": { 1027 | "noteNumber": 58, 1028 | "velocity": 0 1029 | } 1030 | }, 1031 | { 1032 | "channel": 0, 1033 | "delta": 95, 1034 | "noteOn": { 1035 | "noteNumber": 65, 1036 | "velocity": 0 1037 | } 1038 | }, 1039 | { 1040 | "channel": 0, 1041 | "delta": 136, 1042 | "noteOn": { 1043 | "noteNumber": 67, 1044 | "velocity": 103 1045 | } 1046 | }, 1047 | { 1048 | "channel": 0, 1049 | "controlChange": { 1050 | "type": 64, 1051 | "value": 123 1052 | }, 1053 | "delta": 118 1054 | }, 1055 | { 1056 | "channel": 0, 1057 | "controlChange": { 1058 | "type": 64, 1059 | "value": 113 1060 | }, 1061 | "delta": 12 1062 | }, 1063 | { 1064 | "channel": 0, 1065 | "controlChange": { 1066 | "type": 64, 1067 | "value": 103 1068 | }, 1069 | "delta": 11 1070 | }, 1071 | { 1072 | "channel": 0, 1073 | "delta": 9, 1074 | "noteOn": { 1075 | "noteNumber": 67, 1076 | "velocity": 0 1077 | } 1078 | }, 1079 | { 1080 | "channel": 0, 1081 | "controlChange": { 1082 | "type": 64, 1083 | "value": 88 1084 | }, 1085 | "delta": 3 1086 | }, 1087 | { 1088 | "channel": 0, 1089 | "controlChange": { 1090 | "type": 64, 1091 | "value": 68 1092 | }, 1093 | "delta": 11 1094 | }, 1095 | { 1096 | "channel": 0, 1097 | "controlChange": { 1098 | "type": 64, 1099 | "value": 42 1100 | }, 1101 | "delta": 13 1102 | }, 1103 | { 1104 | "channel": 0, 1105 | "controlChange": { 1106 | "type": 64, 1107 | "value": 2 1108 | }, 1109 | "delta": 11 1110 | }, 1111 | { 1112 | "channel": 0, 1113 | "controlChange": { 1114 | "type": 64, 1115 | "value": 0 1116 | }, 1117 | "delta": 11 1118 | }, 1119 | { 1120 | "channel": 0, 1121 | "delta": 40, 1122 | "noteOn": { 1123 | "noteNumber": 67, 1124 | "velocity": 72 1125 | } 1126 | }, 1127 | { 1128 | "channel": 0, 1129 | "delta": 18, 1130 | "noteOn": { 1131 | "noteNumber": 60, 1132 | "velocity": 71 1133 | } 1134 | }, 1135 | { 1136 | "channel": 0, 1137 | "delta": 3, 1138 | "noteOn": { 1139 | "noteNumber": 55, 1140 | "velocity": 68 1141 | } 1142 | }, 1143 | { 1144 | "channel": 0, 1145 | "delta": 3, 1146 | "noteOn": { 1147 | "noteNumber": 50, 1148 | "velocity": 66 1149 | } 1150 | }, 1151 | { 1152 | "channel": 0, 1153 | "controlChange": { 1154 | "type": 64, 1155 | "value": 16 1156 | }, 1157 | "delta": 202 1158 | }, 1159 | { 1160 | "channel": 0, 1161 | "controlChange": { 1162 | "type": 64, 1163 | "value": 80 1164 | }, 1165 | "delta": 11 1166 | }, 1167 | { 1168 | "channel": 0, 1169 | "controlChange": { 1170 | "type": 64, 1171 | "value": 127 1172 | }, 1173 | "delta": 12 1174 | }, 1175 | { 1176 | "channel": 0, 1177 | "delta": 534, 1178 | "noteOn": { 1179 | "noteNumber": 60, 1180 | "velocity": 0 1181 | } 1182 | }, 1183 | { 1184 | "channel": 0, 1185 | "delta": 29, 1186 | "noteOn": { 1187 | "noteNumber": 55, 1188 | "velocity": 0 1189 | } 1190 | }, 1191 | { 1192 | "channel": 0, 1193 | "delta": 69, 1194 | "noteOn": { 1195 | "noteNumber": 50, 1196 | "velocity": 0 1197 | } 1198 | }, 1199 | { 1200 | "channel": 0, 1201 | "delta": 72, 1202 | "noteOn": { 1203 | "noteNumber": 55, 1204 | "velocity": 66 1205 | } 1206 | }, 1207 | { 1208 | "channel": 0, 1209 | "delta": 46, 1210 | "noteOn": { 1211 | "noteNumber": 55, 1212 | "velocity": 0 1213 | } 1214 | }, 1215 | { 1216 | "channel": 0, 1217 | "delta": 67, 1218 | "noteOn": { 1219 | "noteNumber": 67, 1220 | "velocity": 0 1221 | } 1222 | }, 1223 | { 1224 | "channel": 0, 1225 | "delta": 124, 1226 | "noteOn": { 1227 | "noteNumber": 70, 1228 | "velocity": 94 1229 | } 1230 | }, 1231 | { 1232 | "channel": 0, 1233 | "delta": 109, 1234 | "noteOn": { 1235 | "noteNumber": 70, 1236 | "velocity": 0 1237 | } 1238 | }, 1239 | { 1240 | "channel": 0, 1241 | "controlChange": { 1242 | "type": 64, 1243 | "value": 100 1244 | }, 1245 | "delta": 44 1246 | }, 1247 | { 1248 | "channel": 0, 1249 | "controlChange": { 1250 | "type": 64, 1251 | "value": 52 1252 | }, 1253 | "delta": 12 1254 | }, 1255 | { 1256 | "channel": 0, 1257 | "controlChange": { 1258 | "type": 64, 1259 | "value": 12 1260 | }, 1261 | "delta": 11 1262 | }, 1263 | { 1264 | "channel": 0, 1265 | "controlChange": { 1266 | "type": 64, 1267 | "value": 0 1268 | }, 1269 | "delta": 12 1270 | }, 1271 | { 1272 | "channel": 0, 1273 | "delta": 60, 1274 | "noteOn": { 1275 | "noteNumber": 72, 1276 | "velocity": 105 1277 | } 1278 | }, 1279 | { 1280 | "channel": 0, 1281 | "delta": 107, 1282 | "noteOn": { 1283 | "noteNumber": 72, 1284 | "velocity": 0 1285 | } 1286 | }, 1287 | { 1288 | "channel": 0, 1289 | "delta": 124, 1290 | "noteOn": { 1291 | "noteNumber": 72, 1292 | "velocity": 103 1293 | } 1294 | }, 1295 | { 1296 | "channel": 0, 1297 | "delta": 121, 1298 | "noteOn": { 1299 | "noteNumber": 74, 1300 | "velocity": 84 1301 | } 1302 | }, 1303 | { 1304 | "channel": 0, 1305 | "delta": 6, 1306 | "noteOn": { 1307 | "noteNumber": 72, 1308 | "velocity": 0 1309 | } 1310 | }, 1311 | { 1312 | "channel": 0, 1313 | "delta": 61, 1314 | "noteOn": { 1315 | "noteNumber": 43, 1316 | "velocity": 55 1317 | } 1318 | }, 1319 | { 1320 | "channel": 0, 1321 | "delta": 104, 1322 | "noteOn": { 1323 | "noteNumber": 74, 1324 | "velocity": 0 1325 | } 1326 | }, 1327 | { 1328 | "channel": 0, 1329 | "delta": 2, 1330 | "noteOn": { 1331 | "noteNumber": 70, 1332 | "velocity": 72 1333 | } 1334 | }, 1335 | { 1336 | "channel": 0, 1337 | "delta": 116, 1338 | "noteOn": { 1339 | "noteNumber": 70, 1340 | "velocity": 0 1341 | } 1342 | }, 1343 | { 1344 | "channel": 0, 1345 | "delta": 60, 1346 | "noteOn": { 1347 | "noteNumber": 43, 1348 | "velocity": 0 1349 | } 1350 | }, 1351 | { 1352 | "channel": 0, 1353 | "delta": 26, 1354 | "noteOn": { 1355 | "noteNumber": 36, 1356 | "velocity": 72 1357 | } 1358 | }, 1359 | { 1360 | "channel": 0, 1361 | "delta": 13, 1362 | "noteOn": { 1363 | "noteNumber": 67, 1364 | "velocity": 76 1365 | } 1366 | }, 1367 | { 1368 | "channel": 0, 1369 | "controlChange": { 1370 | "type": 64, 1371 | "value": 22 1372 | }, 1373 | "delta": 31 1374 | }, 1375 | { 1376 | "channel": 0, 1377 | "controlChange": { 1378 | "type": 64, 1379 | "value": 106 1380 | }, 1381 | "delta": 9 1382 | }, 1383 | { 1384 | "channel": 0, 1385 | "controlChange": { 1386 | "type": 64, 1387 | "value": 127 1388 | }, 1389 | "delta": 11 1390 | }, 1391 | { 1392 | "channel": 0, 1393 | "delta": 170, 1394 | "noteOn": { 1395 | "noteNumber": 36, 1396 | "velocity": 0 1397 | } 1398 | }, 1399 | { 1400 | "channel": 0, 1401 | "delta": 9, 1402 | "noteOn": { 1403 | "noteNumber": 43, 1404 | "velocity": 38 1405 | } 1406 | }, 1407 | { 1408 | "channel": 0, 1409 | "delta": 58, 1410 | "noteOn": { 1411 | "noteNumber": 43, 1412 | "velocity": 0 1413 | } 1414 | }, 1415 | { 1416 | "channel": 0, 1417 | "delta": 144, 1418 | "noteOn": { 1419 | "noteNumber": 67, 1420 | "velocity": 0 1421 | } 1422 | }, 1423 | { 1424 | "channel": 0, 1425 | "delta": 309, 1426 | "noteOn": { 1427 | "noteNumber": 70, 1428 | "velocity": 76 1429 | } 1430 | }, 1431 | { 1432 | "channel": 0, 1433 | "controlChange": { 1434 | "type": 64, 1435 | "value": 123 1436 | }, 1437 | "delta": 3 1438 | }, 1439 | { 1440 | "channel": 0, 1441 | "delta": 3, 1442 | "noteOn": { 1443 | "noteNumber": 79, 1444 | "velocity": 72 1445 | } 1446 | }, 1447 | { 1448 | "channel": 0, 1449 | "delta": 3, 1450 | "noteOn": { 1451 | "noteNumber": 58, 1452 | "velocity": 81 1453 | } 1454 | }, 1455 | { 1456 | "channel": 0, 1457 | "controlChange": { 1458 | "type": 64, 1459 | "value": 82 1460 | }, 1461 | "delta": 5 1462 | }, 1463 | { 1464 | "channel": 0, 1465 | "controlChange": { 1466 | "type": 64, 1467 | "value": 26 1468 | }, 1469 | "delta": 12 1470 | }, 1471 | { 1472 | "channel": 0, 1473 | "delta": 6, 1474 | "noteOn": { 1475 | "noteNumber": 48, 1476 | "velocity": 59 1477 | } 1478 | }, 1479 | { 1480 | "channel": 0, 1481 | "controlChange": { 1482 | "type": 64, 1483 | "value": 0 1484 | }, 1485 | "delta": 6 1486 | }, 1487 | { 1488 | "channel": 0, 1489 | "delta": 0, 1490 | "noteOn": { 1491 | "noteNumber": 53, 1492 | "velocity": 55 1493 | } 1494 | }, 1495 | { 1496 | "channel": 0, 1497 | "controlChange": { 1498 | "type": 64, 1499 | "value": 48 1500 | }, 1501 | "delta": 231 1502 | }, 1503 | { 1504 | "channel": 0, 1505 | "controlChange": { 1506 | "type": 64, 1507 | "value": 125 1508 | }, 1509 | "delta": 11 1510 | }, 1511 | { 1512 | "channel": 0, 1513 | "controlChange": { 1514 | "type": 64, 1515 | "value": 127 1516 | }, 1517 | "delta": 12 1518 | }, 1519 | { 1520 | "channel": 0, 1521 | "delta": 124, 1522 | "noteOn": { 1523 | "noteNumber": 48, 1524 | "velocity": 0 1525 | } 1526 | }, 1527 | { 1528 | "channel": 0, 1529 | "delta": 0, 1530 | "noteOn": { 1531 | "noteNumber": 53, 1532 | "velocity": 0 1533 | } 1534 | }, 1535 | { 1536 | "channel": 0, 1537 | "delta": 14, 1538 | "noteOn": { 1539 | "noteNumber": 58, 1540 | "velocity": 0 1541 | } 1542 | }, 1543 | { 1544 | "channel": 0, 1545 | "delta": 29, 1546 | "noteOn": { 1547 | "noteNumber": 70, 1548 | "velocity": 0 1549 | } 1550 | }, 1551 | { 1552 | "channel": 0, 1553 | "delta": 29, 1554 | "noteOn": { 1555 | "noteNumber": 79, 1556 | "velocity": 0 1557 | } 1558 | }, 1559 | { 1560 | "channel": 0, 1561 | "controlChange": { 1562 | "type": 64, 1563 | "value": 120 1564 | }, 1565 | "delta": 413 1566 | }, 1567 | { 1568 | "channel": 0, 1569 | "controlChange": { 1570 | "type": 64, 1571 | "value": 90 1572 | }, 1573 | "delta": 11 1574 | }, 1575 | { 1576 | "channel": 0, 1577 | "controlChange": { 1578 | "type": 64, 1579 | "value": 50 1580 | }, 1581 | "delta": 12 1582 | }, 1583 | { 1584 | "channel": 0, 1585 | "controlChange": { 1586 | "type": 64, 1587 | "value": 8 1588 | }, 1589 | "delta": 11 1590 | }, 1591 | { 1592 | "channel": 0, 1593 | "controlChange": { 1594 | "type": 64, 1595 | "value": 0 1596 | }, 1597 | "delta": 12 1598 | }, 1599 | { 1600 | "channel": 0, 1601 | "delta": 43, 1602 | "noteOn": { 1603 | "noteNumber": 77, 1604 | "velocity": 59 1605 | } 1606 | }, 1607 | { 1608 | "channel": 0, 1609 | "delta": 3, 1610 | "noteOn": { 1611 | "noteNumber": 60, 1612 | "velocity": 50 1613 | } 1614 | }, 1615 | { 1616 | "channel": 0, 1617 | "delta": 3, 1618 | "noteOn": { 1619 | "noteNumber": 50, 1620 | "velocity": 46 1621 | } 1622 | }, 1623 | { 1624 | "channel": 0, 1625 | "delta": 9, 1626 | "noteOn": { 1627 | "noteNumber": 72, 1628 | "velocity": 61 1629 | } 1630 | }, 1631 | { 1632 | "channel": 0, 1633 | "delta": 2, 1634 | "noteOn": { 1635 | "noteNumber": 55, 1636 | "velocity": 59 1637 | } 1638 | }, 1639 | { 1640 | "channel": 0, 1641 | "delta": 3, 1642 | "noteOn": { 1643 | "noteNumber": 67, 1644 | "velocity": 51 1645 | } 1646 | }, 1647 | { 1648 | "channel": 0, 1649 | "controlChange": { 1650 | "type": 64, 1651 | "value": 60 1652 | }, 1653 | "delta": 76 1654 | }, 1655 | { 1656 | "channel": 0, 1657 | "controlChange": { 1658 | "type": 64, 1659 | "value": 127 1660 | }, 1661 | "delta": 11 1662 | }, 1663 | { 1664 | "channel": 0, 1665 | "delta": 26, 1666 | "noteOn": { 1667 | "noteNumber": 67, 1668 | "velocity": 0 1669 | } 1670 | }, 1671 | { 1672 | "channel": 0, 1673 | "delta": 0, 1674 | "noteOn": { 1675 | "noteNumber": 72, 1676 | "velocity": 0 1677 | } 1678 | }, 1679 | { 1680 | "channel": 0, 1681 | "delta": 20, 1682 | "noteOn": { 1683 | "noteNumber": 60, 1684 | "velocity": 0 1685 | } 1686 | }, 1687 | { 1688 | "channel": 0, 1689 | "delta": 3, 1690 | "noteOn": { 1691 | "noteNumber": 77, 1692 | "velocity": 0 1693 | } 1694 | }, 1695 | { 1696 | "channel": 0, 1697 | "delta": 6, 1698 | "noteOn": { 1699 | "noteNumber": 50, 1700 | "velocity": 0 1701 | } 1702 | }, 1703 | { 1704 | "channel": 0, 1705 | "delta": 6, 1706 | "noteOn": { 1707 | "noteNumber": 55, 1708 | "velocity": 0 1709 | } 1710 | }, 1711 | { 1712 | "channel": 0, 1713 | "controlChange": { 1714 | "type": 64, 1715 | "value": 78 1716 | }, 1717 | "delta": 1815 1718 | }, 1719 | { 1720 | "channel": 0, 1721 | "controlChange": { 1722 | "type": 64, 1723 | "value": 14 1724 | }, 1725 | "delta": 13 1726 | }, 1727 | { 1728 | "channel": 0, 1729 | "controlChange": { 1730 | "type": 64, 1731 | "value": 0 1732 | }, 1733 | "delta": 11 1734 | }, 1735 | { 1736 | "delta": 0, 1737 | "endOfTrack": true 1738 | } 1739 | ] 1740 | ] 1741 | } 1742 | -------------------------------------------------------------------------------- /test/fixtures/test8bars.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisguttandin/json-midi-encoder/707991410c90b8b2860560e380251e196e7afb89/test/fixtures/test8bars.mid -------------------------------------------------------------------------------- /test/helper/filenames.js: -------------------------------------------------------------------------------- 1 | export const filenames = [ 2 | '26-2', 3 | '98137', 4 | 'A_F_NO7_01', 5 | 'MIDIOkFormat1-lyrics', 6 | 'MIDIOkFormat2', 7 | 'MorozovS07', 8 | 'SubTractor 1', 9 | 'SubTractor 2', 10 | 'TheEntertainer', 11 | 'because', 12 | 'californication', 13 | 'minute_waltz', 14 | 'rachmaninov3', 15 | 'scale', 16 | 'test', 17 | 'test8bars' 18 | ]; 19 | -------------------------------------------------------------------------------- /test/helper/load-fixture.js: -------------------------------------------------------------------------------- 1 | export const loadFixtureAsArrayBuffer = (fixture) => fetch(`/base/test/fixtures/${fixture}`).then((response) => response.arrayBuffer()); 2 | 3 | export const loadFixtureAsJson = (fixture) => fetch(`/base/test/fixtures/${fixture}`).then((response) => response.json()); 4 | -------------------------------------------------------------------------------- /test/unit/module.js: -------------------------------------------------------------------------------- 1 | import * as jsonMidiEncoder from '../../src/module'; 2 | import { loadFixtureAsArrayBuffer, loadFixtureAsJson } from '../helper/load-fixture'; 3 | import { filenames } from '../helper/filenames'; 4 | 5 | describe('module', () => { 6 | describe('encode()', () => { 7 | for (const filename of filenames) { 8 | describe('with a json object', () => { 9 | let arrayBuffer; 10 | let json; 11 | 12 | beforeEach(async function () { 13 | this.timeout(20000); 14 | 15 | arrayBuffer = await loadFixtureAsArrayBuffer(`${filename}.mid`); 16 | json = await loadFixtureAsJson(`${filename}.json`); 17 | }); 18 | 19 | it('should encode the json object', async function () { 20 | this.timeout(20000); 21 | 22 | const midiFile = await jsonMidiEncoder.encode(json); 23 | 24 | expect(new Uint8Array(midiFile)).to.deep.equal(new Uint8Array(arrayBuffer)); 25 | }); 26 | }); 27 | 28 | describe('with a binary file', () => { 29 | let arrayBuffer; 30 | 31 | beforeEach(async function () { 32 | this.timeout(20000); 33 | 34 | arrayBuffer = await loadFixtureAsArrayBuffer(`${filename}.mid`); 35 | }); 36 | 37 | it('should refuse to encode the file', function (done) { 38 | jsonMidiEncoder.encode(arrayBuffer).catch((err) => { 39 | expect(err.message).to.equal('The given JSON object seems to be invalid.'); 40 | 41 | done(); 42 | }); 43 | }); 44 | }); 45 | } 46 | }); 47 | }); 48 | --------------------------------------------------------------------------------