{"id":13768843,"url":"https://github.com/g200kg/webaudio-tinysynth","last_synced_at":"2026-02-22T01:44:40.172Z","repository":{"id":17664846,"uuid":"82438302","full_name":"g200kg/webaudio-tinysynth","owner":"g200kg","description":"Light-weight GM mapped WebAudio-JavaScript Synthesizer Engine / MIDI Player","archived":false,"fork":false,"pushed_at":"2022-12-20T04:31:49.000Z","size":2058,"stargazers_count":247,"open_issues_count":4,"forks_count":25,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-09-14T13:42:09.808Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/g200kg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-19T05:46:52.000Z","updated_at":"2025-08-25T17:42:09.000Z","dependencies_parsed_at":"2022-08-31T09:53:18.428Z","dependency_job_id":null,"html_url":"https://github.com/g200kg/webaudio-tinysynth","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/g200kg/webaudio-tinysynth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g200kg%2Fwebaudio-tinysynth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g200kg%2Fwebaudio-tinysynth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g200kg%2Fwebaudio-tinysynth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g200kg%2Fwebaudio-tinysynth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/g200kg","download_url":"https://codeload.github.com/g200kg/webaudio-tinysynth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g200kg%2Fwebaudio-tinysynth/sbom","scorecard":{"id":415908,"data":{"date":"2025-08-11","repo":{"name":"github.com/g200kg/webaudio-tinysynth","commit":"3d75aee4b3f43cbd932265e7d60201fd5b770397"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":7,"reason":"Found 6/8 approved changesets -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T23:51:16.520Z","repository_id":17664846,"created_at":"2025-08-18T23:51:16.520Z","updated_at":"2025-08-18T23:51:16.520Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29703227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T23:35:04.139Z","status":"ssl_error","status_checked_at":"2026-02-21T23:35:03.832Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T16:01:26.600Z","updated_at":"2026-02-22T01:44:40.153Z","avatar_url":"https://github.com/g200kg.png","language":"JavaScript","funding_links":[],"categories":["MIDI instruments","Packages"],"sub_categories":["Synths","Apps"],"readme":"# webaudio-tinysynth\nWebAudio Tiny GM mapped Synthesizer [JavaScript]\n\n[![npm](https://img.shields.io/npm/v/webaudio-tinysynth.svg)](https://www.npmjs.com/package/webaudio-tinysynth)\n\n## Overview\n\n**webaudio-tinysynth** is a small synthesizer written in JavaScript with GM like timbre map.\nAll timbres are generated by the combinations of Oscillator and dynamically generated BufferSource algolithmically without any PCM samples.\n\n- There are two ways to use this library, CustomElement or simple Javascript library.\n  The CustomElement can be used by a Tag in HTML, '\u0026lt;webaudio-tinysynth\u0026gt;\u0026lt;/webaudio-tinysynth\u0026gt;'. It has small graphical display and play controls like HTML5 \u0026lt;audio\u0026gt; tags. MIDI file drop is also acceptable. JavaScript version has no GUI and everything are controlled by function call. The synthesizer instance will be created like this: 'synth = new WebAudioTinySynth()'. You can control from the JavaScript API in the same way in either usage.\n\n- The APIs are MIDI like. Function  `send([midi-message],timestamp)` receives MIDI message and generate sounds.\n\n- Two timbre set are supported. These are switched by `quality` option. `quality=0` mode is light-weight chip-tune like sounds that use 1 osc per 1 note. `quality=1` mode is FM based sounds and use 2 or more osc per 1 note.\n\n- webaudio-tinysynth has a built-in MIDI-SMF (.mid file) sequencer. It is initiated by function call or MIDI file drag \u0026 drop.\n\nCustomElement version GUI :  \n![./tinysynth0.png](./tinysynth0.png)  MIDI files is not loaded  \n\n![./tinysynth1.png](./tinysynth1.png)  MIDI files is loaded  \nUpper red indicator shows Note#  \nLower red indicator shows MIDI ch.  \n\n## Files\n  **webaudio-tinysynth.js** : JavaScript library  \n  **webaudio-tinysynth.min.js** : JavaScript library minified version  \n  Each one works with only one file, there are no dependencies.\n\n## Environment\n Webaudio-tinysynth is confirmed to work with the following browsers\n  * Chrome / Firefox / Edge / Safari\n\n## Live Demo\nTest Pages are here :  \n [soundedit.html](https://g200kg.github.io/webaudio-tinysynth/soundedit.html)  (CustomElement playable demo with timbre edit function  / MIDI keyboard via WebMIDI API)  \n [simple.html](https://g200kg.github.io/webaudio-tinysynth/simple.html)  (Most simple sample of CustomElement)  \n [jstest.html](https://g200kg.github.io/webaudio-tinysynth/jstest.html)   (Use from simple JavaScript without GUI)\n\n## Usage\n\n### Load this Library\n\n* Necessary file is a `webaudio-tinysynth.js` ( or minified `webaudio-tinysynth.min.js` ) only. Deploy webaudio-tinysynth.js appropriately and load library:\n  * `\u003cscript src='webaudio-tinysynth.js'\u003e\u003c/script\u003e`.  \n  * Or load it from a CDN:  \n  `\u003cscript src='https://g200kg.github.io/webaudio-tinysynth/webaudio-tinysynth.js'\u003e\u003c/script\u003e`\n  * Or:  \n  `\u003cscript src='https://cdn.jsdelivr.net/npm/webaudio-tinysynth'\u003e\u003c/script\u003e`\n  * Or via npm (`npm install webaudio-tinysynth --save`):  \n  `var WebAudioTinySynth = require('webaudio-tinysynth');`\n\n### Without GUI\n\n* To make the instance of synthesizer without GUI, use following command :  \n`synth = new WebAudioTinySynth();`  \n  Some options are acceptable. For example :\n  * `synth = new WebAudioTinySynth({quality:0, useReverb:0});`\n\n* Then use the function calls described later for that instance. For example...  \n `synth.send([0x90, 60, 100]); // NoteOn:ch1 Note#:60 Velocity:100 `\n\n### With GUI\n\n+ If you want to run on older browsers that don't support custom elements, you need a polyfill of 'CustomElements'. Following script tag will load polyfill from CDN. Be sure to read polyfill before webaudio-tinysynth.js   \n* `\u003cscript src=\"https://unpkg.com/@webcomponents/custom-elements\"\u003e\u003c/script\u003e`\n\n* Place webaudio-tinysynth element in HTML  \n  * `\u003cwebaudio-tinysynth\u003e\u003c/webaudio-tinysynth\u003e`\n  * To get instance of synthesizer for JavaScript API, as usual:   \n  `synth = document.getElementById(\"wbaudio-tinysynth tag id here\");`\n\n## Attributes\n These attributes are for CustomElement.\n\n|Attribute          |Options|Default   |Description               |\n|-------------------|-------|----------|--------------------------|\n|**width**          |String |\"300px\"   | width of element         |\n|**height**         |String |\"32px\"    | height of element        |\n|**masterVol**      |Number | 1.0      | master volume            |\n|**reverbLev**      |Number | 0.3      | reverb level             |\n|**useReverb**      |Number | 1        | disable Reverb if 0. It makes a little save the CPU consumption.      |\n|**quality**        |Number | 1        | 0: 1osc/note chiptune like\u003cbr/\u003e 1: 2 or more oscs/note FM based|\n|**src**            |String |null      | .mid file url            |\n|**loop**           |Number | 0        | loop playMIDI            |\n|**disableDrop**    |Number | 0        | disable MIDI file drop   |\n|**graph**          |Number | 1        | enable waveform graph    |\n|**internalContext**|Number | 1        | Use internal audioContext|\n|**tsmode**         |Number | 0        | default timestamp mode   |\n|**perfmon**        |Number | 0        | performance monitor      |\n|**voices**         |Number | 64       | Max number of simultaneous voices. Large number needs more CPU.               |\n\n\n* In default, necessary audioContext will be created internally. `internalContext=\"0\"` will prevent this and should provide audioContext with `setAudioContext()` function.\n* Note that the webaudio-tinysynth may not be ready yet immediately after 'window.onload' if you use 'CustomElement'. especially be careful if using webcomponents polyfill. Use `ready()` function for wait to complete th initialize that return a `Promise` that will be resolved when initialize completed.  \n `isReady` flag also be usable for confirming the synth is ready.\n\n```\n// use \"then\"\nsynth = document.getElementById(\"synth\");\nsynth.ready().then(()=\u003e{\n  ...\n});\n\n// or in \"async\" function : \nasync function() {\n  synth = document.getElementById(\"synth\");\n  await synth.ready();\n  ...\n}\n\n```\n\n## Functions\n  These functions are available for polymer module and javascript version.  \n\n**WebAudioTinySynth(options)**  \n\u003e Constructor of WebAudioTinySynth for JavaScript version. This is not used for Polymer version. options is a object with members :  \n\n\u003e  **quality** : Specify timbre quality same as setQuality(). default is `1`.  \n\u003e  **useReverb** : If zero, disable reverb function.  \n\u003e  **voices** : max number of voices.\n\u003e\n\u003e  For example, `new WebAudioTinySynth({quality:0, useReverb:0, voices:32})`\n\n**getAudioContext()**  \n\u003e Get current in-use AudioContext.\n\n**setAudioContext(audioContext, destinationNode)**  \n\u003e In default, though audioContext is internally created and used, this function can specify `audioContext` should be used.  \n\u003e All sounds are routed to specified `destinationNode`, or audioContext.destination is used if destinationNode is not specified.  \n\u003e the audioContext in use currently can be accessed with `getAudioContext()` fucntion.\n\n**getTimbreName(m,n)**\n\u003e get name of specified timbre. m=0:normal channel voice,n=prog#. or m=1:drum track,n=note#\n\n**setQuality(q)**\n\u003e Switch timbre set.  \n\u003e q=0 : chip tune like 1 osc / note.  \n\u003e q=1 : FM based 2 (or more) osc / note.\n\n**setMasterVol(lev)**\n\u003e Master volume setting. default=0.5.\n\n**setReverbLev(lev)**\n\u003e Reverb Level setting. default=0.3.\n\n**setLoop(f)**\n\u003e if non zero, MIDI play is looped.\n\n**setVoices(v)**\n\u003e set max voices that simultaneous sounds, default is 64.\n\n**loadMIDI(mididata)**\n\u003e load MIDI data to built-in sequencer. mididata is a arraybuffer of SMF (.mid file contents).\n\n**loadMIDIUrl(url)**\n\u003e load MIDI data from specified url\n\n**playMIDI()**\n\u003e play loaded MIDI data.\n\n**stopMIDI()**\n\u003e stop playing MIDI data.\n\n**locateMIDI(tick)**\n\u003e locate current playing position in tick.\n\n**getPlayStatus()**\n\u003e get current MIDI sequence play status.\n\u003e return value is a object `{play:playstatus, curTick:currenttick, maxTick:maxtick}`\n\n**setTsMode(mode)**\n\u003e Set time stamp mode that is used in send() or Channel message functions.  \n\u003e If `mode=0` timestamp is a time of in-use audioContext's currentTime timeline.\n\u003e If `mode=1` timestamp is HighResolutionTime timeline.\n\n**setTimbre(m,n,p)**\n\u003e Even webaudio-tinysynth has defaultly GM mapped timbre set, This function can overwrite with user-definable timbre.  \n\u003e `m=0` : timbre for normal channel.  \n\u003e `m=1` : timbre for rhythm channel (ch=9).  \n\u003e `n` : program number for normal channel or notenumber for rhythm channel.  \n\u003e `p` : timbre object. Source of this object can be created by soundedit.html **(Details are not yet documented)**\n\n**reset()**\n\u003e Reset all channel to initial state. Including all controllers, program, chVol, pan and bendRange.\n\n**send([midi-message], t)**\n\u003e midi-message is an array of midi data-bytes for one message. For example,  \n\u003e `send([0x90, 60, 100], t)` is for NoteOn ch=1 note#=60 velocity=100.  \n\u003e `t` is a timestamp that this message should be processed.  \n\u003e The timeline of `t` is depends on timestampmode that is set by setTsMode() function.\n\u003e If timestampmode == 0 (default), `t` is a time (sec) in timeline of the in use audioContext.currentTime.  If timestampmode == 1, `t` is a time (msec) in HighResolutionTime (performance.now()) timeline.  \n\u003e In both timestamp mode, this message will be immediately processed if `t`=0 or omitted.\n\u003e If timestampmode is omitted, the mode depends on `tsmode` in Attributes.\n\n#### Channel Message Functions\n\nFollowings are voicing functions that controls each note directly. Each function is almost equivalent to corresponding `send([MIDI-message],t)` but prepared for human readability.  \n\nIn these functions, the `ch` parameter specify the MIDI channel. Each channel has individual timbre and set of control parameters, for example bend, modulation, expression, and so on. `ch` range is 0-15. (In MIDI spec., called 'channel 1-16')  \n`ch`==9 is a special channel for rhythm. In this channel, each note number is assigned to individual percussive instruments according to GM drummap (Note number 35-81).\n\nAlmost function has the timestamp, `t` parameter. That specify accurate timing of the effect occur. Refer `send()` function for details of timestamp. Anyway the command is immediately processed if `t` is 0 or omitted.\n\n**noteOn(ch, note, velo, t)**\n\u003e Generate a note in specified channel. `note` is the note number that specify pitch. `60` is middle 'C'. `velo` is velocity that control the volume of the note. velocity range is 0-127. this function is processed same as noteOff() if `velo` is `0`.\n\n**noteOff(ch, note, t)**\n\u003e stop the note that is generated by noteOn(). One noteOff() (or equivalent noteOn with velo=0) should be called corresponding to one noteOn() call.\n\n**setModulation(ch, val, t)**\n\u003e set modulation (vibrato) depth. `val` range is 0-127. +- 100 cent depth if val=127.\n\n**setChVol(ch, val, t)**\n\u003e set volume of the channel. `val` range is 0-127. Default value is 100.\n\n**setPan(ch, val, t)**\n\u003e Set pan of the channel. `val` range is 0-127. Default value=64.  \n\u003e  0:left  \n\u003e 64:center  \n\u003e 127:right.\n\n**setExpression(ch, val, t)**\n\u003e Set expression level. `val` range is 0-127. Both Expression and ChVol are control the Channel volume, but Expression is mainly used as note's articulation.  \n\n**setSustain(ch, val, t)**\n\u003e Set sustain pedal state. While sustain is on, generated notes in that channel are sustained even corresponding noteOff() is called. Note that `val` is judged as 'on' if `val\u003e=64`. Usually use `0` and `127` as a value.\n\n**setProgram(ch, pg)**\n\u003e Set timbre for that channel. `pg` range is 0-127 that is timbre number in GM map.\n\n**setBend(ch, val, t)**\n\u003e Set pitch bend state. Notes in this channel are all affected to this pitch modification. `val` range is 0 to 16384 and the center with no bend is 8192. sensitivity is depends on `setBendRange()` setting. Default state is `8192`.\n\n**setBendRange(ch, val)**\n\u003e Set bend sensitivity for that channel. `val` unit is 100/127 cent. That means +-1 octave if 0x600, +-1 semitone if 0x80.\n Default value is 0x100 that means +-200 cent (2 semitone) range.\n\n**allSoundOff(ch)**\n\u003e Stop all sound of specified ch immediately. All notes initiated by noteOn() go to noteOff state.\n\n**resetAllControllers(ch)**\n\u003e Control parameters of specified ch are reset. It includes Bend / Modulation / Expression / Sustain.\n\n## MIDI implimentation chart\n\n|                        |Recognized|Description                     |\n|------------------------|----------|--------------------------------|\n|**Basic Channel**       | Yes      | 1-16. ch10 = drum track        |\n|**NoteOn / NoteOff**    | Yes      | note# 0-127 / velocity 0-127   |\n|**Polyphonic Pressure** | No       |                                |\n|**Control Change**      | Yes      | see bellow                     |\n|**Program Change**      | Yes      | program 0-127                  |\n|**Channel Pressure**    | No       |                                |\n|**Pitch Bend**          | Yes      | -8192 - +8191                  |\n|------------------------|----------|--------------------------------|\n|**Control Number**      |          |                                |\n|**1**                   | Yes      | Modulation                     |\n|**6 / 38**              | Yes      | Data Entry                     |\n|**7**                   | Yes      | Channel Volume                 |\n|**10**                  | Yes      | Pan                            |\n|**11**                  | Yes      | Expression                     |\n|**64**                  | Yes      | Sustain                        |\n|**100/101**             | Yes      | RPN Index                      |\n|------------------------|----------|--------------------------------|\n|**Channel Mode Message**|          |                                |\n|**120**                 | Yes      | all sound off                  |\n|**121**                 | Yes      | reset all controller           |\n|**123**                 | Yes      | all note off                   |\n|------------------------|----------|--------------------------------|\n|**RPN**                 |          |                                |\n|**0**                   | Yes      | Bend Range                     |\n|**1**                   | Yes      | Channel Fine Tuning            |\n|**2**                   | Yes      | Channel Coarse Tuning          |\n|------------------------|----------|--------------------------------|\n|**Universal SysEx**     |          |                                |\n|**F0 F7 xx 04 03 lsb msb F7** | Yes | Master Fine Tuning            |\n|**F0 F7 xx 04 04 00 msb F7** | Yes | Master Coarse Tuning           |\n|------------------------|----------|--------------------------------|\n|**GS Exclusive**        |          |                                |\n|**F0 41 xx 42 12 40 00 05 xx xx xx xx sum F7** | Yes |Master Tuning |\n|**F0 41 xx 42 12 40 00 05 xx sum F7** | Yes    |Master Transpose    |\n|**F0 41 xx 42 12 40 1x 15 xx sum F7** | Yes    |Use For Rhythm Part |\n|**F0 41 xx 42 12 40 1x 4x xx sum F7** | Yes    |Scale Tuning        |\n|------------------------|----------|--------------------------------|\n\n## Timbre Object Structure\nAs you can see that in source code, each timbre is represented as a object array. Fore example the program# 1 \"Acoustic Grand Piano\" is like this :\n\n```\n[{w:\"sine\",v:.4,d:0.7,r:0.1,},{w:\"triangle\",v:3,d:0.7,s:0.1,g:1,a:0.01,k:-1.2}]\n```\nEach element of the array means a oscillator and object member means :  \n* g: output destination 0=final output / n=FM to specified osc\n* w: waveform  \n     \"sine\"/\"sawtooth\"/\"square\"/\"triangle\" (basic waveforms)  \n     \"w9999\" (summing 1-4 harmonics)  \n     \"n0\" (white noise)  \n     \"n1\" (metalic noise)  \n* v: volume  \n* t: tune factor according to note#\n* f: fixed frequency in Hz\n* a: attack time\n* h: hold time\n* d: decay time\n* s: sustain level\n* r: release time  (5 params make AHDSR envelope)\n* p: pitch bend\n* q: pitch bend speed factor\n* k: volume key tracking factor\n\nYou can test how these parameter work with 'Timbre Editor' panel in 'soundedit.html'.  And the created timbre can be used with `setTimbre()` function.\n\n## License\n\nLicensed under the Apache License, Version 2.0","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg200kg%2Fwebaudio-tinysynth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fg200kg%2Fwebaudio-tinysynth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg200kg%2Fwebaudio-tinysynth/lists"}