diff --git a/package-lock.json b/package-lock.json index 579657c2..1b469861 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3951,6 +3951,15 @@ "node": ">=0.10" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -4959,6 +4968,29 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -5138,6 +5170,18 @@ "node": ">= 0.12" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -6620,11 +6664,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -6935,11 +6974,6 @@ "node": ">=10" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -7596,6 +7630,25 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -9726,16 +9779,6 @@ "resolved": "https://registry.npmjs.org/shift-spec/-/shift-spec-2018.0.0.tgz", "integrity": "sha512-/aiPOkj7dbe+CV2VZhIMTHQToZmgniofpRG7Yr7x2/0sO6CSVC++py1Wzf+s+rWSTDHKcLvziVAxjRRV4i4EoQ==" }, - "node_modules/shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -10572,77 +10615,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typedoc": { - "version": "0.22.17", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.17.tgz", - "integrity": "sha512-h6+uXHVVCPDaANzjwzdsj9aePBjZiBTpiMpBBeyh1zcN2odVsDCNajz8zyKnixF93HJeGpl34j/70yoEE5BfNg==", - "dependencies": { - "glob": "^8.0.3", - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 12.10.0" - }, - "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" - } - }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", @@ -10891,16 +10863,6 @@ } } }, - "node_modules/vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==" - }, - "node_modules/vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==" - }, "node_modules/w3c-keyname": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", @@ -10924,12 +10886,13 @@ "defaults": "^1.0.3" } }, - "node_modules/webaudiofont": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webaudiofont/-/webaudiofont-3.0.1.tgz", - "integrity": "sha512-PwqbR4OdvzbW8/TLTitSU/rw4mxMKyAGTKV42mePCgMoUGLJoQj8HDLWVqtNOpUZ0ghPNhNE6cRFEv6HFFEBQA==", - "dependencies": { - "typedoc": "^0.22.14" + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "dev": true, + "engines": { + "node": ">= 8" } }, "node_modules/WebDirt": { @@ -11528,10 +11491,33 @@ "license": "AGPL-3.0-or-later" }, "packages/soundfonts": { + "name": "@strudel.cycles/soundfonts", "version": "0.1.0", "license": "AGPL-3.0-or-later", "dependencies": { - "webaudiofont": "^3.0.1" + "@strudel.cycles/core": "*", + "@strudel.cycles/webaudio": "*" + }, + "devDependencies": { + "node-fetch": "^3.2.6" + } + }, + "packages/soundfonts/node_modules/node-fetch": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.6.tgz", + "integrity": "sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "packages/tonal": { @@ -13507,7 +13493,22 @@ "@strudel.cycles/soundfonts": { "version": "file:packages/soundfonts", "requires": { - "webaudiofont": "^3.0.1" + "@strudel.cycles/core": "*", + "@strudel.cycles/webaudio": "*", + "node-fetch": "^3.2.6" + }, + "dependencies": { + "node-fetch": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.6.tgz", + "integrity": "sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + } } }, "@strudel.cycles/tonal": { @@ -14934,6 +14935,12 @@ "assert-plus": "^1.0.0" } }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "dev": true + }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -15607,6 +15614,16 @@ "reusify": "^1.0.4" } }, + "fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "dev": true, + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -15735,6 +15752,15 @@ "mime-types": "^2.1.12" } }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "requires": { + "fetch-blob": "^3.1.2" + } + }, "fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -16858,11 +16884,6 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" - }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -17118,11 +17139,6 @@ "yallist": "^4.0.0" } }, - "lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -17621,6 +17637,12 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -19299,16 +19321,6 @@ } } }, - "shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", - "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -19967,54 +19979,6 @@ "is-typedarray": "^1.0.0" } }, - "typedoc": { - "version": "0.22.17", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.17.tgz", - "integrity": "sha512-h6+uXHVVCPDaANzjwzdsj9aePBjZiBTpiMpBBeyh1zcN2odVsDCNajz8zyKnixF93HJeGpl34j/70yoEE5BfNg==", - "requires": { - "glob": "^8.0.3", - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "peer": true - }, "typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", @@ -20203,16 +20167,6 @@ "rollup": "^2.59.0" } }, - "vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==" - }, - "vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==" - }, "w3c-keyname": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", @@ -20233,13 +20187,11 @@ "defaults": "^1.0.3" } }, - "webaudiofont": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webaudiofont/-/webaudiofont-3.0.1.tgz", - "integrity": "sha512-PwqbR4OdvzbW8/TLTitSU/rw4mxMKyAGTKV42mePCgMoUGLJoQj8HDLWVqtNOpUZ0ghPNhNE6cRFEv6HFFEBQA==", - "requires": { - "typedoc": "^0.22.14" - } + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "dev": true }, "WebDirt": { "version": "git+ssh://git@github.com/dktr0/WebDirt.git#425dc8fd023440d9c61ffdb8642e44e2710faea0", diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index c6f96263..a04cd706 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -27,6 +27,7 @@ const generic_params = [ * */ ['s', 's', 'sound'], + ['sf', 'sf', 'soundfont'], /** * The note or sample number to choose for a synth or sampleset * Note names currently not working yet, but will hopefully soon. Just stick to numbers for now diff --git a/packages/soundfonts/convert.js b/packages/soundfonts/convert.js new file mode 100644 index 00000000..91ecfc6c --- /dev/null +++ b/packages/soundfonts/convert.js @@ -0,0 +1,13 @@ +// this script converts a soundfont into a json file, it has not been not used yet +import fetch from 'node-fetch'; + +const name = '0000_JCLive'; + +const js = await fetch(`https://surikov.github.io/webaudiofontdata/sound/${name}_sf2_file.js`).then((res) => + res.text(), +); +// console.log(js); + +let [_, data] = js.split('_sf2_file='); +data = eval(data); +console.log(JSON.stringify(data)); diff --git a/packages/soundfonts/fontloader.mjs b/packages/soundfonts/fontloader.mjs new file mode 100644 index 00000000..09841780 --- /dev/null +++ b/packages/soundfonts/fontloader.mjs @@ -0,0 +1,108 @@ +let loadCache = {}; +async function loadFont(name) { + if (loadCache[name]) { + return loadCache[name]; + } + const load = async () => { + // TODO: make soundfont source configurable + const url = `https://surikov.github.io/webaudiofontdata/sound/${name}.js`; + console.log('load font', name, url); + const preset = await fetch(url).then((res) => res.text()); + let [_, data] = preset.split('={'); + return eval('{' + data); + }; + loadCache[name] = load(); + return loadCache[name]; +} + +let bufferCache = {}; +export async function getFontBufferSource(name, pitch, ac) { + const key = `${name}:::${pitch}`; + if (bufferCache[key]) { + return (await bufferCache[key])(); + } + // console.log('load buffer', key); + const load = async () => { + const preset = await loadFont(name); + if (!preset) { + throw new Error(`Could not load soundfont ${name}`); + } + const zone = findZone(preset, pitch); + if (!zone) { + throw new Error('no soundfont zone found for preset ', name, 'pitch', pitch); + } + const buffer = await getBuffer(zone, ac); + if (!buffer) { + throw new Error(`no soundfont buffer found for preset ${name}, pitch: ${pitch}`); + } + return () => { + const src = ac.createBufferSource(); + src.buffer = buffer; + const baseDetune = zone.originalPitch - 100.0 * zone.coarseTune - zone.fineTune; + const playbackRate = 1.0 * Math.pow(2, (100.0 * pitch - baseDetune) / 1200.0); + // src detune? + src.playbackRate.value = playbackRate; + const loop = zone.loopStart > 1 && zone.loopStart < zone.loopEnd; + if (!loop) { + /* const waveDuration = duration + this.afterTime; + if (waveDuration > zone.buffer.duration / playbackRate) { + waveDuration = zone.buffer.duration / playbackRate; + // TODO: do sth with waveduration + } */ + } else { + src.loop = true; + /* src.loopStart = zone.loopStart / zone.sampleRate + (zone.delay ? zone.delay : 0); + src.loopEnd = zone.loopEnd / zone.sampleRate + (zone.delay ? zone.delay : 0); */ + } + + return src; + }; + }; + bufferCache[key] = load(); // dont await here to cache promise immediately! + return (await bufferCache[key])(); +} + +function findZone(preset, pitch) { + return preset.find((zone) => { + return zone.keyRangeLow <= pitch && zone.keyRangeHigh + 1 >= pitch; + }); +} + +// promisified version of https://github.com/felixroos/webaudiofont/blob/c6f97249b60dcfafc20fca5bb381294a6b2f8f51/npm/dist/WebAudioFontPlayer.js#L740 +async function getBuffer(zone, audioContext) { + if (zone.sample) { + console.warn('zone.sample untested!'); + const decoded = atob(zone.sample); + zone.buffer = audioContext.createBuffer(1, decoded.length / 2, zone.sampleRate); + const float32Array = zone.buffer.getChannelData(0); + let b1, b2, n; + for (var i = 0; i < decoded.length / 2; i++) { + b1 = decoded.charCodeAt(i * 2); + b2 = decoded.charCodeAt(i * 2 + 1); + if (b1 < 0) { + b1 = 256 + b1; + } + if (b2 < 0) { + b2 = 256 + b2; + } + n = b2 * 256 + b1; + if (n >= 65536 / 2) { + n = n - 65536; + } + float32Array[i] = n / 65536.0; + } + } else { + if (zone.file) { + const datalen = zone.file.length; + const arraybuffer = new ArrayBuffer(datalen); + const view = new Uint8Array(arraybuffer); + const decoded = atob(zone.file); + let b; + for (let i = 0; i < decoded.length; i++) { + b = decoded.charCodeAt(i); + view[i] = b; + } + return new Promise((resolve) => audioContext.decodeAudioData(arraybuffer, resolve)); + } + } +} diff --git a/packages/soundfonts/index.mjs b/packages/soundfonts/index.mjs index 4bc56730..f5156cf1 100644 --- a/packages/soundfonts/index.mjs +++ b/packages/soundfonts/index.mjs @@ -1,29 +1,6 @@ -import { Pattern } from '@strudel.cycles/core'; -import { getAudioContext } from '@strudel.cycles/webaudio'; -// import * as WebAudioFontPlayer from 'webaudiofont'; -import * as WebAudioFont from 'webaudiofont'; -console.log('WebAudioFont:!', WebAudioFont); -// https://surikov.github.io/webaudiofont/npm/dist/WebAudioFontPlayer.js -// https://surikov.github.io/webaudiofontdata/sound/0000_JCLive_sf2_file.js +import { getFontBufferSource } from './fontloader.mjs'; +import * as soundfontList from './list.mjs'; -// https://github.com/surikov/webaudiofont#dynamic-loading -/* function changeInstrument(path, name) { - player.loader.startLoad(audioContext, path, name); - player.loader.waitLoad(function () { - instr = window[name]; - }); -} */ - -Pattern.prototype.soundfont = function (soundfont) { - const ac = getAudioContext(); - return this.onTrigger((t, hap, ct) => { - // const url = `https://surikov.github.io/webaudiofontdata/sound/${soundfont}_sf2_file.js`; - // changeInstrument('https://surikov.github.io/webaudiofontdata/sound/0290_Aspirin_sf2_file.js','_tone_0290_Aspirin_sf2_file'); - console.log('url', url); - // const player = WebAudioFontPlayer(); - // console.log('soundfont', url, player); - /* var selectedPreset = _tone_0000_JCLive_sf2_file; - player.loader.decodeAfterLoading(ac, '_tone_0000_JCLive_sf2_file'); - player.queueWaveTable(ac, ac.destination, selectedPreset, 0, 55, 3.5); */ - }); -}; +globalThis.getFontBufferSource = getFontBufferSource; +globalThis.soundfontList = soundfontList; +globalThis.soundfontList = soundfontList; diff --git a/packages/soundfonts/list.mjs b/packages/soundfonts/list.mjs new file mode 100644 index 00000000..69396a1d --- /dev/null +++ b/packages/soundfonts/list.mjs @@ -0,0 +1,1767 @@ +export const instruments = [ + '0000_JCLive_sf2_file', + '0000_Aspirin_sf2_file', + '0000_Chaos_sf2_file', + '0000_FluidR3_GM_sf2_file', + '0000_GeneralUserGS_sf2_file', + '0000_SBLive_sf2', + '0000_SoundBlasterOld_sf2', + '0001_FluidR3_GM_sf2_file', + '0001_GeneralUserGS_sf2_file', + '0002_GeneralUserGS_sf2_file', + '0003_GeneralUserGS_sf2_file', + '0010_Aspirin_sf2_file', + '0010_Chaos_sf2_file', + '0010_FluidR3_GM_sf2_file', + '0010_GeneralUserGS_sf2_file', + '0010_JCLive_sf2_file', + '0010_SBLive_sf2', + '0010_SoundBlasterOld_sf2', + '0011_Aspirin_sf2_file', + '0011_FluidR3_GM_sf2_file', + '0011_GeneralUserGS_sf2_file', + '0012_GeneralUserGS_sf2_file', + '0020_Aspirin_sf2_file', + '0020_Chaos_sf2_file', + '0020_FluidR3_GM_sf2_file', + '0020_GeneralUserGS_sf2_file', + '0020_JCLive_sf2_file', + '0020_SBLive_sf2', + '0020_SoundBlasterOld_sf2', + '0021_Aspirin_sf2_file', + '0021_GeneralUserGS_sf2_file', + '0022_Aspirin_sf2_file', + '0030_Aspirin_sf2_file', + '0030_Chaos_sf2_file', + '0030_FluidR3_GM_sf2_file', + '0030_GeneralUserGS_sf2_file', + '0030_JCLive_sf2_file', + '0030_SBLive_sf2', + '0030_SoundBlasterOld_sf2', + '0031_Aspirin_sf2_file', + '0031_FluidR3_GM_sf2_file', + '0031_GeneralUserGS_sf2_file', + '0031_SoundBlasterOld_sf2', // pianos until here + '0040_Aspirin_sf2_file', + '0040_Chaos_sf2_file', + '0040_FluidR3_GM_sf2_file', // rhodes + '0040_GeneralUserGS_sf2_file', // staccato rhodes + '0040_JCLive_sf2_file', // warbly rhodes + '0040_SBLive_sf2', // ? + '0040_SoundBlasterOld_sf2', // ? + '0041_FluidR3_GM_sf2_file', // rhodes + '0041_GeneralUserGS_sf2_file', // staccato rhodes + '0041_SoundBlasterOld_sf2', // ? + '0042_GeneralUserGS_sf2_file', // staccato wurly + '0043_GeneralUserGS_sf2_file', // high bell + '0044_GeneralUserGS_sf2_file', // reed organ + '0045_GeneralUserGS_sf2_file', // ? + '0046_GeneralUserGS_sf2_file', // ? + '0050_Aspirin_sf2_file', // glass organ + '0050_Chaos_sf2_file', // short glass organ + '0050_FluidR3_GM_sf2_file',// long glass organ ! + '0050_GeneralUserGS_sf2_file', // short glass organ + '0050_JCLive_sf2_file', // glass organ + '0050_SBLive_sf2', // ? + '0050_SoundBlasterOld_sf2', // ? + '0051_FluidR3_GM_sf2_file', // long lass organ + '0051_GeneralUserGS_sf2_file', + '0052_GeneralUserGS_sf2_file', // ? + '0053_GeneralUserGS_sf2_file', + '0054_GeneralUserGS_sf2_file', // piano + '0060_Aspirin_sf2_file', // harpsichord + '0060_Chaos_sf2_file', + '0060_FluidR3_GM_sf2_file', // harpsichord ! + '0060_GeneralUserGS_sf2_file', + '0060_JCLive_sf2_file', + '0060_SBLive_sf2', + '0060_SoundBlasterOld_sf2', + '0061_Aspirin_sf2_file', + '0061_GeneralUserGS_sf2_file', + '0061_SoundBlasterOld_sf2', + '0062_GeneralUserGS_sf2_file', + '0070_Aspirin_sf2_file', + '0070_Chaos_sf2_file', + '0070_FluidR3_GM_sf2_file', + '0070_GeneralUserGS_sf2_file', + '0070_JCLive_sf2_file', + '0070_SBLive_sf2', + '0070_SoundBlasterOld_sf2', + '0071_GeneralUserGS_sf2_file', + '0080_Aspirin_sf2_file', + '0080_Chaos_sf2_file', + '0080_FluidR3_GM_sf2_file', + '0080_GeneralUserGS_sf2_file', + '0080_JCLive_sf2_file', + '0080_SBLive_sf2', + '0080_SoundBlasterOld_sf2', + '0081_FluidR3_GM_sf2_file', + '0081_GeneralUserGS_sf2_file', + '0081_SoundBlasterOld_sf2', + '0090_Aspirin_sf2_file', + '0090_Chaos_sf2_file', + '0090_FluidR3_GM_sf2_file', + '0090_GeneralUserGS_sf2_file', + '0090_JCLive_sf2_file', + '0090_SBLive_sf2', + '0090_SoundBlasterOld_sf2', + '0091_SoundBlasterOld_sf2', + '0100_Aspirin_sf2_file', + '0100_Chaos_sf2_file', + '0100_FluidR3_GM_sf2_file', + '0100_GeneralUserGS_sf2_file', + '0100_JCLive_sf2_file', + '0100_SBLive_sf2', + '0100_SoundBlasterOld_sf2', + '0101_GeneralUserGS_sf2_file', + '0101_SoundBlasterOld_sf2', + '0110_Aspirin_sf2_file', + '0110_Chaos_sf2_file', + '0110_FluidR3_GM_sf2_file', + '0110_GeneralUserGS_sf2_file', + '0110_JCLive_sf2_file', + '0110_SBLive_sf2', + '0110_SoundBlasterOld_sf2', + '0111_FluidR3_GM_sf2_file', + '0120_Aspirin_sf2_file', + '0120_Chaos_sf2_file', + '0120_FluidR3_GM_sf2_file', + '0120_GeneralUserGS_sf2_file', + '0120_JCLive_sf2_file', + '0120_SBLive_sf2', + '0120_SoundBlasterOld_sf2', + '0121_FluidR3_GM_sf2_file', + '0121_GeneralUserGS_sf2_file', + '0130_Aspirin_sf2_file', + '0130_Chaos_sf2_file', + '0130_FluidR3_GM_sf2_file', + '0130_GeneralUserGS_sf2_file', + '0130_JCLive_sf2_file', + '0130_SBLive_sf2', + '0130_SoundBlasterOld_sf2', + '0131_FluidR3_GM_sf2_file', + '0140_Aspirin_sf2_file', + '0140_Chaos_sf2_file', + '0140_FluidR3_GM_sf2_file', + '0140_GeneralUserGS_sf2_file', + '0140_JCLive_sf2_file', + '0140_SBLive_sf2', + '0140_SoundBlasterOld_sf2', + '0141_FluidR3_GM_sf2_file', + '0141_GeneralUserGS_sf2_file', + '0142_GeneralUserGS_sf2_file', + '0143_GeneralUserGS_sf2_file', + '0150_Aspirin_sf2_file', + '0150_Chaos_sf2_file', + '0150_FluidR3_GM_sf2_file', + '0150_GeneralUserGS_sf2_file', + '0150_JCLive_sf2_file', + '0150_SBLive_sf2', + '0150_SoundBlasterOld_sf2', + '0151_FluidR3_GM_sf2_file', + '0160_Aspirin_sf2_file', + '0160_Chaos_sf2_file', + '0160_FluidR3_GM_sf2_file', + '0160_GeneralUserGS_sf2_file', + '0160_JCLive_sf2_file', + '0160_SBLive_sf2', + '0160_SoundBlasterOld_sf2', + '0161_Aspirin_sf2_file', + '0161_FluidR3_GM_sf2_file', + '0161_SoundBlasterOld_sf2', + '0170_Aspirin_sf2_file', + '0170_Chaos_sf2_file', + '0170_FluidR3_GM_sf2_file', + '0170_GeneralUserGS_sf2_file', + '0170_JCLive_sf2_file', + '0170_SBLive_sf2', + '0170_SoundBlasterOld_sf2', + '0171_FluidR3_GM_sf2_file', + '0171_GeneralUserGS_sf2_file', + '0172_FluidR3_GM_sf2_file', + '0180_Aspirin_sf2_file', + '0180_Chaos_sf2_file', + '0180_FluidR3_GM_sf2_file', + '0180_GeneralUserGS_sf2_file', + '0180_JCLive_sf2_file', + '0180_SBLive_sf2', + '0180_SoundBlasterOld_sf2', + '0181_Aspirin_sf2_file', + '0181_GeneralUserGS_sf2_file', + '0181_SoundBlasterOld_sf2', + '0190_Aspirin_sf2_file', + '0190_Chaos_sf2_file', + '0190_FluidR3_GM_sf2_file', + '0190_GeneralUserGS_sf2_file', + '0190_JCLive_sf2_file', + '0190_SBLive_sf2', + '0190_SoundBlasterOld_sf2', + '0191_Aspirin_sf2_file', + '0191_GeneralUserGS_sf2_file', + '0191_SoundBlasterOld_sf2', + '0200_Aspirin_sf2_file', + '0200_Chaos_sf2_file', + '0200_FluidR3_GM_sf2_file', + '0200_GeneralUserGS_sf2_file', + '0200_JCLive_sf2_file', + '0200_SBLive_sf2', + '0200_SoundBlasterOld_sf2', + '0201_Aspirin_sf2_file', + '0201_FluidR3_GM_sf2_file', + '0201_GeneralUserGS_sf2_file', + '0201_SoundBlasterOld_sf2', + '0210_Aspirin_sf2_file', + '0210_Chaos_sf2_file', + '0210_FluidR3_GM_sf2_file', + '0210_GeneralUserGS_sf2_file', + '0210_JCLive_sf2_file', + '0210_SBLive_sf2', + '0210_SoundBlasterOld_sf2', + '0211_Aspirin_sf2_file', + '0211_FluidR3_GM_sf2_file', + '0211_GeneralUserGS_sf2_file', + '0211_SoundBlasterOld_sf2', + '0212_GeneralUserGS_sf2_file', + '0220_Aspirin_sf2_file', + '0220_Chaos_sf2_file', + '0220_FluidR3_GM_sf2_file', + '0220_GeneralUserGS_sf2_file', + '0220_JCLive_sf2_file', + '0220_SBLive_sf2', + '0220_SoundBlasterOld_sf2', + '0221_FluidR3_GM_sf2_file', + '0230_Aspirin_sf2_file', + '0230_Chaos_sf2_file', + '0230_FluidR3_GM_sf2_file', + '0230_GeneralUserGS_sf2_file', + '0230_JCLive_sf2_file', + '0230_SBLive_sf2', + '0230_SoundBlasterOld_sf2', + '0231_FluidR3_GM_sf2_file', + '0231_GeneralUserGS_sf2_file', + '0231_JCLive_sf2_file', + '0231_SoundBlasterOld_sf2', + '0232_FluidR3_GM_sf2_file', + '0233_FluidR3_GM_sf2_file', + '0240_Aspirin_sf2_file', + '0240_Chaos_sf2_file', + '0240_FluidR3_GM_sf2_file', + '0240_GeneralUserGS_sf2_file', + '0240_JCLive_sf2_file', + '0240_LK_Godin_Nylon_SF2_file', + '0240_SBLive_sf2', + '0240_SoundBlasterOld_sf2', + '0241_GeneralUserGS_sf2_file', + '0241_JCLive_sf2_file', + '0242_JCLive_sf2_file', + '0243_JCLive_sf2_file', + '0253_Acoustic_Guitar_sf2_file', + '0250_Aspirin_sf2_file', + '0250_Chaos_sf2_file', + '0250_FluidR3_GM_sf2_file', + '0250_GeneralUserGS_sf2_file', + '0250_JCLive_sf2_file', + '0250_LK_AcousticSteel_SF2_file', + '0250_SBLive_sf2', + '0250_SoundBlasterOld_sf2', + '0251_Acoustic_Guitar_sf2_file', + '0251_GeneralUserGS_sf2_file', + '0252_Acoustic_Guitar_sf2_file', + '0252_GeneralUserGS_sf2_file', + '0253_Acoustic_Guitar_sf2_file', + '0253_GeneralUserGS_sf2_file', + '0254_Acoustic_Guitar_sf2_file', + '0254_GeneralUserGS_sf2_file', + '0255_GeneralUserGS_sf2_file', + '0260_Aspirin_sf2_file', + '0260_Chaos_sf2_file', + '0260_FluidR3_GM_sf2_file', + '0260_GeneralUserGS_sf2_file', + '0260_JCLive_sf2_file', + '0260_SBLive_sf2', + '0260_SoundBlasterOld_sf2', + '0260_Stratocaster_sf2_file', + '0261_GeneralUserGS_sf2_file', + '0261_SoundBlasterOld_sf2', + '0261_Stratocaster_sf2_file', + '0262_Stratocaster_sf2_file', + '0270_Aspirin_sf2_file', + '0270_Chaos_sf2_file', + '0270_FluidR3_GM_sf2_file', + '0270_GeneralUserGS_sf2_file', + '0270_Gibson_Les_Paul_sf2_file', + '0270_JCLive_sf2_file', + '0270_SBAWE32_sf2_file', + '0270_SBLive_sf2', + '0270_SoundBlasterOld_sf2', + '0270_Stratocaster_sf2_file', + '0271_GeneralUserGS_sf2_file', + '0271_Stratocaster_sf2_file', + '0272_Stratocaster_sf2_file', + '0280_Aspirin_sf2_file', + '0280_Chaos_sf2_file', + '0280_FluidR3_GM_sf2_file', + '0280_GeneralUserGS_sf2_file', + '0280_JCLive_sf2_file', + '0280_LesPaul_sf2', + '0280_LesPaul_sf2_file', + '0280_SBAWE32_sf2_file', + '0280_SBLive_sf2', + '0280_SoundBlasterOld_sf2', + '0281_Aspirin_sf2_file', + '0281_FluidR3_GM_sf2_file', + '0281_GeneralUserGS_sf2_file', + '0282_FluidR3_GM_sf2_file', + '0282_GeneralUserGS_sf2_file', + '0283_GeneralUserGS_sf2_file', + '0290_Aspirin_sf2_file', + '0290_Chaos_sf2_file', + '0290_FluidR3_GM_sf2_file', + '0290_GeneralUserGS_sf2_file', + '0290_JCLive_sf2_file', + '0290_LesPaul_sf2', + '0290_LesPaul_sf2_file', + '0290_SBAWE32_sf2_file', + '0290_SBLive_sf2', + '0290_SoundBlasterOld_sf2', + '0291_Aspirin_sf2_file', + '0291_LesPaul_sf2', + '0291_LesPaul_sf2_file', + '0291_SBAWE32_sf2_file', + '0291_SoundBlasterOld_sf2', + '0292_Aspirin_sf2_file', + '0292_LesPaul_sf2', + '0292_LesPaul_sf2_file', + '0300_Aspirin_sf2_file', + '0300_Chaos_sf2_file', + '0300_FluidR3_GM_sf2_file', + '0300_GeneralUserGS_sf2_file', + '0300_JCLive_sf2_file', + '0300_LesPaul_sf2', + '0300_LesPaul_sf2_file', + '0300_SBAWE32_sf2_file', + '0300_SBLive_sf2', + '0300_SoundBlasterOld_sf2', + '0301_Aspirin_sf2_file', + '0301_FluidR3_GM_sf2_file', + '0301_GeneralUserGS_sf2_file', + '0301_JCLive_sf2_file', + '0301_LesPaul_sf2', + '0301_LesPaul_sf2_file', + '0302_Aspirin_sf2_file', + '0302_GeneralUserGS_sf2_file', + '0302_JCLive_sf2_file', + '0303_Aspirin_sf2_file', + '0304_Aspirin_sf2_file', + '0310_Aspirin_sf2_file', + '0310_Chaos_sf2_file', + '0310_FluidR3_GM_sf2_file', + '0310_GeneralUserGS_sf2_file', + '0310_JCLive_sf2_file', + '0310_LesPaul_sf2', + '0310_LesPaul_sf2_file', + '0310_SBAWE32_sf2_file', + '0310_SBLive_sf2', + '0310_SoundBlasterOld_sf2', + '0311_FluidR3_GM_sf2_file', + '0311_GeneralUserGS_sf2_file', + '0320_Aspirin_sf2_file', + '0320_Chaos_sf2_file', + '0320_FluidR3_GM_sf2_file', + '0320_GeneralUserGS_sf2_file', + '0320_JCLive_sf2_file', + '0320_SBLive_sf2', + '0320_SoundBlasterOld_sf2', + '0321_GeneralUserGS_sf2_file', + '0322_GeneralUserGS_sf2_file', + '0330_Aspirin_sf2_file', + '0330_Chaos_sf2_file', + '0330_FluidR3_GM_sf2_file', + '0330_GeneralUserGS_sf2_file', + '0330_JCLive_sf2_file', + '0330_SBLive_sf2', + '0330_SoundBlasterOld_sf2', + '0331_GeneralUserGS_sf2_file', + '0332_GeneralUserGS_sf2_file', + '0340_Aspirin_sf2_file', + '0340_Chaos_sf2_file', + '0340_FluidR3_GM_sf2_file', + '0340_GeneralUserGS_sf2_file', + '0340_JCLive_sf2_file', + '0340_SBLive_sf2', + '0340_SoundBlasterOld_sf2', + '0341_Aspirin_sf2_file', + '0341_GeneralUserGS_sf2_file', + '0350_Aspirin_sf2_file', + '0350_Chaos_sf2_file', + '0350_FluidR3_GM_sf2_file', + '0350_GeneralUserGS_sf2_file', + '0350_JCLive_sf2_file', + '0350_SBLive_sf2', + '0350_SoundBlasterOld_sf2', + '0351_GeneralUserGS_sf2_file', + '0360_Aspirin_sf2_file', + '0360_Chaos_sf2_file', + '0360_FluidR3_GM_sf2_file', + '0360_GeneralUserGS_sf2_file', + '0360_JCLive_sf2_file', + '0360_SBLive_sf2', + '0360_SoundBlasterOld_sf2', + '0361_GeneralUserGS_sf2_file', + '0370_Aspirin_sf2_file', + '0370_Chaos_sf2_file', + '0370_FluidR3_GM_sf2_file', + '0370_GeneralUserGS_sf2_file', + '0370_JCLive_sf2_file', + '0370_SBLive_sf2', + '0370_SoundBlasterOld_sf2', + '0371_GeneralUserGS_sf2_file', + '0372_GeneralUserGS_sf2_file', + '0385_GeneralUserGS_sf2_file', + '0380_Aspirin_sf2_file', + '0380_Chaos_sf2_file', + '0380_FluidR3_GM_sf2_file', + '0380_GeneralUserGS_sf2_file', + '0380_JCLive_sf2_file', + '0380_SBLive_sf2', + '0380_SoundBlasterOld_sf2', + '0381_FluidR3_GM_sf2_file', + '0381_GeneralUserGS_sf2_file', + '0382_FluidR3_GM_sf2_file', + '0382_GeneralUserGS_sf2_file', + '0383_GeneralUserGS_sf2_file', + '0384_GeneralUserGS_sf2_file', + '0386_GeneralUserGS_sf2_file', + '0387_GeneralUserGS_sf2_file', + '0390_Aspirin_sf2_file', + '0390_Chaos_sf2_file', + '0390_FluidR3_GM_sf2_file', + '0390_GeneralUserGS_sf2_file', + '0390_JCLive_sf2_file', + '0390_SBLive_sf2', + '0390_SoundBlasterOld_sf2', + '0391_FluidR3_GM_sf2_file', + '0391_GeneralUserGS_sf2_file', + '0391_SoundBlasterOld_sf2', + '0392_FluidR3_GM_sf2_file', + '0392_GeneralUserGS_sf2_file', + '0393_GeneralUserGS_sf2_file', + '0400_Aspirin_sf2_file', + '0400_Chaos_sf2_file', + '0400_FluidR3_GM_sf2_file', + '0400_GeneralUserGS_sf2_file', + '0400_JCLive_sf2_file', + '0400_SBLive_sf2', + '0400_SoundBlasterOld_sf2', + '0401_Aspirin_sf2_file', + '0401_FluidR3_GM_sf2_file', + '0401_GeneralUserGS_sf2_file', + '0402_GeneralUserGS_sf2_file', + '0410_Aspirin_sf2_file', + '0410_Chaos_sf2_file', + '0410_FluidR3_GM_sf2_file', + '0410_GeneralUserGS_sf2_file', + '0410_JCLive_sf2_file', + '0410_SBLive_sf2', + '0410_SoundBlasterOld_sf2', + '0411_FluidR3_GM_sf2_file', + '0420_Aspirin_sf2_file', + '0420_Chaos_sf2_file', + '0420_FluidR3_GM_sf2_file', + '0420_GeneralUserGS_sf2_file', + '0420_JCLive_sf2_file', + '0420_SBLive_sf2', + '0420_SoundBlasterOld_sf2', + '0421_FluidR3_GM_sf2_file', + '0421_GeneralUserGS_sf2_file', + '0430_Aspirin_sf2_file', + '0430_Chaos_sf2_file', + '0430_FluidR3_GM_sf2_file', + '0430_GeneralUserGS_sf2_file', + '0430_JCLive_sf2_file', + '0430_SBLive_sf2', + '0430_SoundBlasterOld_sf2', + '0431_FluidR3_GM_sf2_file', + '0440_Aspirin_sf2_file', + '0440_Chaos_sf2_file', + '0440_FluidR3_GM_sf2_file', + '0440_GeneralUserGS_sf2_file', + '0440_JCLive_sf2_file', + '0440_SBLive_sf2', + '0440_SoundBlasterOld_sf2', + '0441_GeneralUserGS_sf2_file', + '0442_GeneralUserGS_sf2_file', + '0450_Aspirin_sf2_file', + '0450_Chaos_sf2_file', + '0450_FluidR3_GM_sf2_file', + '0450_GeneralUserGS_sf2_file', + '0450_JCLive_sf2_file', + '0450_SBLive_sf2', + '0450_SoundBlasterOld_sf2', + '0451_FluidR3_GM_sf2_file', + '0460_Aspirin_sf2_file', + '0460_Chaos_sf2_file', + '0460_FluidR3_GM_sf2_file', + '0460_GeneralUserGS_sf2_file', + '0460_JCLive_sf2_file', + '0460_SBLive_sf2', + '0460_SoundBlasterOld_sf2', + '0461_FluidR3_GM_sf2_file', + '0470_Aspirin_sf2_file', + '0470_Chaos_sf2_file', + '0470_FluidR3_GM_sf2_file', + '0470_GeneralUserGS_sf2_file', + '0470_JCLive_sf2_file', + '0470_SBLive_sf2', + '0470_SoundBlasterOld_sf2', + '0471_FluidR3_GM_sf2_file', + '0471_GeneralUserGS_sf2_file', + '0480_Aspirin_sf2_file', + '0480_Chaos_sf2_file', + '0480_FluidR3_GM_sf2_file', + '0480_GeneralUserGS_sf2_file', + '0480_JCLive_sf2_file', + '0480_SBLive_sf2', + '0480_SoundBlasterOld_sf2', + '04810_GeneralUserGS_sf2_file', + '04811_GeneralUserGS_sf2_file', + '04812_GeneralUserGS_sf2_file', + '04813_GeneralUserGS_sf2_file', + '04814_GeneralUserGS_sf2_file', + '04815_GeneralUserGS_sf2_file', + '04816_GeneralUserGS_sf2_file', + '04817_GeneralUserGS_sf2_file', + '0481_Aspirin_sf2_file', + '0481_FluidR3_GM_sf2_file', + '0481_GeneralUserGS_sf2_file', + '0482_Aspirin_sf2_file', + '0482_GeneralUserGS_sf2_file', + '0483_GeneralUserGS_sf2_file', + '0484_GeneralUserGS_sf2_file', + '0485_GeneralUserGS_sf2_file', + '0486_GeneralUserGS_sf2_file', + '0487_GeneralUserGS_sf2_file', + '0488_GeneralUserGS_sf2_file', + '0489_GeneralUserGS_sf2_file', + '0490_Aspirin_sf2_file', + '0490_Chaos_sf2_file', + '0490_FluidR3_GM_sf2_file', + '0490_GeneralUserGS_sf2_file', + '0490_JCLive_sf2_file', + '0490_SBLive_sf2', + '0490_SoundBlasterOld_sf2', + '0491_GeneralUserGS_sf2_file', + '0492_GeneralUserGS_sf2_file', + '0500_Aspirin_sf2_file', + '0500_Chaos_sf2_file', + '0500_FluidR3_GM_sf2_file', + '0500_GeneralUserGS_sf2_file', + '0500_JCLive_sf2_file', + '0500_SBLive_sf2', + '0500_SoundBlasterOld_sf2', + '0501_FluidR3_GM_sf2_file', + '0501_GeneralUserGS_sf2_file', + '0502_FluidR3_GM_sf2_file', + '0502_GeneralUserGS_sf2_file', + '0503_FluidR3_GM_sf2_file', + '0504_FluidR3_GM_sf2_file', + '0505_FluidR3_GM_sf2_file', + '0510_Aspirin_sf2_file', + '0510_Chaos_sf2_file', + '0510_FluidR3_GM_sf2_file', + '0510_GeneralUserGS_sf2_file', + '0510_JCLive_sf2_file', + '0510_SBLive_sf2', + '0510_SoundBlasterOld_sf2', + '0511_GeneralUserGS_sf2_file', + '0511_SoundBlasterOld_sf2', + '0520_Aspirin_sf2_file', + '0520_Chaos_sf2_file', + '0520_FluidR3_GM_sf2_file', + '0520_GeneralUserGS_sf2_file', + '0520_JCLive_sf2_file', + '0520_SBLive_sf2', + '0520_Soul_Ahhs_sf2_file', + '0520_SoundBlasterOld_sf2', + '0521_FluidR3_GM_sf2_file', + '0521_Soul_Ahhs_sf2_file', + '0521_SoundBlasterOld_sf2', + '0522_Soul_Ahhs_sf2_file', + '0530_Aspirin_sf2_file', + '0530_Chaos_sf2_file', + '0530_FluidR3_GM_sf2_file', + '0530_GeneralUserGS_sf2_file', + '0530_JCLive_sf2_file', + '0530_SBLive_sf2', + '0530_Soul_Ahhs_sf2_file', + '0530_SoundBlasterOld_sf2', + '0531_FluidR3_GM_sf2_file', + '0531_GeneralUserGS_sf2_file', + '0531_JCLive_sf2_file', + '0531_SoundBlasterOld_sf2', + '0540_Aspirin_sf2_file', + '0540_Chaos_sf2_file', + '0540_FluidR3_GM_sf2_file', + '0540_GeneralUserGS_sf2_file', + '0540_JCLive_sf2_file', + '0540_SBLive_sf2', + '0540_SoundBlasterOld_sf2', + '0541_FluidR3_GM_sf2_file', + '0550_Aspirin_sf2_file', + '0550_Chaos_sf2_file', + '0550_FluidR3_GM_sf2_file', + '0550_GeneralUserGS_sf2_file', + '0550_JCLive_sf2_file', + '0550_SBLive_sf2', + '0550_SoundBlasterOld_sf2', + '0551_Aspirin_sf2_file', + '0551_FluidR3_GM_sf2_file', + '0560_Aspirin_sf2_file', + '0560_Chaos_sf2_file', + '0560_FluidR3_GM_sf2_file', + '0560_GeneralUserGS_sf2_file', + '0560_JCLive_sf2_file', + '0560_SBLive_sf2', + '0560_SoundBlasterOld_sf2', + '0570_Aspirin_sf2_file', + '0570_Chaos_sf2_file', + '0570_FluidR3_GM_sf2_file', + '0570_GeneralUserGS_sf2_file', + '0570_JCLive_sf2_file', + '0570_SBLive_sf2', + '0570_SoundBlasterOld_sf2', + '0571_GeneralUserGS_sf2_file', + '0580_Aspirin_sf2_file', + '0580_Chaos_sf2_file', + '0580_FluidR3_GM_sf2_file', + '0580_GeneralUserGS_sf2_file', + '0580_JCLive_sf2_file', + '0580_SBLive_sf2', + '0580_SoundBlasterOld_sf2', + '0581_GeneralUserGS_sf2_file', + '0590_Aspirin_sf2_file', + '0590_Chaos_sf2_file', + '0590_FluidR3_GM_sf2_file', + '0590_GeneralUserGS_sf2_file', + '0590_JCLive_sf2_file', + '0590_SBLive_sf2', + '0590_SoundBlasterOld_sf2', + '0591_GeneralUserGS_sf2_file', + '0600_Aspirin_sf2_file', + '0600_Chaos_sf2_file', + '0600_FluidR3_GM_sf2_file', + '0600_GeneralUserGS_sf2_file', + '0600_JCLive_sf2_file', + '0600_SBLive_sf2', + '0600_SoundBlasterOld_sf2', + '0601_FluidR3_GM_sf2_file', + '0601_GeneralUserGS_sf2_file', + '0602_GeneralUserGS_sf2_file', + '0603_GeneralUserGS_sf2_file', + '0610_Aspirin_sf2_file', + '0610_Chaos_sf2_file', + '0610_FluidR3_GM_sf2_file', + '0610_GeneralUserGS_sf2_file', + '0610_JCLive_sf2_file', + '0610_SBLive_sf2', + '0610_SoundBlasterOld_sf2', + '0611_GeneralUserGS_sf2_file', + '0612_GeneralUserGS_sf2_file', + '0613_GeneralUserGS_sf2_file', + '0614_GeneralUserGS_sf2_file', + '0615_GeneralUserGS_sf2_file', + '0620_Aspirin_sf2_file', + '0620_Chaos_sf2_file', + '0620_FluidR3_GM_sf2_file', + '0620_GeneralUserGS_sf2_file', + '0620_JCLive_sf2_file', + '0620_SBLive_sf2', + '0620_SoundBlasterOld_sf2', + '0621_Aspirin_sf2_file', + '0621_FluidR3_GM_sf2_file', + '0621_GeneralUserGS_sf2_file', + '0622_FluidR3_GM_sf2_file', + '0622_GeneralUserGS_sf2_file', + '0630_Aspirin_sf2_file', + '0630_Chaos_sf2_file', + '0630_FluidR3_GM_sf2_file', + '0630_GeneralUserGS_sf2_file', + '0630_JCLive_sf2_file', + '0630_SBLive_sf2', + '0630_SoundBlasterOld_sf2', + '0631_Aspirin_sf2_file', + '0631_FluidR3_GM_sf2_file', + '0631_GeneralUserGS_sf2_file', + '0632_FluidR3_GM_sf2_file', + '0633_FluidR3_GM_sf2_file', + '0640_Aspirin_sf2_file', + '0640_Chaos_sf2_file', + '0640_FluidR3_GM_sf2_file', + '0640_GeneralUserGS_sf2_file', + '0640_JCLive_sf2_file', + '0640_SBLive_sf2', + '0640_SoundBlasterOld_sf2', + '0641_FluidR3_GM_sf2_file', + '0650_Aspirin_sf2_file', + '0650_Chaos_sf2_file', + '0650_FluidR3_GM_sf2_file', + '0650_GeneralUserGS_sf2_file', + '0650_JCLive_sf2_file', + '0650_SBLive_sf2', + '0650_SoundBlasterOld_sf2', + '0651_Aspirin_sf2_file', + '0651_FluidR3_GM_sf2_file', + '0660_Aspirin_sf2_file', + '0660_Chaos_sf2_file', + '0660_FluidR3_GM_sf2_file', + '0660_GeneralUserGS_sf2_file', + '0660_JCLive_sf2_file', + '0660_SBLive_sf2', + '0660_SoundBlasterOld_sf2', + '0661_FluidR3_GM_sf2_file', + '0661_GeneralUserGS_sf2_file', + '0670_Aspirin_sf2_file', + '0670_Chaos_sf2_file', + '0670_FluidR3_GM_sf2_file', + '0670_GeneralUserGS_sf2_file', + '0670_JCLive_sf2_file', + '0670_SBLive_sf2', + '0670_SoundBlasterOld_sf2', + '0671_FluidR3_GM_sf2_file', + '0680_Aspirin_sf2_file', + '0680_Chaos_sf2_file', + '0680_FluidR3_GM_sf2_file', + '0680_GeneralUserGS_sf2_file', + '0680_JCLive_sf2_file', + '0680_SBLive_sf2', + '0680_SoundBlasterOld_sf2', + '0681_FluidR3_GM_sf2_file', + '0690_Aspirin_sf2_file', + '0690_Chaos_sf2_file', + '0690_FluidR3_GM_sf2_file', + '0690_GeneralUserGS_sf2_file', + '0690_JCLive_sf2_file', + '0690_SBLive_sf2', + '0690_SoundBlasterOld_sf2', + '0691_FluidR3_GM_sf2_file', + '0700_Aspirin_sf2_file', + '0700_Chaos_sf2_file', + '0700_FluidR3_GM_sf2_file', + '0700_GeneralUserGS_sf2_file', + '0700_JCLive_sf2_file', + '0700_SBLive_sf2', + '0700_SoundBlasterOld_sf2', + '0701_FluidR3_GM_sf2_file', + '0701_GeneralUserGS_sf2_file', + '0710_Aspirin_sf2_file', + '0710_Chaos_sf2_file', + '0710_FluidR3_GM_sf2_file', + '0710_GeneralUserGS_sf2_file', + '0710_JCLive_sf2_file', + '0710_SBLive_sf2', + '0710_SoundBlasterOld_sf2', + '0711_FluidR3_GM_sf2_file', + '0720_Aspirin_sf2_file', + '0720_Chaos_sf2_file', + '0720_FluidR3_GM_sf2_file', + '0720_GeneralUserGS_sf2_file', + '0720_JCLive_sf2_file', + '0720_SBLive_sf2', + '0720_SoundBlasterOld_sf2', + '0721_FluidR3_GM_sf2_file', + '0721_SoundBlasterOld_sf2', + '0730_Aspirin_sf2_file', + '0730_Chaos_sf2_file', + '0730_FluidR3_GM_sf2_file', + '0730_GeneralUserGS_sf2_file', + '0730_JCLive_sf2_file', + '0730_SBLive_sf2', + '0730_SoundBlasterOld_sf2', + '0731_Aspirin_sf2_file', + '0731_FluidR3_GM_sf2_file', + '0731_SoundBlasterOld_sf2', + '0740_Aspirin_sf2_file', + '0740_Chaos_sf2_file', + '0740_FluidR3_GM_sf2_file', + '0740_GeneralUserGS_sf2_file', + '0740_JCLive_sf2_file', + '0740_SBLive_sf2', + '0740_SoundBlasterOld_sf2', + '0741_GeneralUserGS_sf2_file', + '0750_Aspirin_sf2_file', + '0750_Chaos_sf2_file', + '0750_FluidR3_GM_sf2_file', + '0750_GeneralUserGS_sf2_file', + '0750_JCLive_sf2_file', + '0750_SBLive_sf2', + '0750_SoundBlasterOld_sf2', + '0751_Aspirin_sf2_file', + '0751_FluidR3_GM_sf2_file', + '0751_GeneralUserGS_sf2_file', + '0751_SoundBlasterOld_sf2', + '0760_Aspirin_sf2_file', + '0760_Chaos_sf2_file', + '0760_FluidR3_GM_sf2_file', + '0760_GeneralUserGS_sf2_file', + '0760_JCLive_sf2_file', + '0760_SBLive_sf2', + '0760_SoundBlasterOld_sf2', + '0761_FluidR3_GM_sf2_file', + '0761_GeneralUserGS_sf2_file', + '0761_SoundBlasterOld_sf2', + '0762_GeneralUserGS_sf2_file', + '0770_Aspirin_sf2_file', + '0770_Chaos_sf2_file', + '0770_FluidR3_GM_sf2_file', + '0770_GeneralUserGS_sf2_file', + '0770_JCLive_sf2_file', + '0770_SBLive_sf2', + '0770_SoundBlasterOld_sf2', + '0771_FluidR3_GM_sf2_file', + '0771_GeneralUserGS_sf2_file', + '0772_GeneralUserGS_sf2_file', + '0780_Aspirin_sf2_file', + '0780_Chaos_sf2_file', + '0780_FluidR3_GM_sf2_file', + '0780_GeneralUserGS_sf2_file', + '0780_JCLive_sf2_file', + '0780_SBLive_sf2', + '0780_SoundBlasterOld_sf2', + '0781_GeneralUserGS_sf2_file', + '0790_Aspirin_sf2_file', + '0790_Chaos_sf2_file', + '0790_FluidR3_GM_sf2_file', + '0790_GeneralUserGS_sf2_file', + '0790_JCLive_sf2_file', + '0790_SBLive_sf2', + '0790_SoundBlasterOld_sf2', + '0791_GeneralUserGS_sf2_file', + '0800_Aspirin_sf2_file', + '0800_Chaos_sf2_file', + '0800_FluidR3_GM_sf2_file', + '0800_GeneralUserGS_sf2_file', + '0800_JCLive_sf2_file', + '0800_SBLive_sf2', + '0800_SoundBlasterOld_sf2', + '0801_FluidR3_GM_sf2_file', + '0801_GeneralUserGS_sf2_file', + '0810_Aspirin_sf2_file', + '0810_Chaos_sf2_file', + '0810_FluidR3_GM_sf2_file', + '0810_GeneralUserGS_sf2_file', + '0810_JCLive_sf2_file', + '0810_SBLive_sf2', + '0810_SoundBlasterOld_sf2', + '0811_Aspirin_sf2_file', + '0811_GeneralUserGS_sf2_file', + '0811_SoundBlasterOld_sf2', + '0820_Aspirin_sf2_file', + '0820_Chaos_sf2_file', + '0820_FluidR3_GM_sf2_file', + '0820_GeneralUserGS_sf2_file', + '0820_JCLive_sf2_file', + '0820_SBLive_sf2', + '0820_SoundBlasterOld_sf2', + '0821_FluidR3_GM_sf2_file', + '0821_GeneralUserGS_sf2_file', + '0821_SoundBlasterOld_sf2', + '0822_GeneralUserGS_sf2_file', + '0823_GeneralUserGS_sf2_file', + '0830_Aspirin_sf2_file', + '0830_Chaos_sf2_file', + '0830_FluidR3_GM_sf2_file', + '0830_GeneralUserGS_sf2_file', + '0830_JCLive_sf2_file', + '0830_SBLive_sf2', + '0830_SoundBlasterOld_sf2', + '0831_FluidR3_GM_sf2_file', + '0831_GeneralUserGS_sf2_file', + '0831_SoundBlasterOld_sf2', + '0840_Aspirin_sf2_file', + '0840_Chaos_sf2_file', + '0840_FluidR3_GM_sf2_file', + '0840_GeneralUserGS_sf2_file', + '0840_JCLive_sf2_file', + '0840_SBLive_sf2', + '0840_SoundBlasterOld_sf2', + '0841_Aspirin_sf2_file', + '0841_Chaos_sf2_file', + '0841_FluidR3_GM_sf2_file', + '0841_GeneralUserGS_sf2_file', + '0841_JCLive_sf2_file', + '0841_SoundBlasterOld_sf2', + '0842_FluidR3_GM_sf2_file', + '0850_Aspirin_sf2_file', + '0850_Chaos_sf2_file', + '0850_FluidR3_GM_sf2_file', + '0850_GeneralUserGS_sf2_file', + '0850_JCLive_sf2_file', + '0850_SBLive_sf2', + '0850_SoundBlasterOld_sf2', + '0851_FluidR3_GM_sf2_file', + '0851_GeneralUserGS_sf2_file', + '0851_JCLive_sf2_file', + '0851_SoundBlasterOld_sf2', + '0860_Aspirin_sf2_file', + '0860_Chaos_sf2_file', + '0860_FluidR3_GM_sf2_file', + '0860_GeneralUserGS_sf2_file', + '0860_JCLive_sf2_file', + '0860_SBLive_sf2', + '0860_SoundBlasterOld_sf2', + '0861_Aspirin_sf2_file', + '0861_FluidR3_GM_sf2_file', + '0861_SoundBlasterOld_sf2', + '0870_Aspirin_sf2_file', + '0870_Chaos_sf2_file', + '0870_FluidR3_GM_sf2_file', + '0870_GeneralUserGS_sf2_file', + '0870_JCLive_sf2_file', + '0870_SBLive_sf2', + '0870_SoundBlasterOld_sf2', + '0871_GeneralUserGS_sf2_file', + '0872_GeneralUserGS_sf2_file', + '0873_GeneralUserGS_sf2_file', + '0880_Aspirin_sf2_file', + '0880_Chaos_sf2_file', + '0880_FluidR3_GM_sf2_file', + '0880_GeneralUserGS_sf2_file', + '0880_JCLive_sf2_file', + '0880_SBLive_sf2', + '0880_SoundBlasterOld_sf2', + '0881_Aspirin_sf2_file', + '0881_FluidR3_GM_sf2_file', + '0881_GeneralUserGS_sf2_file', + '0881_SoundBlasterOld_sf2', + '0882_Aspirin_sf2_file', + '0882_FluidR3_GM_sf2_file', + '0882_GeneralUserGS_sf2_file', + '0883_GeneralUserGS_sf2_file', + '0884_GeneralUserGS_sf2_file', + '0885_GeneralUserGS_sf2_file', + '0886_GeneralUserGS_sf2_file', + '0887_GeneralUserGS_sf2_file', + '0888_GeneralUserGS_sf2_file', + '0889_GeneralUserGS_sf2_file', + '0890_Aspirin_sf2_file', + '0890_Chaos_sf2_file', + '0890_FluidR3_GM_sf2_file', + '0890_GeneralUserGS_sf2_file', + '0890_JCLive_sf2_file', + '0890_SBLive_sf2', + '0890_SoundBlasterOld_sf2', + '0891_Aspirin_sf2_file', + '0891_FluidR3_GM_sf2_file', + '0891_GeneralUserGS_sf2_file', + '0900_Aspirin_sf2_file', + '0900_Chaos_sf2_file', + '0900_FluidR3_GM_sf2_file', + '0900_GeneralUserGS_sf2_file', + '0900_JCLive_sf2_file', + '0900_SBLive_sf2', + '0900_SoundBlasterOld_sf2', + '0901_Aspirin_sf2_file', + '0901_FluidR3_GM_sf2_file', + '0901_GeneralUserGS_sf2_file', + '0901_SoundBlasterOld_sf2', + '0910_Aspirin_sf2_file', + '0910_Chaos_sf2_file', + '0910_FluidR3_GM_sf2_file', + '0910_GeneralUserGS_sf2_file', + '0910_JCLive_sf2_file', + '0910_SBLive_sf2', + '0910_SoundBlasterOld_sf2', + '0911_Aspirin_sf2_file', + '0911_GeneralUserGS_sf2_file', + '0911_JCLive_sf2_file', + '0911_SoundBlasterOld_sf2', + '0920_Aspirin_sf2_file', + '0920_Chaos_sf2_file', + '0920_FluidR3_GM_sf2_file', + '0920_GeneralUserGS_sf2_file', + '0920_JCLive_sf2_file', + '0920_SBLive_sf2', + '0920_SoundBlasterOld_sf2', + '0921_Aspirin_sf2_file', + '0921_GeneralUserGS_sf2_file', + '0921_SoundBlasterOld_sf2', + '0930_Aspirin_sf2_file', + '0930_Chaos_sf2_file', + '0930_FluidR3_GM_sf2_file', + '0930_GeneralUserGS_sf2_file', + '0930_JCLive_sf2_file', + '0930_SBLive_sf2', + '0930_SoundBlasterOld_sf2', + '0931_Aspirin_sf2_file', + '0931_FluidR3_GM_sf2_file', + '0931_GeneralUserGS_sf2_file', + '0931_SoundBlasterOld_sf2', + '0940_Aspirin_sf2_file', + '0940_Chaos_sf2_file', + '0940_FluidR3_GM_sf2_file', + '0940_GeneralUserGS_sf2_file', + '0940_JCLive_sf2_file', + '0940_SBLive_sf2', + '0940_SoundBlasterOld_sf2', + '0941_Aspirin_sf2_file', + '0941_FluidR3_GM_sf2_file', + '0941_GeneralUserGS_sf2_file', + '0941_JCLive_sf2_file', + '0950_Aspirin_sf2_file', + '0950_Chaos_sf2_file', + '0950_FluidR3_GM_sf2_file', + '0950_GeneralUserGS_sf2_file', + '0950_JCLive_sf2_file', + '0950_SBLive_sf2', + '0950_SoundBlasterOld_sf2', + '0951_FluidR3_GM_sf2_file', + '0951_GeneralUserGS_sf2_file', + '0960_Aspirin_sf2_file', + '0960_Chaos_sf2_file', + '0960_FluidR3_GM_sf2_file', + '0960_GeneralUserGS_sf2_file', + '0960_JCLive_sf2_file', + '0960_SBLive_sf2', + '0960_SoundBlasterOld_sf2', + '0961_Aspirin_sf2_file', + '0961_FluidR3_GM_sf2_file', + '0961_GeneralUserGS_sf2_file', + '0961_SoundBlasterOld_sf2', + '0962_GeneralUserGS_sf2_file', + '0970_Aspirin_sf2_file', + '0970_Chaos_sf2_file', + '0970_FluidR3_GM_sf2_file', + '0970_GeneralUserGS_sf2_file', + '0970_JCLive_sf2_file', + '0970_SBLive_sf2', + '0970_SoundBlasterOld_sf2', + '0971_FluidR3_GM_sf2_file', + '0971_GeneralUserGS_sf2_file', + '0971_SoundBlasterOld_sf2', + '0980_Aspirin_sf2_file', + '0980_Chaos_sf2_file', + '0980_FluidR3_GM_sf2_file', + '0980_GeneralUserGS_sf2_file', + '0980_JCLive_sf2_file', + '0980_SBLive_sf2', + '0980_SoundBlasterOld_sf2', + '0981_Aspirin_sf2_file', + '0981_FluidR3_GM_sf2_file', + '0981_GeneralUserGS_sf2_file', + '0981_SoundBlasterOld_sf2', + '0982_GeneralUserGS_sf2_file', + '0983_GeneralUserGS_sf2_file', + '0984_GeneralUserGS_sf2_file', + '0990_Aspirin_sf2_file', + '0990_Chaos_sf2_file', + '0990_FluidR3_GM_sf2_file', + '0990_GeneralUserGS_sf2_file', + '0990_JCLive_sf2_file', + '0990_SBLive_sf2', + '0990_SoundBlasterOld_sf2', + '0991_Aspirin_sf2_file', + '0991_FluidR3_GM_sf2_file', + '0991_GeneralUserGS_sf2_file', + '0991_JCLive_sf2_file', + '0991_SoundBlasterOld_sf2', + '0992_FluidR3_GM_sf2_file', + '0992_JCLive_sf2_file', + '0993_JCLive_sf2_file', + '0994_JCLive_sf2_file', + '1000_Aspirin_sf2_file', + '1000_Chaos_sf2_file', + '1000_FluidR3_GM_sf2_file', + '1000_GeneralUserGS_sf2_file', + '1000_JCLive_sf2_file', + '1000_SBLive_sf2', + '1000_SoundBlasterOld_sf2', + '1001_Aspirin_sf2_file', + '1001_FluidR3_GM_sf2_file', + '1001_GeneralUserGS_sf2_file', + '1001_JCLive_sf2_file', + '1001_SoundBlasterOld_sf2', + '1002_Aspirin_sf2_file', + '1002_FluidR3_GM_sf2_file', + '1002_GeneralUserGS_sf2_file', + '1010_Aspirin_sf2_file', + '1010_Chaos_sf2_file', + '1010_FluidR3_GM_sf2_file', + '1010_GeneralUserGS_sf2_file', + '1010_JCLive_sf2_file', + '1010_SBLive_sf2', + '1010_SoundBlasterOld_sf2', + '1011_Aspirin_sf2_file', + '1011_FluidR3_GM_sf2_file', + '1011_JCLive_sf2_file', + '1012_Aspirin_sf2_file', + '1020_Aspirin_sf2_file', + '1020_Chaos_sf2_file', + '1020_FluidR3_GM_sf2_file', + '1020_GeneralUserGS_sf2_file', + '1020_JCLive_sf2_file', + '1020_SBLive_sf2', + '1020_SoundBlasterOld_sf2', + '1021_Aspirin_sf2_file', + '1021_FluidR3_GM_sf2_file', + '1021_GeneralUserGS_sf2_file', + '1021_JCLive_sf2_file', + '1021_SoundBlasterOld_sf2', + '1022_GeneralUserGS_sf2_file', + '1030_Aspirin_sf2_file', + '1030_Chaos_sf2_file', + '1030_FluidR3_GM_sf2_file', + '1030_GeneralUserGS_sf2_file', + '1030_JCLive_sf2_file', + '1030_SBLive_sf2', + '1030_SoundBlasterOld_sf2', + '1031_Aspirin_sf2_file', + '1031_FluidR3_GM_sf2_file', + '1031_GeneralUserGS_sf2_file', + '1031_SoundBlasterOld_sf2', + '1032_FluidR3_GM_sf2_file', + '1040_Aspirin_sf2_file', + '1040_Chaos_sf2_file', + '1040_FluidR3_GM_sf2_file', + '1040_GeneralUserGS_sf2_file', + '1040_JCLive_sf2_file', + '1040_SBLive_sf2', + '1040_SoundBlasterOld_sf2', + '1041_FluidR3_GM_sf2_file', + '1041_GeneralUserGS_sf2_file', + '1050_Aspirin_sf2_file', + '1050_Chaos_sf2_file', + '1050_FluidR3_GM_sf2_file', + '1050_GeneralUserGS_sf2_file', + '1050_JCLive_sf2_file', + '1050_SBLive_sf2', + '1050_SoundBlasterOld_sf2', + '1051_GeneralUserGS_sf2_file', + '1060_Aspirin_sf2_file', + '1060_Chaos_sf2_file', + '1060_FluidR3_GM_sf2_file', + '1060_GeneralUserGS_sf2_file', + '1060_JCLive_sf2_file', + '1060_SBLive_sf2', + '1060_SoundBlasterOld_sf2', + '1061_FluidR3_GM_sf2_file', + '1061_GeneralUserGS_sf2_file', + '1061_SoundBlasterOld_sf2', + '1070_Aspirin_sf2_file', + '1070_Chaos_sf2_file', + '1070_FluidR3_GM_sf2_file', + '1070_GeneralUserGS_sf2_file', + '1070_JCLive_sf2_file', + '1070_SBLive_sf2', + '1070_SoundBlasterOld_sf2', + '1071_FluidR3_GM_sf2_file', + '1071_GeneralUserGS_sf2_file', + '1072_GeneralUserGS_sf2_file', + '1073_GeneralUserGS_sf2_file', + '1080_Aspirin_sf2_file', + '1080_Chaos_sf2_file', + '1080_FluidR3_GM_sf2_file', + '1080_GeneralUserGS_sf2_file', + '1080_JCLive_sf2_file', + '1080_SBLive_sf2', + '1080_SoundBlasterOld_sf2', + '1081_SoundBlasterOld_sf2', + '1090_Aspirin_sf2_file', + '1090_Chaos_sf2_file', + '1090_FluidR3_GM_sf2_file', + '1090_GeneralUserGS_sf2_file', + '1090_JCLive_sf2_file', + '1090_SBLive_sf2', + '1090_SoundBlasterOld_sf2', + '1091_SoundBlasterOld_sf2', + '1100_Aspirin_sf2_file', + '1100_Chaos_sf2_file', + '1100_FluidR3_GM_sf2_file', + '1100_GeneralUserGS_sf2_file', + '1100_JCLive_sf2_file', + '1100_SBLive_sf2', + '1100_SoundBlasterOld_sf2', + '1101_Aspirin_sf2_file', + '1101_FluidR3_GM_sf2_file', + '1101_GeneralUserGS_sf2_file', + '1102_GeneralUserGS_sf2_file', + '1110_Aspirin_sf2_file', + '1110_Chaos_sf2_file', + '1110_FluidR3_GM_sf2_file', + '1110_GeneralUserGS_sf2_file', + '1110_JCLive_sf2_file', + '1110_SBLive_sf2', + '1110_SoundBlasterOld_sf2', + '1120_Aspirin_sf2_file', + '1120_Chaos_sf2_file', + '1120_FluidR3_GM_sf2_file', + '1120_GeneralUserGS_sf2_file', + '1120_JCLive_sf2_file', + '1120_SBLive_sf2', + '1120_SoundBlasterOld_sf2', + '1121_SoundBlasterOld_sf2', + '1130_Aspirin_sf2_file', + '1130_Chaos_sf2_file', + '1130_FluidR3_GM_sf2_file', + '1130_GeneralUserGS_sf2_file', + '1130_JCLive_sf2_file', + '1130_SBLive_sf2', + '1130_SoundBlasterOld_sf2', + '1131_FluidR3_GM_sf2_file', + '1131_SoundBlasterOld_sf2', + '1140_Aspirin_sf2_file', + '1140_Chaos_sf2_file', + '1140_FluidR3_GM_sf2_file', + '1140_GeneralUserGS_sf2_file', + '1140_JCLive_sf2_file', + '1140_SBLive_sf2', + '1140_SoundBlasterOld_sf2', + '1141_FluidR3_GM_sf2_file', + '1150_Aspirin_sf2_file', + '1150_Chaos_sf2_file', + '1150_FluidR3_GM_sf2_file', + '1150_GeneralUserGS_sf2_file', + '1150_JCLive_sf2_file', + '1150_SBLive_sf2', + '1150_SoundBlasterOld_sf2', + '1151_FluidR3_GM_sf2_file', + '1151_GeneralUserGS_sf2_file', + '1152_FluidR3_GM_sf2_file', + '1152_GeneralUserGS_sf2_file', + '1160_Aspirin_sf2_file', + '1160_Chaos_sf2_file', + '1160_FluidR3_GM_sf2_file', + '1160_GeneralUserGS_sf2_file', + '1160_JCLive_sf2_file', + '1160_SBLive_sf2', + '1160_SoundBlasterOld_sf2', + '1161_FluidR3_GM_sf2_file', + '1161_GeneralUserGS_sf2_file', + '1161_SoundBlasterOld_sf2', + '1162_FluidR3_GM_sf2_file', + '1162_GeneralUserGS_sf2_file', + '1163_FluidR3_GM_sf2_file', + '1170_Aspirin_sf2_file', + '1170_Chaos_sf2_file', + '1170_FluidR3_GM_sf2_file', + '1170_GeneralUserGS_sf2_file', + '1170_JCLive_sf2_file', + '1170_SBLive_sf2', + '1170_SoundBlasterOld_sf2', + '1171_FluidR3_GM_sf2_file', + '1171_GeneralUserGS_sf2_file', + '1172_FluidR3_GM_sf2_file', + '1173_FluidR3_GM_sf2_file', + '1180_Aspirin_sf2_file', + '1180_Chaos_sf2_file', + '1180_FluidR3_GM_sf2_file', + '1180_GeneralUserGS_sf2_file', + '1180_JCLive_sf2_file', + '1180_SBLive_sf2', + '1180_SoundBlasterOld_sf2', + '1181_FluidR3_GM_sf2_file', + '1181_GeneralUserGS_sf2_file', + '1181_SoundBlasterOld_sf2', + '1190_Aspirin_sf2_file', + '1190_Chaos_sf2_file', + '1190_FluidR3_GM_sf2_file', + '1190_GeneralUserGS_sf2_file', + '1190_JCLive_sf2_file', + '1190_SBLive_sf2', + '1190_SoundBlasterOld_sf2', + '1191_GeneralUserGS_sf2_file', + '1192_GeneralUserGS_sf2_file', + '1193_GeneralUserGS_sf2_file', + '1194_GeneralUserGS_sf2_file', + '1200_Aspirin_sf2_file', + '1200_Chaos_sf2_file', + '1200_FluidR3_GM_sf2_file', + '1200_GeneralUserGS_sf2_file', + '1200_JCLive_sf2_file', + '1200_SBLive_sf2', + '1200_SoundBlasterOld_sf2', + '1201_Aspirin_sf2_file', + '1201_GeneralUserGS_sf2_file', + '1202_GeneralUserGS_sf2_file', + '1210_Aspirin_sf2_file', + '1210_Chaos_sf2_file', + '1210_FluidR3_GM_sf2_file', + '1210_GeneralUserGS_sf2_file', + '1210_JCLive_sf2_file', + '1210_SBLive_sf2', + '1210_SoundBlasterOld_sf2', + '1211_Aspirin_sf2_file', + '1211_GeneralUserGS_sf2_file', + '1212_GeneralUserGS_sf2_file', + '1220_Aspirin_sf2_file', + '1220_Chaos_sf2_file', + '1220_FluidR3_GM_sf2_file', + '1220_GeneralUserGS_sf2_file', + '1220_JCLive_sf2_file', + '1220_SBLive_sf2', + '1220_SoundBlasterOld_sf2', + '1221_Aspirin_sf2_file', + '1221_GeneralUserGS_sf2_file', + '1221_JCLive_sf2_file', + '1222_Aspirin_sf2_file', + '1222_GeneralUserGS_sf2_file', + '1223_Aspirin_sf2_file', + '1223_GeneralUserGS_sf2_file', + '1224_Aspirin_sf2_file', + '1224_GeneralUserGS_sf2_file', + '1225_GeneralUserGS_sf2_file', + '1226_GeneralUserGS_sf2_file', + '1230_Aspirin_sf2_file', + '1230_Chaos_sf2_file', + '1230_FluidR3_GM_sf2_file', + '1230_GeneralUserGS_sf2_file', + '1230_JCLive_sf2_file', + '1230_SBLive_sf2', + '1230_SoundBlasterOld_sf2', + '1231_Aspirin_sf2_file', + '1231_GeneralUserGS_sf2_file', + '1232_Aspirin_sf2_file', + '1232_GeneralUserGS_sf2_file', + '1233_GeneralUserGS_sf2_file', + '1234_GeneralUserGS_sf2_file', + '1240_Aspirin_sf2_file', + '1240_Chaos_sf2_file', + '1240_FluidR3_GM_sf2_file', + '1240_GeneralUserGS_sf2_file', + '1240_JCLive_sf2_file', + '1240_SBLive_sf2', + '1240_SoundBlasterOld_sf2', + '1241_Aspirin_sf2_file', + '1241_GeneralUserGS_sf2_file', + '1242_Aspirin_sf2_file', + '1242_GeneralUserGS_sf2_file', + '1243_Aspirin_sf2_file', + '1243_GeneralUserGS_sf2_file', + '1244_Aspirin_sf2_file', + '1244_GeneralUserGS_sf2_file', + '1250_Aspirin_sf2_file', + '1250_Chaos_sf2_file', + '1250_FluidR3_GM_sf2_file', + '1250_GeneralUserGS_sf2_file', + '1250_JCLive_sf2_file', + '1250_SBLive_sf2', + '1250_SoundBlasterOld_sf2', + '1251_Aspirin_sf2_file', + '1251_FluidR3_GM_sf2_file', + '1251_GeneralUserGS_sf2_file', + '1252_Aspirin_sf2_file', + '1252_FluidR3_GM_sf2_file', + '1252_GeneralUserGS_sf2_file', + '1253_Aspirin_sf2_file', + '1253_GeneralUserGS_sf2_file', + '1254_Aspirin_sf2_file', + '1254_GeneralUserGS_sf2_file', + '1255_Aspirin_sf2_file', + '1255_GeneralUserGS_sf2_file', + '1256_Aspirin_sf2_file', + '1256_GeneralUserGS_sf2_file', + '1257_Aspirin_sf2_file', + '1257_GeneralUserGS_sf2_file', + '1258_Aspirin_sf2_file', + '1258_GeneralUserGS_sf2_file', + '1259_GeneralUserGS_sf2_file', + '1260_Aspirin_sf2_file', + '1260_Chaos_sf2_file', + '1260_FluidR3_GM_sf2_file', + '1260_GeneralUserGS_sf2_file', + '1260_JCLive_sf2_file', + '1260_SBLive_sf2', + '1260_SoundBlasterOld_sf2', + '1261_Aspirin_sf2_file', + '1261_GeneralUserGS_sf2_file', + '1262_Aspirin_sf2_file', + '1262_GeneralUserGS_sf2_file', + '1263_Aspirin_sf2_file', + '1263_GeneralUserGS_sf2_file', + '1264_Aspirin_sf2_file', + '1264_GeneralUserGS_sf2_file', + '1265_Aspirin_sf2_file', + '1265_GeneralUserGS_sf2_file', + '1270_Aspirin_sf2_file', + '1270_Chaos_sf2_file', + '1270_FluidR3_GM_sf2_file', + '1270_GeneralUserGS_sf2_file', + '1270_JCLive_sf2_file', + '1270_SBLive_sf2', + '1270_SoundBlasterOld_sf2', + '1271_Aspirin_sf2_file', + '1271_GeneralUserGS_sf2_file', + '1272_Aspirin_sf2_file', + '1272_GeneralUserGS_sf2_file', + '1273_GeneralUserGS_sf2_file', + '1274_GeneralUserGS_sf2_file', +]; + +export const drums = [ + //'35_0_SBLive_sf2' + '35_0_Chaos_sf2_file', + '35_12_JCLive_sf2_file', + '35_16_JCLive_sf2_file', + '35_18_JCLive_sf2_file', + '35_4_Chaos_sf2_file', + '36_0_SBLive_sf2', + '36_12_JCLive_sf2_file', + '36_16_JCLive_sf2_file', + '36_18_JCLive_sf2_file', + '36_4_Chaos_sf2_file', + '37_0_SBLive_sf2', + '37_12_JCLive_sf2_file', + '37_16_JCLive_sf2_file', + '37_18_JCLive_sf2_file', + '37_4_Chaos_sf2_file', + '38_0_SBLive_sf2', + '38_12_JCLive_sf2_file', + '38_16_JCLive_sf2_file', + '38_18_JCLive_sf2_file', + '38_4_Chaos_sf2_file', + '39_0_SBLive_sf2', + '39_12_JCLive_sf2_file', + '39_16_JCLive_sf2_file', + '39_18_JCLive_sf2_file', + '39_4_Chaos_sf2_file', + '40_0_SBLive_sf2', + '40_12_JCLive_sf2_file', + '40_16_JCLive_sf2_file', + '40_18_JCLive_sf2_file', + '40_4_Chaos_sf2_file', + '41_0_SBLive_sf2', + '41_12_JCLive_sf2_file', + '41_16_JCLive_sf2_file', + '41_18_JCLive_sf2_file', + '41_4_Chaos_sf2_file', + '42_0_SBLive_sf2', + '42_12_JCLive_sf2_file', + '42_16_JCLive_sf2_file', + '42_18_JCLive_sf2_file', + '42_4_Chaos_sf2_file', + '43_0_SBLive_sf2', + '43_12_JCLive_sf2_file', + '43_16_JCLive_sf2_file', + '43_18_JCLive_sf2_file', + '43_4_Chaos_sf2_file', + '44_0_SBLive_sf2', + '44_12_JCLive_sf2_file', + '44_16_JCLive_sf2_file', + '44_18_JCLive_sf2_file', + '44_4_Chaos_sf2_file', + '45_0_SBLive_sf2', + '45_12_JCLive_sf2_file', + '45_16_JCLive_sf2_file', + '45_18_JCLive_sf2_file', + '45_4_Chaos_sf2_file', + '46_0_SBLive_sf2', + '46_12_JCLive_sf2_file', + '46_16_JCLive_sf2_file', + '46_18_JCLive_sf2_file', + '46_4_Chaos_sf2_file', + '47_0_SBLive_sf2', + '47_12_JCLive_sf2_file', + '47_16_JCLive_sf2_file', + '47_18_JCLive_sf2_file', + '47_4_Chaos_sf2_file', + '48_0_SBLive_sf2', + '48_12_JCLive_sf2_file', + '48_16_JCLive_sf2_file', + '48_18_JCLive_sf2_file', + '48_4_Chaos_sf2_file', + '49_0_SBLive_sf2', + '49_12_JCLive_sf2_file', + '49_16_JCLive_sf2_file', + '49_18_JCLive_sf2_file', + '49_4_Chaos_sf2_file', + '50_0_SBLive_sf2', + '50_12_JCLive_sf2_file', + '50_16_JCLive_sf2_file', + '50_18_JCLive_sf2_file', + '50_4_Chaos_sf2_file', + '51_0_SBLive_sf2', + '51_12_JCLive_sf2_file', + '51_16_JCLive_sf2_file', + '51_18_JCLive_sf2_file', + '51_4_Chaos_sf2_file', + '52_0_SBLive_sf2', + '52_12_JCLive_sf2_file', + '52_16_JCLive_sf2_file', + '52_18_JCLive_sf2_file', + '52_4_Chaos_sf2_file', + '53_0_SBLive_sf2', + '53_12_JCLive_sf2_file', + '53_16_JCLive_sf2_file', + '53_18_JCLive_sf2_file', + '53_4_Chaos_sf2_file', + '54_0_SBLive_sf2', + '54_12_JCLive_sf2_file', + '54_16_JCLive_sf2_file', + '54_18_JCLive_sf2_file', + '54_4_Chaos_sf2_file', + '55_0_SBLive_sf2', + '55_12_JCLive_sf2_file', + '55_16_JCLive_sf2_file', + '55_18_JCLive_sf2_file', + '55_4_Chaos_sf2_file', + '56_0_SBLive_sf2', + '56_12_JCLive_sf2_file', + '56_16_JCLive_sf2_file', + '56_18_JCLive_sf2_file', + '56_4_Chaos_sf2_file', + '57_0_SBLive_sf2', + '57_12_JCLive_sf2_file', + '57_16_JCLive_sf2_file', + '57_18_JCLive_sf2_file', + '57_4_Chaos_sf2_file', + '58_0_SBLive_sf2', + '58_12_JCLive_sf2_file', + '58_16_JCLive_sf2_file', + '58_18_JCLive_sf2_file', + '58_4_Chaos_sf2_file', + '59_0_SBLive_sf2', + '59_12_JCLive_sf2_file', + '59_16_JCLive_sf2_file', + '59_18_JCLive_sf2_file', + '59_4_Chaos_sf2_file', + '60_0_SBLive_sf2', + '60_12_JCLive_sf2_file', + '60_16_JCLive_sf2_file', + '60_18_JCLive_sf2_file', + '60_4_Chaos_sf2_file', + '61_0_SBLive_sf2', + '61_12_JCLive_sf2_file', + '61_16_JCLive_sf2_file', + '61_18_JCLive_sf2_file', + '61_4_Chaos_sf2_file', + '62_0_SBLive_sf2', + '62_12_JCLive_sf2_file', + '62_16_JCLive_sf2_file', + '62_18_JCLive_sf2_file', + '62_4_Chaos_sf2_file', + '63_0_SBLive_sf2', + '63_12_JCLive_sf2_file', + '63_16_JCLive_sf2_file', + '63_18_JCLive_sf2_file', + '63_4_Chaos_sf2_file', + '64_0_SBLive_sf2', + '64_12_JCLive_sf2_file', + '64_16_JCLive_sf2_file', + '64_18_JCLive_sf2_file', + '64_4_Chaos_sf2_file', + '65_0_SBLive_sf2', + '65_12_JCLive_sf2_file', + '65_16_JCLive_sf2_file', + '65_18_JCLive_sf2_file', + '65_4_Chaos_sf2_file', + '66_0_SBLive_sf2', + '66_12_JCLive_sf2_file', + '66_16_JCLive_sf2_file', + '66_18_JCLive_sf2_file', + '66_4_Chaos_sf2_file', + '67_0_SBLive_sf2', + '67_12_JCLive_sf2_file', + '67_16_JCLive_sf2_file', + '67_18_JCLive_sf2_file', + '67_4_Chaos_sf2_file', + '68_0_SBLive_sf2', + '68_12_JCLive_sf2_file', + '68_16_JCLive_sf2_file', + '68_18_JCLive_sf2_file', + '68_4_Chaos_sf2_file', + '69_0_SBLive_sf2', + '69_12_JCLive_sf2_file', + '69_16_JCLive_sf2_file', + '69_18_JCLive_sf2_file', + '69_4_Chaos_sf2_file', + '70_0_SBLive_sf2', + '70_12_JCLive_sf2_file', + '70_16_JCLive_sf2_file', + '70_18_JCLive_sf2_file', + '70_4_Chaos_sf2_file', + '71_0_SBLive_sf2', + '71_12_JCLive_sf2_file', + '71_16_JCLive_sf2_file', + '71_18_JCLive_sf2_file', + '71_4_Chaos_sf2_file', + '72_0_SBLive_sf2', + '72_12_JCLive_sf2_file', + '72_16_JCLive_sf2_file', + '72_18_JCLive_sf2_file', + '72_4_Chaos_sf2_file', + '73_0_SBLive_sf2', + '73_12_JCLive_sf2_file', + '73_16_JCLive_sf2_file', + '73_18_JCLive_sf2_file', + '73_4_Chaos_sf2_file', + '74_0_SBLive_sf2', + '74_12_JCLive_sf2_file', + '74_16_JCLive_sf2_file', + '74_18_JCLive_sf2_file', + '74_4_Chaos_sf2_file', + '75_0_SBLive_sf2', + '75_12_JCLive_sf2_file', + '75_16_JCLive_sf2_file', + '75_18_JCLive_sf2_file', + '75_4_Chaos_sf2_file', + '76_0_SBLive_sf2', + '76_12_JCLive_sf2_file', + '76_16_JCLive_sf2_file', + '76_18_JCLive_sf2_file', + '76_4_Chaos_sf2_file', + '77_0_SBLive_sf2', + '77_12_JCLive_sf2_file', + '77_16_JCLive_sf2_file', + '77_18_JCLive_sf2_file', + '77_4_Chaos_sf2_file', + '78_0_SBLive_sf2', + '78_12_JCLive_sf2_file', + '78_16_JCLive_sf2_file', + '78_18_JCLive_sf2_file', + '78_4_Chaos_sf2_file', + '79_0_SBLive_sf2', + '79_12_JCLive_sf2_file', + '79_16_JCLive_sf2_file', + '79_18_JCLive_sf2_file', + '79_4_Chaos_sf2_file', + '80_0_SBLive_sf2', + '80_12_JCLive_sf2_file', + '80_16_JCLive_sf2_file', + '80_18_JCLive_sf2_file', + '80_4_Chaos_sf2_file', + '81_0_SBLive_sf2', + '81_12_JCLive_sf2_file', + '81_16_JCLive_sf2_file', + '81_18_JCLive_sf2_file', + '81_4_Chaos_sf2_file', +]; + +// see https://www.midi.org/specifications-old/item/gm-level-1-sound-set +export const instrumentNames = []; +instrumentNames[0] = 'Acoustic Grand Piano: Piano'; +instrumentNames[1] = 'Bright Acoustic Piano: Piano'; +instrumentNames[2] = 'Electric Grand Piano: Piano'; +instrumentNames[3] = 'Honky-tonk Piano: Piano'; +instrumentNames[4] = 'Electric Piano 1: Piano'; +instrumentNames[5] = 'Electric Piano 2: Piano'; +instrumentNames[6] = 'Harpsichord: Piano'; +instrumentNames[7] = 'Clavinet: Piano'; +instrumentNames[8] = 'Celesta: Chromatic Percussion'; +instrumentNames[9] = 'Glockenspiel: Chromatic Percussion'; +instrumentNames[10] = 'Music Box: Chromatic Percussion'; +instrumentNames[11] = 'Vibraphone: Chromatic Percussion'; +instrumentNames[12] = 'Marimba: Chromatic Percussion'; +instrumentNames[13] = 'Xylophone: Chromatic Percussion'; +instrumentNames[14] = 'Tubular Bells: Chromatic Percussion'; +instrumentNames[15] = 'Dulcimer: Chromatic Percussion'; +instrumentNames[16] = 'Drawbar Organ: Organ'; +instrumentNames[17] = 'Percussive Organ: Organ'; +instrumentNames[18] = 'Rock Organ: Organ'; +instrumentNames[19] = 'Church Organ: Organ'; +instrumentNames[20] = 'Reed Organ: Organ'; +instrumentNames[21] = 'Accordion: Organ'; +instrumentNames[22] = 'Harmonica: Organ'; +instrumentNames[23] = 'Tango Accordion: Organ'; +instrumentNames[24] = 'Acoustic Guitar (nylon): Guitar'; +instrumentNames[25] = 'Acoustic Guitar (steel): Guitar'; +instrumentNames[26] = 'Electric Guitar (jazz): Guitar'; +instrumentNames[27] = 'Electric Guitar (clean): Guitar'; +instrumentNames[28] = 'Electric Guitar (muted): Guitar'; +instrumentNames[29] = 'Overdriven Guitar: Guitar'; +instrumentNames[30] = 'Distortion Guitar: Guitar'; +instrumentNames[31] = 'Guitar Harmonics: Guitar'; +instrumentNames[32] = 'Acoustic Bass: Bass'; +instrumentNames[33] = 'Electric Bass (finger): Bass'; +instrumentNames[34] = 'Electric Bass (pick): Bass'; +instrumentNames[35] = 'Fretless Bass: Bass'; +instrumentNames[36] = 'Slap Bass 1: Bass'; +instrumentNames[37] = 'Slap Bass 2: Bass'; +instrumentNames[38] = 'Synth Bass 1: Bass'; +instrumentNames[39] = 'Synth Bass 2: Bass'; +instrumentNames[40] = 'Violin: Strings'; +instrumentNames[41] = 'Viola: Strings'; +instrumentNames[42] = 'Cello: Strings'; +instrumentNames[43] = 'Contrabass: Strings'; +instrumentNames[44] = 'Tremolo Strings: Strings'; +instrumentNames[45] = 'Pizzicato Strings: Strings'; +instrumentNames[46] = 'Orchestral Harp: Strings'; +instrumentNames[47] = 'Timpani: Strings'; +instrumentNames[48] = 'String Ensemble 1: Ensemble'; +instrumentNames[49] = 'String Ensemble 2: Ensemble'; +instrumentNames[50] = 'Synth Strings 1: Ensemble'; +instrumentNames[51] = 'Synth Strings 2: Ensemble'; +instrumentNames[52] = 'Choir Aahs: Ensemble'; +instrumentNames[53] = 'Voice Oohs: Ensemble'; +instrumentNames[54] = 'Synth Choir: Ensemble'; +instrumentNames[55] = 'Orchestra Hit: Ensemble'; +instrumentNames[56] = 'Trumpet: Brass'; +instrumentNames[57] = 'Trombone: Brass'; +instrumentNames[58] = 'Tuba: Brass'; +instrumentNames[59] = 'Muted Trumpet: Brass'; +instrumentNames[60] = 'French Horn: Brass'; +instrumentNames[61] = 'Brass Section: Brass'; +instrumentNames[62] = 'Synth Brass 1: Brass'; +instrumentNames[63] = 'Synth Brass 2: Brass'; +instrumentNames[64] = 'Soprano Sax: Reed'; +instrumentNames[65] = 'Alto Sax: Reed'; +instrumentNames[66] = 'Tenor Sax: Reed'; +instrumentNames[67] = 'Baritone Sax: Reed'; +instrumentNames[68] = 'Oboe: Reed'; +instrumentNames[69] = 'English Horn: Reed'; +instrumentNames[70] = 'Bassoon: Reed'; +instrumentNames[71] = 'Clarinet: Reed'; +instrumentNames[72] = 'Piccolo: Pipe'; +instrumentNames[73] = 'Flute: Pipe'; +instrumentNames[74] = 'Recorder: Pipe'; +instrumentNames[75] = 'Pan Flute: Pipe'; +instrumentNames[76] = 'Blown bottle: Pipe'; +instrumentNames[77] = 'Shakuhachi: Pipe'; +instrumentNames[78] = 'Whistle: Pipe'; +instrumentNames[79] = 'Ocarina: Pipe'; +instrumentNames[80] = 'Lead 1 (square): Synth Lead'; +instrumentNames[81] = 'Lead 2 (sawtooth): Synth Lead'; +instrumentNames[82] = 'Lead 3 (calliope): Synth Lead'; +instrumentNames[83] = 'Lead 4 (chiff): Synth Lead'; +instrumentNames[84] = 'Lead 5 (charang): Synth Lead'; +instrumentNames[85] = 'Lead 6 (voice): Synth Lead'; +instrumentNames[86] = 'Lead 7 (fifths): Synth Lead'; +instrumentNames[87] = 'Lead 8 (bass + lead): Synth Lead'; +instrumentNames[88] = 'Pad 1 (new age): Synth Pad'; +instrumentNames[89] = 'Pad 2 (warm): Synth Pad'; +instrumentNames[90] = 'Pad 3 (polysynth): Synth Pad'; +instrumentNames[91] = 'Pad 4 (choir): Synth Pad'; +instrumentNames[92] = 'Pad 5 (bowed): Synth Pad'; +instrumentNames[93] = 'Pad 6 (metallic): Synth Pad'; +instrumentNames[94] = 'Pad 7 (halo): Synth Pad'; +instrumentNames[95] = 'Pad 8 (sweep): Synth Pad'; +instrumentNames[96] = 'FX 1 (rain): Synth Effects'; +instrumentNames[97] = 'FX 2 (soundtrack): Synth Effects'; +instrumentNames[98] = 'FX 3 (crystal): Synth Effects'; +instrumentNames[99] = 'FX 4 (atmosphere): Synth Effects'; +instrumentNames[100] = 'FX 5 (brightness): Synth Effects'; +instrumentNames[101] = 'FX 6 (goblins): Synth Effects'; +instrumentNames[102] = 'FX 7 (echoes): Synth Effects'; +instrumentNames[103] = 'FX 8 (sci-fi): Synth Effects'; +instrumentNames[104] = 'Sitar: Ethnic'; +instrumentNames[105] = 'Banjo: Ethnic'; +instrumentNames[106] = 'Shamisen: Ethnic'; +instrumentNames[107] = 'Koto: Ethnic'; +instrumentNames[108] = 'Kalimba: Ethnic'; +instrumentNames[109] = 'Bagpipe: Ethnic'; +instrumentNames[110] = 'Fiddle: Ethnic'; +instrumentNames[111] = 'Shanai: Ethnic'; +instrumentNames[112] = 'Tinkle Bell: Percussive'; +instrumentNames[113] = 'Agogo: Percussive'; +instrumentNames[114] = 'Steel Drums: Percussive'; +instrumentNames[115] = 'Woodblock: Percussive'; +instrumentNames[116] = 'Taiko Drum: Percussive'; +instrumentNames[117] = 'Melodic Tom: Percussive'; +instrumentNames[118] = 'Synth Drum: Percussive'; +instrumentNames[119] = 'Reverse Cymbal: Percussive'; +instrumentNames[120] = 'Guitar Fret Noise: Sound effects'; +instrumentNames[121] = 'Breath Noise: Sound effects'; +instrumentNames[122] = 'Seashore: Sound effects'; +instrumentNames[123] = 'Bird Tweet: Sound effects'; +instrumentNames[124] = 'Telephone Ring: Sound effects'; +instrumentNames[125] = 'Helicopter: Sound effects'; +instrumentNames[126] = 'Applause: Sound effects'; +instrumentNames[127] = 'Gunshot: Sound effects'; diff --git a/packages/soundfonts/package.json b/packages/soundfonts/package.json index accb43e5..bf4f7527 100644 --- a/packages/soundfonts/package.json +++ b/packages/soundfonts/package.json @@ -6,6 +6,7 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, + "type": "module", "repository": { "type": "git", "url": "git+https://github.com/tidalcycles/strudel.git" @@ -24,8 +25,10 @@ }, "homepage": "https://github.com/tidalcycles/strudel#readme", "dependencies": { - "webaudiofont": "^3.0.1", "@strudel.cycles/core": "*", "@strudel.cycles/webaudio": "*" + }, + "devDependencies": { + "node-fetch": "^3.2.6" } } diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index 77d7e235..bdd38bbc 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -39,6 +39,54 @@ const getADSR = (attack, decay, sustain, release, velocity, begin, end) => { return gainNode; }; +const getOscillator = ({ s, freq, t, duration, release }) => { + // make oscillator + const o = getAudioContext().createOscillator(); + o.type = s || 'triangle'; + o.frequency.value = Number(freq); + o.start(t); + o.stop(t + duration + release); + return o; +}; + +const getSoundfontKey = (s) => { + if (!globalThis.soundfontList) { + // soundfont package not loaded + return false; + } + if (globalThis.soundfontList?.instruments?.includes(s)) { + return s; + } + // check if s is one of the soundfonts, which are loaded into globalThis, to avoid coupling both packages + const nameIndex = globalThis.soundfontList?.instrumentNames?.indexOf(s); + // convert number nameIndex (0-128) to 3 digit string (001-128) + const name = nameIndex < 10 ? `00${nameIndex}` : nameIndex < 100 ? `0${nameIndex}` : nameIndex; + if (nameIndex !== -1) { + // TODO: indices of instrumentNames do not seem to match instruments + s = globalThis.soundfontList.instruments.find((instrument) => instrument.startsWith(name)); + // console.log('match', nameIndex, s); + } + return globalThis.soundfontList?.instruments?.[nameIndex]; +}; + +const getSampleBufferSource = async (s, n) => { + const ac = getAudioContext(); + // is sample from loaded samples(..) + const samples = getLoadedSamples(); + if (!samples) { + throw new Error('no samples loaded'); + } + const bank = samples?.[s]; + if (!bank) { + throw new Error('sample not found:', s, 'try one of ' + Object.keys(samples)); + } + const sampleUrl = bank[n % bank.length]; + const buffer = await loadBuffer(sampleUrl, ac); + const bufferSource = ac.createBufferSource(); + bufferSource.buffer = buffer; + return bufferSource; +}; + Pattern.prototype.out = function () { return this.onTrigger(async (t, hap, ct) => { const ac = getAudioContext(); @@ -48,6 +96,7 @@ Pattern.prototype.out = function () { let { freq, s, + sf, n = 0, gain = 1, cutoff, @@ -67,20 +116,16 @@ Pattern.prototype.out = function () { } = hap.value; // the chain will hold all audio nodes that connect to each other const chain = []; + if (typeof n === 'string') { + n = toMidi(n); // e.g. c3 => 48 + } if (!s || ['sine', 'square', 'triangle', 'sawtooth'].includes(s)) { // get frequency if (!freq && typeof n === 'number') { freq = fromMidi(n); // + 48); } - if (!freq && typeof n === 'string') { - freq = fromMidi(toMidi(n)); - } // make oscillator - const o = ac.createOscillator(); - o.type = s || 'triangle'; - o.frequency.value = Number(freq); - o.start(t); - o.stop(t + hap.duration + release); + const o = getOscillator({ t, s, freq, duration: hap.duration, release }); chain.push(o); // level down oscillators as they are really loud compared to samples i've tested const g = ac.createGain(); @@ -92,42 +137,57 @@ Pattern.prototype.out = function () { chain.push(adsr); } else { // load sample - const samples = getLoadedSamples(); - if (!samples) { - console.warn('no samples loaded'); + if (speed === 0) { + // no playback return; } - const bank = samples?.[s]; - if (!bank) { - console.warn('sample not found:', s, 'try one of ' + Object.keys(samples)); + if (!s) { + console.warn('no sample specified'); return; - } else { - if (speed === 0) { - // no playback - return; - } - if (!s) { - console.warn('no sample specified'); - return; - } - const bank = samples[s]; - const sampleUrl = bank[n % bank.length]; - let buffer = await loadBuffer(sampleUrl, ac); - if (ac.currentTime > t) { - console.warn('sample still loading:', s, n); - return; - } - const src = ac.createBufferSource(); - src.buffer = buffer; - src.playbackRate.value = Math.abs(speed); - // TODO: nudge, unit, cut, loop + } + const soundfont = getSoundfontKey(s); + let bufferSource; - let duration = src.buffer.duration; - const offset = begin * duration; - duration = ((end - begin) * duration) / Math.abs(speed); - src.start(t, offset, duration); - src.stop(t + duration); - chain.push(src); + try { + if (soundfont) { + // is soundfont + bufferSource = await globalThis.getFontBufferSource(soundfont, n, ac); + } else { + // is sample from loaded samples(..) + bufferSource = await getSampleBufferSource(s, n); + } + } catch (err) { + console.warn(err); + return; + } + // asny stuff above took too long? + if (ac.currentTime > t) { + console.warn('sample still loading:', s, n); + return; + } + if (!bufferSource) { + console.warn('no buffer source'); + return; + } + // bufferSource.playbackRate.value = Math.abs(speed) * playbackRate; + bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value; + // TODO: nudge, unit, cut, loop + + let duration = soundfont ? hap.duration : bufferSource.buffer.duration; + // let duration = bufferSource.buffer.duration; + const offset = begin * duration; + duration = ((end - begin) * duration) / Math.abs(speed); + bufferSource.start(t, offset, duration); + bufferSource.stop(t + duration); + chain.push(bufferSource); + if (soundfont) { + const env = ac.createGain(); + env.gain.value = 1; + const fadeLength = 0.1; + env.gain.value = 0.5; + env.gain.setValueAtTime(0.5, t + duration - fadeLength); + env.gain.linearRampToValueAtTime(0, t + duration); + chain.push(env); } } // filters