( function(window){ "use strict"; function WebAudioTinySynthCore(target) { Object.assign(target,{ properties:{ masterVol: {type:Number, value:0.5, observer:"setMasterVol"}, reverbLev: {type:Number, value:0.3, observer:"setReverbLev"}, quality: {type:Number, value:1, observer:"setQuality"}, debug: {type:Number, value:0}, src: {type:String, value:null, observer:"loadMIDIfromSrc"}, loop: {type:Number, value:0}, internalcontext: {type:Number, value:1}, tsmode: {type:Number, value:0}, voices: {type:Number, value:64}, useReverb: {type:Number, value:1}, /*@@gui*/ width: {type:String, value:"300px", observer:"layout"}, height: {type:String, value:"32px", observer:"layout"}, graph: {type:Number, value:1}, disabledrop:{type:Number, value:0}, perfmon: {type:Number, value:0}, /*@@guiEND*/ }, /*@@gui*/ layout:(()=>{ this.canvas.style.width=this.width; this.canvas.style.height=this.height; }), /*@@guiEND*/ program:[ // 1-8 : Piano {name:"Acoustic Grand Piano"}, {name:"Bright Acoustic Piano"}, {name:"Electric Grand Piano"}, {name:"Honky-tonk Piano"}, {name:"Electric Piano 1"}, {name:"Electric Piano 2"}, {name:"Harpsichord"}, {name:"Clavi"}, /* 9-16 : Chromatic Perc*/ {name:"Celesta"}, {name:"Glockenspiel"}, {name:"Music Box"}, {name:"Vibraphone"}, {name:"Marimba"}, {name:"Xylophone"}, {name:"Tubular Bells"}, {name:"Dulcimer"}, /* 17-24 : Organ */ {name:"Drawbar Organ"}, {name:"Percussive Organ"}, {name:"Rock Organ"}, {name:"Church Organ"}, {name:"Reed Organ"}, {name:"Accordion"}, {name:"Harmonica"}, {name:"Tango Accordion"}, /* 25-32 : Guitar */ {name:"Acoustic Guitar (nylon)"}, {name:"Acoustic Guitar (steel)"}, {name:"Electric Guitar (jazz)"}, {name:"Electric Guitar (clean)"}, {name:"Electric Guitar (muted)"}, {name:"Overdriven Guitar"}, {name:"Distortion Guitar"}, {name:"Guitar harmonics"}, /* 33-40 : Bass */ {name:"Acoustic Bass"}, {name:"Electric Bass (finger)"}, {name:"Electric Bass (pick)"}, {name:"Fretless Bass"}, {name:"Slap Bass 1"}, {name:"Slap Bass 2"}, {name:"Synth Bass 1"}, {name:"Synth Bass 2"}, /* 41-48 : Strings */ {name:"Violin"}, {name:"Viola"}, {name:"Cello"}, {name:"Contrabass"}, {name:"Tremolo Strings"}, {name:"Pizzicato Strings"}, {name:"Orchestral Harp"}, {name:"Timpani"}, /* 49-56 : Ensamble */ {name:"String Ensemble 1"}, {name:"String Ensemble 2"}, {name:"SynthStrings 1"}, {name:"SynthStrings 2"}, {name:"Choir Aahs"}, {name:"Voice Oohs"}, {name:"Synth Voice"}, {name:"Orchestra Hit"}, /* 57-64 : Brass */ {name:"Trumpet"}, {name:"Trombone"}, {name:"Tuba"}, {name:"Muted Trumpet"}, {name:"French Horn"}, {name:"Brass Section"}, {name:"SynthBrass 1"}, {name:"SynthBrass 2"}, /* 65-72 : Reed */ {name:"Soprano Sax"}, {name:"Alto Sax"}, {name:"Tenor Sax"}, {name:"Baritone Sax"}, {name:"Oboe"}, {name:"English Horn"}, {name:"Bassoon"}, {name:"Clarinet"}, /* 73-80 : Pipe */ {name:"Piccolo"}, {name:"Flute"}, {name:"Recorder"}, {name:"Pan Flute"}, {name:"Blown Bottle"}, {name:"Shakuhachi"}, {name:"Whistle"}, {name:"Ocarina"}, /* 81-88 : SynthLead */ {name:"Lead 1 (square)"}, {name:"Lead 2 (sawtooth)"}, {name:"Lead 3 (calliope)"}, {name:"Lead 4 (chiff)"}, {name:"Lead 5 (charang)"}, {name:"Lead 6 (voice)"}, {name:"Lead 7 (fifths)"}, {name:"Lead 8 (bass + lead)"}, /* 89-96 : SynthPad */ {name:"Pad 1 (new age)"}, {name:"Pad 2 (warm)"}, {name:"Pad 3 (polysynth)"}, {name:"Pad 4 (choir)"}, {name:"Pad 5 (bowed)"}, {name:"Pad 6 (metallic)"}, {name:"Pad 7 (halo)"}, {name:"Pad 8 (sweep)"}, /* 97-104 : FX */ {name:"FX 1 (rain)"}, {name:"FX 2 (soundtrack)"}, {name:"FX 3 (crystal)"}, {name:"FX 4 (atmosphere)"}, {name:"FX 5 (brightness)"}, {name:"FX 6 (goblins)"}, {name:"FX 7 (echoes)"}, {name:"FX 8 (sci-fi)"}, /* 105-112 : Ethnic */ {name:"Sitar"}, {name:"Banjo"}, {name:"Shamisen"}, {name:"Koto"}, {name:"Kalimba"}, {name:"Bag pipe"}, {name:"Fiddle"}, {name:"Shanai"}, /* 113-120 : Percussive */ {name:"Tinkle Bell"}, {name:"Agogo"}, {name:"Steel Drums"}, {name:"Woodblock"}, {name:"Taiko Drum"}, {name:"Melodic Tom"}, {name:"Synth Drum"}, {name:"Reverse Cymbal"}, /* 121-128 : SE */ {name:"Guitar Fret Noise"}, {name:"Breath Noise"}, {name:"Seashore"}, {name:"Bird Tweet"}, {name:"Telephone Ring"}, {name:"Helicopter"}, {name:"Applause"}, {name:"Gunshot"}, ], drummap:[ // 35 {name:"Acoustic Bass Drum"}, {name:"Bass Drum 1"}, {name:"Side Stick"}, {name:"Acoustic Snare"}, {name:"Hand Clap"}, {name:"Electric Snare"}, {name:"Low Floor Tom"}, {name:"Closed Hi Hat"}, {name:"High Floor Tom"}, {name:"Pedal Hi-Hat"}, {name:"Low Tom"}, {name:"Open Hi-Hat"}, {name:"Low-Mid Tom"}, {name:"Hi-Mid Tom"}, {name:"Crash Cymbal 1"}, {name:"High Tom"}, {name:"Ride Cymbal 1"}, {name:"Chinese Cymbal"}, {name:"Ride Bell"}, {name:"Tambourine"}, {name:"Splash Cymbal"}, {name:"Cowbell"}, {name:"Crash Cymbal 2"}, {name:"Vibraslap"}, {name:"Ride Cymbal 2"}, {name:"Hi Bongo"}, {name:"Low Bongo"}, {name:"Mute Hi Conga"}, {name:"Open Hi Conga"}, {name:"Low Conga"}, {name:"High Timbale"}, {name:"Low Timbale"}, {name:"High Agogo"}, {name:"Low Agogo"}, {name:"Cabasa"}, {name:"Maracas"}, {name:"Short Whistle"}, {name:"Long Whistle"}, {name:"Short Guiro"}, {name:"Long Guiro"}, {name:"Claves"}, {name:"Hi Wood Block"}, {name:"Low Wood Block"}, {name:"Mute Cuica"}, {name:"Open Cuica"}, {name:"Mute Triangle"}, {name:"Open Triangle"}, ], program1:[ // 1-8 : Piano [{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}], [{w:"triangle",v:0.4,d:0.7,r:0.1,},{w:"triangle",v:4,t:3,d:0.4,s:0.1,g:1,k:-1,a:0.01,}], [{w:"sine",d:0.7,r:0.1,},{w:"triangle",v:4,f:2,d:0.5,s:0.5,g:1,k:-1}], [{w:"sine",d:0.7,v:0.2,},{w:"triangle",v:4,t:3,f:2,d:0.3,g:1,k:-1,a:0.01,s:0.5,}], [{w:"sine",v:0.35,d:0.7,},{w:"sine",v:3,t:7,f:1,d:1,s:1,g:1,k:-.7}], [{w:"sine",v:0.35,d:0.7,},{w:"sine",v:8,t:7,f:1,d:0.5,s:1,g:1,k:-.7}], [{w:"sawtooth",v:0.34,d:2,},{w:"sine",v:8,f:0.1,d:2,s:1,r:2,g:1,}], [{w:"triangle",v:0.34,d:1.5,},{w:"square",v:6,f:0.1,d:1.5,s:0.5,r:2,g:1,}], /* 9-16 : Chromatic Perc*/ [{w:"sine",d:0.3,r:0.3,},{w:"sine",v:7,t:11,d:0.03,g:1,}], [{w:"sine",d:0.3,r:0.3,},{w:"sine",v:11,t:6,d:0.2,s:0.4,g:1,}], [{w:"sine",v:0.2,d:0.3,r:0.3,},{w:"sine",v:11,t:5,d:0.1,s:0.4,g:1,}], [{w:"sine",v:0.2,d:0.6,r:0.6,},{w:"triangle",v:11,t:5,f:1,s:0.5,g:1,}], [{w:"sine",v:0.3,d:0.2,r:0.2,},{w:"sine",v:6,t:5,d:0.02,g:1,}], [{w:"sine",v:0.3,d:0.2,r:0.2,},{w:"sine",v:7,t:11,d:0.03,g:1,}], [{w:"sine",v:0.2,d:1,r:1,},{w:"sine",v:11,t:3.5,d:1,r:1,g:1,}], [{w:"triangle",v:0.2,d:0.5,r:0.2,},{w:"sine",v:6,t:2.5,d:0.2,s:0.1,r:0.2,g:1,}], /* 17-24 : Organ */ [{w:"w9999",v:0.22,s:0.9,},{w:"w9999",v:0.22,t:2,f:2,s:0.9,}], [{w:"w9999",v:0.2,s:1,},{w:"sine",v:11,t:6,f:2,s:0.1,g:1,h:0.006,r:0.002,d:0.002,},{w:"w9999",v:0.2,t:2,f:1,h:0,s:1,}], [{w:"w9999",v:0.2,d:0.1,s:0.9,},{w:"w9999",v:0.25,t:4,f:2,s:0.5,}], [{w:"w9999",v:0.3,a:0.04,s:0.9,},{w:"w9999",v:0.2,t:8,f:2,a:0.04,s:0.9,}], [{w:"sine",v:0.2,a:0.02,d:0.05,s:1,},{w:"sine",v:6,t:3,f:1,a:0.02,d:0.05,s:1,g:1,}], [{w:"triangle",v:0.2,a:0.02,d:0.05,s:0.8,},{w:"square",v:7,t:3,f:1,d:0.05,s:1.5,g:1,}], [{w:"square",v:0.2,a:0.02,d:0.2,s:0.5,},{w:"square",v:1,d:0.03,s:2,g:1,}], [{w:"square",v:0.2,a:0.02,d:0.1,s:0.8,},{w:"square",v:1,a:0.3,d:0.1,s:2,g:1,}], /* 25-32 : Guitar */ [{w:"sine",v:0.3,d:0.5,f:1,},{w:"triangle",v:5,t:3,f:-1,d:1,s:0.1,g:1,}], [{w:"sine",v:0.4,d:0.6,f:1,},{w:"triangle",v:12,t:3,d:0.6,s:0.1,g:1,f:-1,}], [{w:"triangle",v:0.3,d:1,f:1,},{w:"triangle",v:6,f:-1,d:0.4,s:0.5,g:1,t:3,}], [{w:"sine",v:0.3,d:1,f:-1,},{w:"triangle",v:11,f:1,d:0.4,s:0.5,g:1,t:3,}], [{w:"sine",v:0.4,d:0.1,r:0.01},{w:"sine",v:7,g:1,}], [{w:"triangle",v:0.4,d:1,f:1,},{w:"square",v:4,f:-1,d:1,s:0.7,g:1,}],//[{w:"triangle",v:0.35,d:1,f:1,},{w:"square",v:7,f:-1,d:0.3,s:0.5,g:1,}], [{w:"triangle",v:0.35,d:1,f:1,},{w:"square",v:7,f:-1,d:0.3,s:0.5,g:1,}],//[{w:"triangle",v:0.4,d:1,f:1,},{w:"square",v:4,f:-1,d:1,s:0.7,g:1,}],//[{w:"triangle",v:0.4,d:1,},{w:"square",v:4,f:2,d:1,s:0.7,g:1,}], [{w:"sine",v:0.2,t:1.5,a:0.005,h:0.2,d:0.6,},{w:"sine",v:11,t:5,f:2,d:1,s:0.5,g:1,}], /* 33-40 : Bass */ [{w:"sine",d:0.3,},{w:"sine",v:4,t:3,d:1,s:1,g:1,}], [{w:"sine",d:0.3,},{w:"sine",v:4,t:3,d:1,s:1,g:1,}], [{w:"w9999",d:0.3,v:0.7,s:0.5,},{w:"sawtooth",v:1.2,d:0.02,s:0.5,g:1,h:0,r:0.02,}], [{w:"sine",d:0.3,},{w:"sine",v:4,t:3,d:1,s:1,g:1,}], [{w:"triangle",v:0.3,t:2,d:1,},{w:"triangle",v:15,t:2.5,d:0.04,s:0.1,g:1,}], [{w:"triangle",v:0.3,t:2,d:1,},{w:"triangle",v:15,t:2.5,d:0.04,s:0.1,g:1,}], [{w:"triangle",d:0.7,},{w:"square",v:0.4,t:0.5,f:1,d:0.2,s:10,g:1,}], [{w:"triangle",d:0.7,},{w:"square",v:0.4,t:0.5,f:1,d:0.2,s:10,g:1,}], /* 41-48 : Strings */ [{w:"sawtooth",v:0.4,a:0.1,d:11,},{w:"sine",v:5,d:11,s:0.2,g:1,}], [{w:"sawtooth",v:0.4,a:0.1,d:11,},{w:"sine",v:5,d:11,s:0.2,g:1,}], [{w:"sawtooth",v:0.4,a:0.1,d:11,},{w:"sine",v:5,t:0.5,d:11,s:0.2,g:1,}], [{w:"sawtooth",v:0.4,a:0.1,d:11,},{w:"sine",v:5,t:0.5,d:11,s:0.2,g:1,}], [{w:"sine",v:0.4,a:0.1,d:11,},{w:"sine",v:6,f:2.5,d:0.05,s:1.1,g:1,}], [{w:"sine",v:0.3,d:0.1,r:0.1,},{w:"square",v:4,t:3,d:1,s:0.2,g:1,}], [{w:"sine",v:0.3,d:0.5,r:0.5,},{w:"sine",v:7,t:2,f:2,d:1,r:1,g:1,}], [{w:"triangle",v:0.6,h:0.03,d:0.3,r:0.3,t:0.5,},{w:"n0",v:8,t:1.5,d:0.08,r:0.08,g:1,}], /* 49-56 : Ensamble */ [{w:"sawtooth",v:0.3,a:0.03,s:0.5,},{w:"sawtooth",v:0.2,t:2,f:2,d:1,s:2,}], [{w:"sawtooth",v:0.3,f:-2,a:0.03,s:0.5,},{w:"sawtooth",v:0.2,t:2,f:2,d:1,s:2,}], [{w:"sawtooth",v:0.2,a:0.02,s:1,},{w:"sawtooth",v:0.2,t:2,f:2,a:1,d:1,s:1,}], [{w:"sawtooth",v:0.2,a:0.02,s:1,},{w:"sawtooth",v:0.2,f:2,a:0.02,d:1,s:1,}], [{w:"triangle",v:0.3,a:0.03,s:1,},{w:"sine",v:3,t:5,f:1,d:1,s:1,g:1,}], [{w:"sine",v:0.4,a:0.03,s:0.9,},{w:"sine",v:1,t:2,f:3,d:0.03,s:0.2,g:1,}], [{w:"triangle",v:0.6,a:0.05,s:0.5,},{w:"sine",v:1,f:0.8,d:0.2,s:0.2,g:1,}], [{w:"square",v:0.15,a:0.01,d:0.2,r:0.2,t:0.5,h:0.03,},{w:"square",v:4,f:0.5,d:0.2,r:11,a:0.01,g:1,h:0.02,},{w:"square",v:0.15,t:4,f:1,a:0.02,d:0.15,r:0.15,h:0.03,},{g:3,w:"square",v:4,f:-0.5,a:0.01,h:0.02,d:0.15,r:11,}], /* 57-64 : Brass */ [{w:"square",v:0.2,a:0.01,d:1,s:0.6,r:0.04,},{w:"sine",v:1,d:0.1,s:4,g:1,}], [{w:"square",v:0.2,a:0.02,d:1,s:0.5,r:0.08,},{w:"sine",v:1,d:0.1,s:4,g:1,}], [{w:"square",v:0.2,a:0.04,d:1,s:0.4,r:0.08,},{w:"sine",v:1,d:0.1,s:4,g:1,}], [{w:"square",v:0.15,a:0.04,s:1,},{w:"sine",v:2,d:0.1,g:1,}], [{w:"square",v:0.2,a:0.02,d:1,s:0.5,r:0.08,},{w:"sine",v:1,d:0.1,s:4,g:1,}], [{w:"square",v:0.2,a:0.02,d:1,s:0.6,r:0.08,},{w:"sine",v:1,f:0.2,d:0.1,s:4,g:1,}], [{w:"square",v:0.2,a:0.02,d:0.5,s:0.7,r:0.08,},{w:"sine",v:1,d:0.1,s:4,g:1,}], [{w:"square",v:0.2,a:0.02,d:1,s:0.5,r:0.08,},{w:"sine",v:1,d:0.1,s:4,g:1,}], /* 65-72 : Reed */ [{w:"square",v:0.2,a:0.02,d:2,s:0.6,},{w:"sine",v:2,d:1,g:1,}], [{w:"square",v:0.2,a:0.02,d:2,s:0.6,},{w:"sine",v:2,d:1,g:1,}], [{w:"square",v:0.2,a:0.02,d:1,s:0.6,},{w:"sine",v:2,d:1,g:1,}], [{w:"square",v:0.2,a:0.02,d:1,s:0.6,},{w:"sine",v:2,d:1,g:1,}], [{w:"sine",v:0.4,a:0.02,d:0.7,s:0.5,},{w:"square",v:5,t:2,d:0.2,s:0.5,g:1,}], [{w:"sine",v:0.3,a:0.05,d:0.2,s:0.8,},{w:"sawtooth",v:6,f:0.1,d:0.1,s:0.3,g:1,}], [{w:"sine",v:0.3,a:0.03,d:0.2,s:0.4,},{w:"square",v:7,f:0.2,d:1,s:0.1,g:1,}], [{w:"square",v:0.2,a:0.05,d:0.1,s:0.8,},{w:"square",v:4,d:0.1,s:1.1,g:1,}], /* 73-80 : Pipe */ [{w:"sine",a:0.02,d:2,},{w:"sine",v:6,t:2,d:0.04,g:1,}], [{w:"sine",v:0.7,a:0.03,d:0.4,s:0.4,},{w:"sine",v:4,t:2,f:0.2,d:0.4,g:1,}], [{w:"sine",v:0.7,a:0.02,d:0.4,s:0.6,},{w:"sine",v:3,t:2,d:0,s:1,g:1,}], [{w:"sine",v:0.4,a:0.06,d:0.3,s:0.3,},{w:"sine",v:7,t:2,d:0.2,s:0.2,g:1,}], [{w:"sine",a:0.02,d:0.3,s:0.3,},{w:"sawtooth",v:3,t:2,d:0.3,g:1,}], [{w:"sine",v:0.4,a:0.02,d:2,s:0.1,},{w:"sawtooth",v:8,t:2,f:1,d:0.5,g:1,}], [{w:"sine",v:0.7,a:0.03,d:0.5,s:0.3,},{w:"sine",v:0.003,t:0,f:4,d:0.1,s:0.002,g:1,}], [{w:"sine",v:0.7,a:0.02,d:2,},{w:"sine",v:1,t:2,f:1,d:0.02,g:1,}], /* 81-88 : SynthLead */ [{w:"square",v:0.3,d:1,s:0.5,},{w:"square",v:1,f:0.2,d:1,s:0.5,g:1,}], [{w:"sawtooth",v:0.3,d:2,s:0.5,},{w:"square",v:2,f:0.1,s:0.5,g:1,}], [{w:"triangle",v:0.5,a:0.05,d:2,s:0.6,},{w:"sine",v:4,t:2,g:1,}], [{w:"triangle",v:0.3,a:0.01,d:2,s:0.3,},{w:"sine",v:22,t:2,f:1,d:0.03,s:0.2,g:1,}], [{w:"sawtooth",v:0.3,d:1,s:0.5,},{w:"sine",v:11,t:11,a:0.2,d:0.05,s:0.3,g:1,}], [{w:"sine",v:0.3,a:0.06,d:1,s:0.5,},{w:"sine",v:7,f:1,d:1,s:0.2,g:1,}], [{w:"sawtooth",v:0.3,a:0.03,d:0.7,s:0.3,r:0.2,},{w:"sawtooth",v:0.3,t:0.75,d:0.7,a:0.1,s:0.3,r:0.2,}], [{w:"triangle",v:0.3,a:0.01,d:0.7,s:0.5,},{w:"square",v:5,t:0.5,d:0.7,s:0.5,g:1,}], /* 89-96 : SynthPad */ [{w:"triangle",v:0.3,a:0.02,d:0.3,s:0.3,r:0.3,},{w:"square",v:3,t:4,f:1,a:0.02,d:0.1,s:1,g:1,},{w:"triangle",v:0.08,t:0.5,a:0.1,h:0,d:0.1,s:0.5,r:0.1,b:0,c:0,}], [{w:"sine",v:0.3,a:0.05,d:1,s:0.7,r:0.3,},{w:"sine",v:2,f:1,d:0.3,s:1,g:1,}], [{w:"square",v:0.3,a:0.03,d:0.5,s:0.3,r:0.1,},{w:"square",v:4,f:1,a:0.03,d:0.1,g:1,}], [{w:"triangle",v:0.3,a:0.08,d:1,s:0.3,r:0.1,},{w:"square",v:2,f:1,d:0.3,s:0.3,g:1,t:4,a:0.08,}], [{w:"sine",v:0.3,a:0.05,d:1,s:0.3,r:0.1,},{w:"sine",v:0.1,t:2.001,f:1,d:1,s:50,g:1,}], [{w:"triangle",v:0.3,a:0.03,d:0.7,s:0.3,r:0.2,},{w:"sine",v:12,t:7,f:1,d:0.5,s:1.7,g:1,}], [{w:"sine",v:0.3,a:0.05,d:1,s:0.3,r:0.1,},{w:"sawtooth",v:22,t:6,d:0.06,s:0.3,g:1,}], [{w:"triangle",v:0.3,a:0.05,d:11,r:0.3,},{w:"triangle",v:1,d:1,s:8,g:1,}], /* 97-104 : FX */ [{w:"sawtooth",v:0.3,d:4,s:0.8,r:0.1,},{w:"square",v:1,t:2,f:8,a:1,d:1,s:1,r:0.1,g:1,}], [{w:"triangle",v:0.3,d:1,s:0.5,t:0.8,a:0.2,p:1.25,q:0.2,},{w:"sawtooth",v:0.2,a:0.2,d:0.3,s:1,t:1.2,p:1.25,q:0.2,}], [{w:"sine",v:0.3,d:1,s:0.3,},{w:"square",v:22,t:11,d:0.5,s:0.1,g:1,}], [{w:"sawtooth",v:0.3,a:0.04,d:1,s:0.8,r:0.1,},{w:"square",v:1,t:0.5,d:1,s:2,g:1,}], [{w:"triangle",v:0.3,d:1,s:0.3,},{w:"sine",v:22,t:6,d:0.6,s:0.05,g:1,}], [{w:"sine",v:0.6,a:0.1,d:0.05,s:0.4,},{w:"sine",v:5,t:5,f:1,d:0.05,s:0.3,g:1,}], [{w:"sine",a:0.1,d:0.05,s:0.4,v:0.8,},{w:"sine",v:5,t:5,f:1,d:0.05,s:0.3,g:1,}], [{w:"square",v:0.3,a:0.1,d:0.1,s:0.4,},{w:"square",v:1,f:1,d:0.3,s:0.1,g:1,}], /* 105-112 : Ethnic */ [{w:"sawtooth",v:0.3,d:0.5,r:0.5,},{w:"sawtooth",v:11,t:5,d:0.05,g:1,}], [{w:"square",v:0.3,d:0.2,r:0.2,},{w:"square",v:7,t:3,d:0.05,g:1,}], [{w:"triangle",d:0.2,r:0.2,},{w:"square",v:9,t:3,d:0.1,r:0.1,g:1,}], [{w:"triangle",d:0.3,r:0.3,},{w:"square",v:6,t:3,d:1,r:1,g:1,}], [{w:"triangle",v:0.4,d:0.2,r:0.2,},{w:"square",v:22,t:12,d:0.1,r:0.1,g:1,}], [{w:"sine",v:0.25,a:0.02,d:0.05,s:0.8,},{w:"square",v:1,t:2,d:0.03,s:11,g:1,}], [{w:"sine",v:0.3,a:0.05,d:11,},{w:"square",v:7,t:3,f:1,s:0.7,g:1,}], [{w:"square",v:0.3,a:0.05,d:0.1,s:0.8,},{w:"square",v:4,d:0.1,s:1.1,g:1,}], /* 113-120 : Percussive */ [{w:"sine",v:0.4,d:0.3,r:0.3,},{w:"sine",v:7,t:9,d:0.1,r:0.1,g:1,}], [{w:"sine",v:0.7,d:0.1,r:0.1,},{w:"sine",v:22,t:7,d:0.05,g:1,}], [{w:"sine",v:0.6,d:0.15,r:0.15,},{w:"square",v:11,t:3.2,d:0.1,r:0.1,g:1,}], [{w:"sine",v:0.8,d:0.07,r:0.07,},{w:"square",v:11,t:7,r:0.01,g:1,}], [{w:"triangle",v:0.7,t:0.5,d:0.2,r:0.2,p:0.95,},{w:"n0",v:9,g:1,d:0.2,r:0.2,}], [{w:"sine",v:0.7,d:0.1,r:0.1,p:0.9,},{w:"square",v:14,t:2,d:0.005,r:0.005,g:1,}], [{w:"square",d:0.15,r:0.15,p:0.5,},{w:"square",v:4,t:5,d:0.001,r:0.001,g:1,}], [{w:"n1",v:0.3,a:1,s:1,d:0.15,r:0,t:0.5,}], /* 121-128 : SE */ [{w:"sine",t:12.5,d:0,r:0,p:0.5,v:0.3,h:0.2,q:0.5,},{g:1,w:"sine",v:1,t:2,d:0,r:0,s:1,},{g:1,w:"n0",v:0.2,t:2,a:0.6,h:0,d:0.1,r:0.1,b:0,c:0,}], [{w:"n0",v:0.2,a:0.05,h:0.02,d:0.02,r:0.02,}], [{w:"n0",v:0.4,a:1,d:1,t:0.25,}], [{w:"sine",v:0.3,a:0.1,d:1,s:0.5,},{w:"sine",v:4,t:0,f:1.5,d:1,s:1,r:0.1,g:1,},{g:1,w:"sine",v:4,t:0,f:2,a:0.6,h:0,d:0.1,s:1,r:0.1,b:0,c:0,}], [{w:"square",v:0.3,t:0.25,d:11,s:1,},{w:"square",v:12,t:0,f:8,d:1,s:1,r:11,g:1,}], [{w:"n0",v:0.4,t:0.5,a:1,d:11,s:1,r:0.5,},{w:"square",v:1,t:0,f:14,d:1,s:1,r:11,g:1,}], [{w:"sine",t:0,f:1221,a:0.2,d:1,r:0.25,s:1,},{g:1,w:"n0",v:3,t:0.5,d:1,s:1,r:1,}], [{w:"sine",d:0.4,r:0.4,p:0.1,t:2.5,v:1,},{w:"n0",v:12,t:2,d:1,r:1,g:1,}], ], program0:[ // 1-8 : Piano [{w:"triangle",v:.5,d:.7}], [{w:"triangle",v:.5,d:.7}], [{w:"triangle",v:.5,d:.7}], [{w:"triangle",v:.5,d:.7}], [{w:"triangle",v:.5,d:.7}], [{w:"triangle",v:.5,d:.7}], [{w:"sawtooth",v:.3,d:.7}], [{w:"sawtooth",v:.3,d:.7}], /* 9-16 : Chromatic Perc*/ [{w:"sine",v:.5,d:.3,r:.3}], [{w:"triangle",v:.5,d:.3,r:.3}], [{w:"square",v:.2,d:.3,r:.3}], [{w:"square",v:.2,d:.3,r:.3}], [{w:"sine",v:.5,d:.1,r:.1}], [{w:"sine",v:.5,d:.1,r:.1}], [{w:"square",v:.2,d:1,r:1}], [{w:"sawtooth",v:.3,d:.7,r:.7}], /* 17-24 : Organ */ [{w:"sine",v:0.5,a:0.01,s:1}], [{w:"sine",v:0.7,d:0.02,s:0.7}], [{w:"square",v:.2,s:1}], [{w:"triangle",v:.5,a:.01,s:1}], [{w:"square",v:.2,a:.02,s:1}], [{w:"square",v:0.2,a:0.02,s:1}], [{w:"square",v:0.2,a:0.02,s:1}], [{w:"square",v:.2,a:.05,s:1}], /* 25-32 : Guitar */ [{w:"triangle",v:.5,d:.5}], [{w:"square",v:.2,d:.6}], [{w:"square",v:.2,d:.6}], [{w:"triangle",v:.8,d:.6}], [{w:"triangle",v:.4,d:.05}], [{w:"square",v:.2,d:1}], [{w:"square",v:.2,d:1}], [{w:"sine",v:.4,d:.6}], /* 33-40 : Bass */ [{w:"triangle",v:.7,d:.4}], [{w:"triangle",v:.7,d:.7}], [{w:"triangle",v:.7,d:.7}], [{w:"triangle",v:.7,d:.7}], [{w:"square",v:.3,d:.2}], [{w:"square",v:.3,d:.2}], [{w:"square",v:.3,d:.1,s:.2}], [{w:"sawtooth",v:.4,d:.1,s:.2}], /* 41-48 : Strings */ [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.3,d:.1}], [{w:"sawtooth",v:.3,d:.5,r:.5}], [{w:"triangle",v:.6,d:.1,r:.1,h:0.03,p:0.8}], /* 49-56 : Ensamble */ [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"sawtooth",v:.2,a:.02,s:1}], [{w:"triangle",v:.3,a:.03,s:1}], [{w:"sine",v:.3,a:.03,s:1}], [{w:"triangle",v:.3,a:.05,s:1}], [{w:"sawtooth",v:.5,a:.01,d:.1}], /* 57-64 : Brass */ [{w:"square",v:.3,a:.05,d:.2,s:.6}], [{w:"square",v:.3,a:.05,d:.2,s:.6}], [{w:"square",v:.3,a:.05,d:.2,s:.6}], [{w:"square",v:0.2,a:.05,d:0.01,s:1}], [{w:"square",v:.3,a:.05,s:1}], [{w:"square",v:.3,s:.7}], [{w:"square",v:.3,s:.7}], [{w:"square",v:.3,s:.7}], /* 65-72 : Reed */ [{w:"square",v:.3,a:.02,d:2}], [{w:"square",v:.3,a:.02,d:2}], [{w:"square",v:.3,a:.03,d:2}], [{w:"square",v:.3,a:.04,d:2}], [{w:"square",v:.3,a:.02,d:2}], [{w:"square",v:.3,a:.05,d:2}], [{w:"square",v:.3,a:.03,d:2}], [{w:"square",v:.3,a:.03,d:2}], /* 73-80 : Pipe */ [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], [{w:"sine",v:.7,a:.02,d:2}], /* 81-88 : SynthLead */ [{w:"square",v:.3,s:.7}], [{w:"sawtooth",v:.4,s:.7}], [{w:"triangle",v:.5,s:.7}], [{w:"sawtooth",v:.4,s:.7}], [{w:"sawtooth",v:.4,d:12}], [{w:"sine",v:.4,a:.06,d:12}], [{w:"sawtooth",v:.4,d:12}], [{w:"sawtooth",v:.4,d:12}], /* 89-96 : SynthPad */ [{w:"sawtooth",v:.3,d:12}], [{w:"triangle",v:.5,d:12}], [{w:"square",v:.3,d:12}], [{w:"triangle",v:.5,a:.08,d:11}], [{w:"sawtooth",v:.5,a:.05,d:11}], [{w:"sawtooth",v:.5,d:11}], [{w:"triangle",v:.5,d:11}], [{w:"triangle",v:.5,d:11}], /* 97-104 : FX */ [{w:"triangle",v:.5,d:11}], [{w:"triangle",v:.5,d:11}], [{w:"square",v:.3,d:11}], [{w:"sawtooth",v:0.5,a:0.04,d:11}], [{w:"sawtooth",v:.5,d:11}], [{w:"triangle",v:.5,a:.8,d:11}], [{w:"triangle",v:.5,d:11}], [{w:"square",v:.3,d:11}], /* 105-112 : Ethnic */ [{w:"sawtooth",v:.3,d:1,r:1}], [{w:"sawtooth",v:.5,d:.3}], [{w:"sawtooth",v:.5,d:.3,r:.3}], [{w:"sawtooth",v:.5,d:.3,r:.3}], [{w:"square",v:.3,d:.2,r:.2}], [{w:"square",v:.3,a:.02,d:2}], [{w:"sawtooth",v:.2,a:.02,d:.7}], [{w:"triangle",v:.5,d:1}], /* 113-120 : Percussive */ [{w:"sawtooth",v:.3,d:.3,r:.3}], [{w:"sine",v:.8,d:.1,r:.1}], [{w:"square",v:.2,d:.1,r:.1,p:1.05}], [{w:"sine",v:.8,d:.05,r:.05}], [{w:"triangle",v:0.5,d:0.1,r:0.1,p:0.96}], [{w:"triangle",v:0.5,d:0.1,r:0.1,p:0.97}], [{w:"square",v:.3,d:.1,r:.1,}], [{w:"n1",v:0.3,a:1,s:1,d:0.15,r:0,t:0.5,}], /* 121-128 : SE */ [{w:"triangle",v:0.5,d:0.03,t:0,f:1332,r:0.001,p:1.1}], [{w:"n0",v:0.2,t:0.1,d:0.02,a:0.05,h:0.02,r:0.02}], [{w:"n0",v:0.4,a:1,d:1,t:0.25,}], [{w:"sine",v:0.3,a:0.8,d:1,t:0,f:1832}], [{w:"triangle",d:0.5,t:0,f:444,s:1,}], [{w:"n0",v:0.4,d:1,t:0,f:22,s:1,}], [{w:"n0",v:0.5,a:0.2,d:11,t:0,f:44}], [{w:"n0",v:0.5,t:0.25,d:0.4,r:0.4}], ], drummap1:[ /*35*/ [{w:"triangle",t:0,f:70,v:1,d:0.05,h:0.03,p:0.9,q:0.1,},{w:"n0",g:1,t:6,v:17,r:0.01,h:0,p:0,}], [{w:"triangle",t:0,f:88,v:1,d:0.05,h:0.03,p:0.5,q:0.1,},{w:"n0",g:1,t:5,v:42,r:0.01,h:0,p:0,}], [{w:"n0",f:222,p:0,t:0,r:0.01,h:0,}], [{w:"triangle",v:0.3,f:180,d:0.05,t:0,h:0.03,p:0.9,q:0.1,},{w:"n0",v:0.6,t:0,f:70,h:0.02,r:0.01,p:0,},{g:1,w:"square",v:2,t:0,f:360,r:0.01,b:0,c:0,}], [{w:"square",f:1150,v:0.34,t:0,r:0.03,h:0.025,d:0.03,},{g:1,w:"n0",t:0,f:13,h:0.025,d:0.1,s:1,r:0.1,v:1,}], /*40*/ [{w:"triangle",f:200,v:1,d:0.06,t:0,r:0.06,},{w:"n0",g:1,t:0,f:400,v:12,r:0.02,d:0.02,}], [{w:"triangle",f:100,v:0.9,d:0.12,h:0.02,p:0.5,t:0,r:0.12,},{g:1,w:"n0",v:5,t:0.4,h:0.015,d:0.005,r:0.005,}], [{w:"n1",f:390,v:0.25,r:0.01,t:0,}], [{w:"triangle",f:120,v:0.9,d:0.12,h:0.02,p:0.5,t:0,r:0.12,},{g:1,w:"n0",v:5,t:0.5,h:0.015,d:0.005,r:0.005,}], [{w:"n1",v:0.25,f:390,r:0.03,t:0,h:0.005,d:0.03,}], /*45*/ [{w:"triangle",f:140,v:0.9,d:0.12,h:0.02,p:0.5,t:0,r:0.12,},{g:1,w:"n0",v:5,t:0.3,h:0.015,d:0.005,r:0.005,}], [{w:"n1",v:0.25,f:390,t:0,d:0.2,r:0.2,},{w:"n0",v:0.3,t:0,c:0,f:440,h:0.005,d:0.05,}], [{w:"triangle",f:155,v:0.9,d:0.12,h:0.02,p:0.5,t:0,r:0.12,},{g:1,w:"n0",v:5,t:0.3,h:0.015,d:0.005,r:0.005,}], [{w:"triangle",f:180,v:0.9,d:0.12,h:0.02,p:0.5,t:0,r:0.12,},{g:1,w:"n0",v:5,t:0.3,h:0.015,d:0.005,r:0.005,}], [{w:"n1",v:0.3,f:1200,d:0.2,r:0.2,h:0.05,t:0,},{w:"n1",t:0,v:1,d:0.1,r:0.1,p:1.2,f:440,}], /*50*/ [{w:"triangle",f:220,v:0.9,d:0.12,h:0.02,p:0.5,t:0,r:0.12,},{g:1,w:"n0",v:5,t:0.3,h:0.015,d:0.005,r:0.005,}], [{w:"n1",f:500,v:0.15,d:0.4,r:0.4,h:0,t:0,},{w:"n0",v:0.1,t:0,r:0.01,f:440,}], [{w:"n1",v:0.3,f:800,d:0.2,r:0.2,h:0.05,t:0,},{w:"square",t:0,v:1,d:0.1,r:0.1,p:0.1,f:220,g:1,}], [{w:"sine",f:1651,v:0.15,d:0.2,r:0.2,h:0,t:0,},{w:"sawtooth",g:1,t:1.21,v:7.2,d:0.1,r:11,h:1,},{g:1,w:"n0",v:3.1,t:0.152,d:0.002,r:0.002,}], null, /*55*/ [{w:"n1",v:.3,f:1200,d:0.2,r:0.2,h:0.05,t:0,},{w:"n1",t:0,v:1,d:0.1,r:0.1,p:1.2,f:440,}], null, [{w:"n1",v:0.3,f:555,d:0.25,r:0.25,h:0.05,t:0,},{w:"n1",t:0,v:1,d:0.1,r:0.1,f:440,a:0.005,h:0.02,}], [{w:"sawtooth",f:776,v:0.2,d:0.3,t:0,r:0.3,},{g:1,w:"n0",v:2,t:0,f:776,a:0.005,h:0.02,d:0.1,s:1,r:0.1,c:0,},{g:11,w:"sine",v:0.1,t:0,f:22,d:0.3,r:0.3,b:0,c:0,}], [{w:"n1",f:440,v:0.15,d:0.4,r:0.4,h:0,t:0,},{w:"n0",v:0.4,t:0,r:0.01,f:440,}], /*60*/ null,null,null,null,null, /*65*/ null,null,null,null,null, /*70*/ null,null,null,null,null, /*75*/ null,null,null,null,null, /*80*/ [{w:"sine",f:1720,v:0.3,d:0.02,t:0,r:0.02,},{w:"square",g:1,t:0,f:2876,v:6,d:0.2,s:1,r:0.2,}], [{w:"sine",f:1720,v:0.3,d:0.25,t:0,r:0.25,},{w:"square",g:1,t:0,f:2876,v:6,d:0.2,s:1,r:0.2,}], ], drummap0:[ /*35*/[{w:"triangle",t:0,f:110,v:1,d:0.05,h:0.02,p:0.1,}], [{w:"triangle",t:0,f:150,v:0.8,d:0.1,p:0.1,h:0.02,r:0.01,}], [{w:"n0",f:392,v:0.5,d:0.01,p:0,t:0,r:0.05}], [{w:"n0",f:33,d:0.05,t:0,}], [{w:"n0",f:100,v:0.7,d:0.03,t:0,r:0.03,h:0.02,}], /*40*/[{w:"n0",f:44,v:0.7,d:0.02,p:0.1,t:0,h:0.02,}], [{w:"triangle",f:240,v:0.9,d:0.1,h:0.02,p:0.1,t:0,}], [{w:"n0",f:440,v:0.2,r:0.01,t:0,}], [{w:"triangle",f:270,v:0.9,d:0.1,h:0.02,p:0.1,t:0,}], [{w:"n0",f:440,v:0.2,d:0.04,r:0.04,t:0,}], /*45*/[{w:"triangle",f:300,v:0.9,d:0.1,h:0.02,p:0.1,t:0,}], [{w:"n0",f:440,v:0.2,d:0.1,r:0.1,h:0.02,t:0,}], [{w:"triangle",f:320,v:0.9,d:0.1,h:0.02,p:0.1,t:0,}], [{w:"triangle",f:360,v:0.9,d:0.1,h:0.02,p:0.1,t:0,}], [{w:"n0",f:150,v:0.2,d:0.1,r:0.1,h:0.05,t:0,p:0.1,}], /*50*/[{w:"triangle",f:400,v:0.9,d:0.1,h:0.02,p:0.1,t:0,}], [{w:"n0",f:150,v:0.2,d:0.1,r:0.01,h:0.05,t:0,p:0.1}], [{w:"n0",f:150,v:0.2,d:0.1,r:0.01,h:0.05,t:0,p:0.1}], [{w:"n0",f:440,v:0.3,d:0.1,p:0.9,t:0,r:0.1,}], [{w:"n0",f:200,v:0.2,d:0.05,p:0.9,t:0,}], /*55*/[{w:"n0",f:440,v:0.3,d:0.12,p:0.9,t:0,}], [{w:"sine",f:800,v:0.4,d:0.06,t:0,}], [{w:"n0",f:150,v:0.2,d:0.1,r:0.01,h:0.05,t:0,p:0.1}], [{w:"n0",f:33,v:0.3,d:0.2,p:0.9,t:0,}], [{w:"n0",f:300,v:0.3,d:0.14,p:0.9,t:0,}], /*60*/[{w:"sine",f:200,d:0.06,t:0,}], [{w:"sine",f:150,d:0.06,t:0,}], [{w:"sine",f:300,t:0,}], [{w:"sine",f:300,d:0.06,t:0,}], [{w:"sine",f:250,d:0.06,t:0,}], /*65*/[{w:"square",f:300,v:.3,d:.06,p:.8,t:0,}], [{w:"square",f:260,v:.3,d:.06,p:.8,t:0,}], [{w:"sine",f:850,v:.5,d:.07,t:0,}], [{w:"sine",f:790,v:.5,d:.07,t:0,}], [{w:"n0",f:440,v:0.3,a:0.05,t:0,}], /*70*/[{w:"n0",f:440,v:0.3,a:0.05,t:0,}], [{w:"triangle",f:1800,v:0.4,p:0.9,t:0,h:0.03,}], [{w:"triangle",f:1800,v:0.3,p:0.9,t:0,h:0.13,}], [{w:"n0",f:330,v:0.3,a:0.02,t:0,r:0.01,}], [{w:"n0",f:330,v:0.3,a:0.02,t:0,h:0.04,r:0.01,}], /*75*/[{w:"n0",f:440,v:0.3,t:0,}], [{w:"sine",f:800,t:0,}], [{w:"sine",f:700,t:0,}], [{w:"n0",f:330,v:0.3,t:0,}], [{w:"n0",f:330,v:0.3,t:0,h:0.1,r:0.01,p:0.7,}], /*80*/[{w:"sine",t:0,f:1200,v:0.3,r:0.01,}], [{w:"sine",t:0,f:1200,v:0.3,d:0.2,r:0.2,}], ], /*@@gui*/ _guiInit:()=>{ if(this.canvas){ this.ctx=this.canvas.getContext("2d"); this.ctx.fillStyle="#000"; this.ctx.fillRect(0,0,300,32); this.canvas.addEventListener("dragover",this.dragOver.bind(this),false); this.canvas.addEventListener("dragleave",this.dragLeave.bind(this),false); this.canvas.addEventListener("drop",this.execDrop.bind(this),false); this.canvas.addEventListener("click",this.click.bind(this),false); this.canvas.addEventListener("mousedown",this.pointerdown.bind(this),false); this.canvas.addEventListener("mousemove",this.pointermove.bind(this),false); this.canvas.addEventListener("touchstart",this.pointerdown.bind(this),false); this.canvas.addEventListener("touchend",this.pointerup.bind(this),false); this.canvas.addEventListener("touchcancel",this.pointerup.bind(this),false); this.canvas.addEventListener("touchmove",this.pointermove.bind(this),false); } }, _guiUpdate:()=>{ if(this.canvas){ this.ctx.fillStyle="#000"; this.ctx.fillRect(0,0,300,32); var row1=8,row2=20; if(this.song) row1=4,row2=24; else { this.ctx.fillStyle="#fff"; this.ctx.fillText("TinySynth",8,20); } if(this.graph){ this.ctx.fillStyle="#800"; this.ctx.fillRect(80,row1,132,4); this.ctx.fillRect(80,row2,132,4); this.ctx.fillStyle="#f00"; for(let i=this.notetab.length-1;i>=0;--i){ const nt=this.notetab[i]; if(!nt.f || this.rhythm[nt.ch]){ this.ctx.fillRect(80+nt.n,row1,4,4); this.ctx.fillRect(80+nt.ch*8,row2,6,4); } } } if(this.perfmon){ this.ctx.fillStyle="#fff"; this.ctx.fillRect(180,30,28,-12); this.ctx.fillStyle="#000"; this.ctx.fillText(this.notetab.length,185,28); } this.ctx.fillStyle="#fff"; this.ctx.fillRect(250,15,32,2); this.ctx.fillStyle="#fff"; this.ctx.strokeStyle="#000"; this.ctx.beginPath(); this.ctx.arc(250+this.masterVol*32,16,6,0,6.28,0); this.ctx.moveTo(220,12); this.ctx.lineTo(224,12); this.ctx.lineTo(230,6); this.ctx.lineTo(230,26); this.ctx.lineTo(224,20); this.ctx.lineTo(220,20); this.ctx.fill(); this.ctx.stroke(); this.ctx.strokeStyle="#fff"; this.ctx.lineWidth=2; this.ctx.beginPath(); this.ctx.arc(230,16,4,-1,1,false); this.ctx.stroke(); this.ctx.beginPath(); this.ctx.arc(230,16,8,-1,1,false); this.ctx.stroke(); if(this.masterVol==0){ this.ctx.strokeStyle="#000"; this.ctx.lineWidth=4; this.ctx.beginPath(); this.ctx.moveTo(220,7); this.ctx.lineTo(238,25); this.ctx.stroke(); this.ctx.strokeStyle="#fff"; this.ctx.lineWidth=2; this.ctx.stroke(); } if(this.song){ this.ctx.fillStyle="#fff"; this.ctx.fillRect(4,2,28,28); this.ctx.fillRect(80,15,128,2); this.ctx.fillStyle="#000"; if(this.playing){ this.ctx.fillRect(12,10,4,12); this.ctx.fillRect(22,10,4,12); } else{ this.ctx.beginPath(); this.ctx.moveTo(12,9); this.ctx.lineTo(25,16); this.ctx.lineTo(12,23); this.ctx.fill(); } this.ctx.fillStyle="#fff" this.ctx.fillText(this.toTime(this.playTick),38,14); this.ctx.fillText(this.toTime(this.maxTick),38,28); this.ctx.strokeStyle="#000"; this.ctx.beginPath(); this.ctx.arc(80+this.playTick/this.maxTick*128,16,6,0,6.28,0); this.ctx.fill(); this.ctx.stroke(); } if(this.waitdrop){ this.ctx.fillStyle="rgba(0,0,0,0.7)" this.ctx.fillRect(0,0,300,32); this.ctx.fillStyle="#fff"; this.ctx.fillText("Drop MIDI File Here",100,20); } } }, toTime:(ti)=>{ ti=(ti*4*60/this.song.timebase/this.song.tempo)|0; const m=(ti/60)|0; const s=ti%60; return ("00"+m).substr(-2)+":"+("00"+s).substr(-2); }, preventScroll:(e)=>{ e.preventDefault(); }, pointerup:(ev)=>{ document.body.removeEventListener('touchstart',this.preventScroll,false); }, getPos:(e)=>{ var p=e.target.getBoundingClientRect(); if(p.right!=p.left) return {x:(e.clientX-p.left)*300/(p.right-p.left),y:e.clientY-p.top}; return {x:0,y:0}; }, pointerdown:(ev)=>{ let e=ev; if(ev.touches) e=ev.touches[0]; this.downpos=this.getPos(e); if(ev.touches || (e.buttons&1)){ if(this.song&&this.downpos.x>=80&&this.downpos.x<=208){ const p=(this.downpos.x-80)/128*this.maxTick; this.locateMIDI(p); document.body.addEventListener('touchstart',this.preventScroll,false); } if(this.downpos.x>=250&&this.downpos.x<282){ const p=(this.downpos.x-250)/32; this.setMasterVol(p); document.body.addEventListener('touchstart',this.preventScroll,false); } } }, pointermove:(ev)=>{ let e=ev; if(ev.touches) e=ev.touches[0]; if(ev.touches || (e.buttons&1)){ const pos=this.getPos(e); if(this.song&&pos.x>=70&&pos.x<=208){ if(pos.x<80) pos.x=80; const p=(pos.x-80)/128*this.maxTick; this.locateMIDI(p); } if(pos.x>=250&&pos.x<282){ const p=(pos.x-250)/32; this.setMasterVol(p); } } }, click:(e)=>{ const pos=this.getPos(e); if(pos.x<40 && this.song){ if(this.playing) this.stopMIDI(); else if(this.song) this.playMIDI(); } if(pos.x>=215&&pos.x<243 && this.downpos.x>=215 && this.downpos.x<243){ if(this.masterVol>0){ this.lastMasterVol=this.masterVol; this.masterVol=0; } else this.masterVol=this.lastMasterVol; } }, dragLeave:(e)=>{ this.waitdrop=0; }, dragOver:(e)=>{ this.waitdrop=1; e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = "copy"; }, execDrop:(e)=>{ this.waitdrop=0; const f = e.dataTransfer.files; if(this.disabledrop==0){ var reader = new FileReader(); reader.onload=function(e){ this.loadMIDI(reader.result); }.bind(this); reader.readAsArrayBuffer(f[0]); } e.stopPropagation(); e.preventDefault(); }, /*@@guiEND*/ ready:()=>{ return new Promise((resolv)=>{ const timerid=setInterval(()=>{ /* if(this.debug) console.log("Initialize checking."); */ if(this.isReady){ clearInterval(timerid); if(this.debug) console.log("Initialized."); resolv(); } },100); }); }, init:()=>{ this.pg=[]; this.vol=[]; this.ex=[]; this.bend=[]; this.rpnidx=[]; this.brange=[]; this.sustain=[]; this.notetab=[]; this.rhythm=[]; this.masterTuningC=0; this.masterTuningF=0; this.tuningC=[]; this.tuningF=[]; this.scaleTuning=[]; this.maxTick=0, this.playTick=0, this.playing=0; this.releaseRatio=3.5; for(let i=0;i<16;++i){ this.pg[i]=0; this.vol[i]=3*100*100/(127*127); this.bend[i]=0; this.brange[i]=0x100; this.tuningC[i]=0; this.tuningF[i]=0; this.scaleTuning[i]=[0,0,0,0,0,0,0,0,0,0,0,0]; this.rhythm[i]=0; } this.rhythm[9]=1; this.preroll=0.2; this.relcnt=0; setInterval( function(){ if(++this.relcnt>=3){ this.relcnt=0; for(let i=this.notetab.length-1;i>=0;--i){ var nt=this.notetab[i]; if(this.actx.currentTime>nt.e){ this._pruneNote(nt); this.notetab.splice(i,1); } } /*@@gui*/ /*@@guiEND*/ } if(this.playing && this.song.ev.length>0){ let e=this.song.ev[this.playIndex]; while(this.actx.currentTime+this.preroll>this.playTime){ if(e.m[0]==0xff51){ this.song.tempo=e.m[1]; this.tick2Time=4*60/this.song.tempo/this.song.timebase; } else this.send(e.m,this.playTime); ++this.playIndex; if(this.playIndex>=this.song.ev.length){ if(this.loop){ e=this.song.ev[this.playIndex=0]; this.playTick=e.t; } else{ this.playTick=this.maxTick; this.playing=0; break; } } else{ e=this.song.ev[this.playIndex]; this.playTime+=(e.t-this.playTick)*this.tick2Time; this.playTick=e.t; } } } }.bind(this),60 ); if(this.debug) console.log("internalcontext:"+this.internalcontext) if(this.internalcontext){ window.AudioContext = window.AudioContext || window.webkitAudioContext; this.setAudioContext(new AudioContext()); } this.isReady=1; }, setMasterVol:(v)=>{ if(v!=undefined) this.masterVol=v; if(this.out) this.out.gain.value=this.masterVol; }, setReverbLev:(v)=>{ if(v!=undefined) this.reverbLev=v; var r=parseFloat(this.reverbLev); if(this.rev&&!isNaN(r)) this.rev.gain.value=r*8; }, setLoop:(f)=>{ this.loop=f; }, setVoices:(v)=>{ this.voices=v; }, getPlayStatus:()=>{ return {play:this.playing, maxTick:this.maxTick, curTick:this.playTick}; }, locateMIDI:(tick)=>{ let i,p=this.playing; this.stopMIDI(); for(i=0;ithis.song.ev[i].t;++i){ var m=this.song.ev[i]; var ch=m.m[0]&0xf; switch(m.m[0]&0xf0){ case 0xb0: switch(m.m[1]){ case 1: this.setModulation(ch,m.m[2]); break; case 7: this.setChVol(ch,m.m[2]); break; case 10: this.setPan(ch,m.m[2]); break; case 11: this.setExpression(ch,m.m[2]); break; case 64: this.setSustain(ch,m.m[2]); break; } break; case 0xc0: this.pg[m.m[0]&0x0f]=m.m[1]; break; } if(m.m[0]==0xff51) this.song.tempo=m.m[1]; } if(!this.song.ev[i]){ this.playIndex=0; this.playTick=this.maxTick; } else{ this.playIndex=i; this.playTick=this.song.ev[i].t; } if(p) this.playMIDI(); }, getTimbreName:(m,n)=>{ if(m==0) return this.program[n].name; else return this.drummap[n-35].name; }, loadMIDIfromSrc:()=>{ this.loadMIDIUrl(this.src); }, loadMIDIUrl:(url)=>{ if(!url) return; var xhr=new XMLHttpRequest(); xhr.open("GET",url,true); xhr.responseType="arraybuffer"; xhr.loadMIDI=this.loadMIDI.bind(this); xhr.onload=function(e){ if(this.status==200){ this.loadMIDI(this.response); } }; xhr.send(); }, reset:()=>{ for(let i=0;i<16;++i){ this.setProgram(i,0); this.setBendRange(i,0x100); this.setModulation(i,0); this.setChVol(i,100); this.setPan(i,64); this.resetAllControllers(i); this.allSoundOff(i); this.rhythm[i]=0; this.tuningC[i]=0; this.tuningF[i]=0; } this.masterTuningC=0; this.masterTuningF=0; this.rhythm[9]=1; }, stopMIDI:()=>{ this.playing=0; for(var i=0;i<16;++i) this.allSoundOff(i); }, playMIDI:()=>{ if(!this.song) return; const dummy=this.actx.createOscillator(); dummy.connect(this.actx.destination); dummy.frequency.value=0; dummy.start(0); dummy.stop(this.actx.currentTime+0.001); if(this.playTick>=this.maxTick) this.playTick=0,this.playIndex=0; this.playTime=this.actx.currentTime+.1; this.tick2Time=4*60/this.song.tempo/this.song.timebase; this.playing=1; }, loadMIDI:(data)=>{ function Get2(s, i) { return (s[i]<<8) + s[i+1]; } function Get3(s, i) { return (s[i]<<16) + (s[i+1]<<8) + s[i+2]; } function Get4(s, i) { return (s[i]<<24) + (s[i+1]<<16) + (s[i+2]<<8) + s[i+3]; } function GetStr(s, i, len) { return String.fromCharCode.apply(null,s.slice(i,i+len)); } function Delta(s, i) { var v, d; v = 0; datalen = 1; while((d = s[i]) & 0x80) { v = (v<<7) + (d&0x7f); ++datalen; ++i; } return (v<<7)+d; } function Msg(song,tick,s,i){ var v=s[i]; datalen=1; if((v&0x80)==0) v=runst,datalen=0; runst=v; switch(v&0xf0){ case 0xc0: case 0xd0: song.ev.push({t:tick,m:[v,s[i+datalen]]}); datalen+=1; break; case 0xf0: switch(v) { case 0xf0: case 0xf7: var len=Delta(s,i+1); datastart=1+datalen; var exd=Array.from(s.slice(i+datastart,i+datastart+len)); exd.unshift(0xf0); song.ev.push({t:tick,m:exd}); /* var sysex=[]; for(var jj=0;jjthis.maxTick) this.maxTick=tick; } idx += (len+8); } this.song.ev.sort(function(x,y){return x.t-y.t}); this.reset(); this.locateMIDI(0); }, setQuality:(q)=>{ if(q!=undefined) this.quality=q; for(let i=0;i<128;++i) this.setTimbre(0,i,this.program0[i]); for(let i=0;i{ const defp={g:0,w:"sine",t:1,f:0,v:0.5,a:0,h:0.01,d:0.01,s:0,r:0.05,p:1,q:1,k:0}; function filldef(p){ for(n=0;n=35 && n<=81) this.drummap[n-35].p=filldef(p); if(m==0 && n>=0 && n<=127) this.program[n].p=filldef(p); }, _pruneNote:(nt)=>{ for(let k=nt.o.length-1;k>=0;--k){ if(nt.o[k].frequency){ nt.o[k].frequency.cancelScheduledValues(0); } else{ nt.o[k].playbackRate.cancelScheduledValues(0); } nt.g[k].gain.cancelScheduledValues(0); nt.o[k].stop(); if(nt.o[k].detune) { try { this.chmod[nt.ch].disconnect(nt.o[k].detune); } catch (e) {} } nt.g[k].gain.value = 0; } }, _limitVoices:(ch,n)=>{ this.notetab.sort(function(n1,n2){ if(n1.f!=n2.f) return n1.f-n2.f; if(n1.e!=n2.e) return n2.e-n1.e; return n2.t-n1.t; }); for(let i=this.notetab.length-1;i>=0;--i){ var nt=this.notetab[i]; if(this.actx.currentTime>nt.e || i>=(this.voices-1)){ this._pruneNote(nt); this.notetab.splice(i,1); } } }, _note:(t,ch,n,v,p)=>{ let out,sc,pn; const o=[],g=[],vp=[],fp=[],r=[]; const f=440*Math.pow(2,(n-69 + this.masterTuningC + this.tuningC[ch] + (this.masterTuningF + this.tuningF[ch]/8192 + this.scaleTuning[ch][n%12]))/12); this._limitVoices(ch,n); for(let i=0;i10) out=g[pn.g-11].gain, sc=1, fp[i]=fp[pn.g-11]*pn.t+pn.f; else if(o[pn.g-1].frequency) out=o[pn.g-1].frequency, sc=fp[pn.g-1], fp[i]=fp[pn.g-1]*pn.t+pn.f; else out=o[pn.g-1].playbackRate, sc=fp[pn.g-1]/440, fp[i]=fp[pn.g-1]*pn.t+pn.f; switch(pn.w[0]){ case "n": o[i]=this.actx.createBufferSource(); o[i].buffer=this.noiseBuf[pn.w]; o[i].loop=true; o[i].playbackRate.value=fp[i]/440; if(pn.p!=1) this._setParamTarget(o[i].playbackRate,fp[i]/440*pn.p,t,pn.q); if (o[i].detune) { this.chmod[ch].connect(o[i].detune); o[i].detune.value=this.bend[ch]; } break; default: o[i]=this.actx.createOscillator(); o[i].frequency.value=fp[i]; if(pn.p!=1) this._setParamTarget(o[i].frequency,fp[i]*pn.p,t,pn.q); if(pn.w[0]=="w") o[i].setPeriodicWave(this.wave[pn.w]); else o[i].type=pn.w; if (o[i].detune) { this.chmod[ch].connect(o[i].detune); o[i].detune.value=this.bend[ch]; } break; } g[i]=this.actx.createGain(); r[i]=pn.r; o[i].connect(g[i]); g[i].connect(out); vp[i]=sc*pn.v; if(pn.k) vp[i]*=Math.pow(2,(n-60)/12*pn.k); if(pn.a){ g[i].gain.value=0; g[i].gain.setValueAtTime(0,t); g[i].gain.linearRampToValueAtTime(vp[i],t+pn.a); } else g[i].gain.setValueAtTime(vp[i],t); this._setParamTarget(g[i].gain,pn.s*vp[i],dt,pn.d); o[i].start(t); if(this.rhythm[ch]){ o[i].onended = ()=>{ try { if (o[i].detune) this.chmod[ch].disconnect(o[i].detune); } catch(e){} }; o[i].stop(t+p[0].d*this.releaseRatio); } } if(!this.rhythm[ch]) this.notetab.push({t:t,e:99999,ch:ch,n:n,o:o,g:g,t2:t+pn.a,v:vp,r:r,f:0}); }, _setParamTarget:(p,v,t,d)=>{ if(d!=0) p.setTargetAtTime(v,t,d); else p.setValueAtTime(v,t); }, _releaseNote:(nt,t)=>{ if(nt.ch!=9){ for(let k=nt.g.length-1;k>=0;--k){ nt.g[k].gain.cancelScheduledValues(t); if(t==nt.t2) nt.g[k].gain.setValueAtTime(nt.v[k],t); else if(t{ this.chmod[ch].gain.setValueAtTime(v*100/127,this._tsConv(t)); }, setChVol:(ch,v,t)=>{ this.vol[ch]=3*v*v/(127*127); this.chvol[ch].gain.setValueAtTime(this.vol[ch]*this.ex[ch],this._tsConv(t)); }, setPan:(ch,v,t)=>{ if(this.chpan[ch]) this.chpan[ch].pan.setValueAtTime((v-64)/64,this._tsConv(t)); }, setExpression:(ch,v,t)=>{ this.ex[ch]=v*v/(127*127); this.chvol[ch].gain.setValueAtTime(this.vol[ch]*this.ex[ch],this._tsConv(t)); }, setSustain:(ch,v,t)=>{ this.sustain[ch]=v; t=this._tsConv(t); if(v<64){ for(let i=this.notetab.length-1;i>=0;--i){ const nt=this.notetab[i]; if(t>=nt.t && nt.ch==ch && nt.f==1) this._releaseNote(nt,t); } } }, allSoundOff:(ch)=>{ for(let i=this.notetab.length-1;i>=0;--i){ const nt=this.notetab[i]; if(nt.ch==ch){ this._pruneNote(nt); this.notetab.splice(i,1); } } }, resetAllControllers:(ch)=>{ this.bend[ch]=0; this.ex[ch]=1.0; this.rpnidx[ch]=0x3fff; this.sustain[ch]=0; if(this.chvol[ch]){ this.chvol[ch].gain.value=this.vol[ch]*this.ex[ch]; this.chmod[ch].gain.value=0; } }, setBendRange:(ch,v)=>{ this.brange[ch]=v; }, setProgram:(ch,v)=>{ if(this.debug) console.log("Pg("+ch+")="+v); this.pg[ch]=v; }, _tsConv:(t)=>{ if(t==undefined||t<=0){ t=0; if(this.actx) t=this.actx.currentTime; } else{ if(this.tsmode) t=t*.001-this.tsdiff; } return t; }, setBend:(ch,v,t)=>{ t=this._tsConv(t); const br=this.brange[ch]*100/127; this.bend[ch]=(v-8192)*br/8192; for(let i=this.notetab.length-1;i>=0;--i){ const nt=this.notetab[i]; if(nt.ch==ch){ for(let k=nt.o.length-1;k>=0;--k){ if(nt.o[k].frequency) if (nt.o[k].detune) nt.o[k].detune.setValueAtTime(this.bend[ch],t); } } } }, noteOff:(ch,n,t)=>{ if(this.rhythm[ch]) return; t=this._tsConv(t); for(let i=this.notetab.length-1;i>=0;--i){ const nt=this.notetab[i]; if(t>=nt.t && nt.ch==ch && nt.n==n && nt.f==0){ nt.f=1; if(this.sustain[ch]<64) this._releaseNote(nt,t); } } }, noteOn:(ch,n,v,t)=>{ if(v==0){ this.noteOff(ch,n,t); return; } t=this._tsConv(t); if(this.rhythm[ch]){ if(n>=35&&n<=81) this._note(t,ch,n,v,this.drummap[n-35].p); return; } this._note(t,ch,n,v,this.program[this.pg[ch]].p); }, setTsMode:(tsmode)=>{ this.tsmode=tsmode; }, send:(msg,t)=>{ /* send midi message */ const ch=msg[0]&0xf; const cmd=msg[0]&~0xf; if(cmd<0x80||cmd>=0x100) return; if(this.audioContext.state=="suspended"){ this.audioContext.resume(); } switch(cmd){ case 0xb0: /* ctl change */ switch(msg[1]){ case 1: this.setModulation(ch,msg[2],t); break; case 7: this.setChVol(ch,msg[2],t); break; case 10: this.setPan(ch,msg[2],t); break; case 11: this.setExpression(ch,msg[2],t); break; case 64: this.setSustain(ch,msg[2],t); break; case 98: case 99: this.rpnidx[ch]=0x3fff; break; /* nrpn lsb/msb */ case 100: this.rpnidx[ch]=(this.rpnidx[ch]&0x3f80)|msg[2]; break; /* rpn lsb */ case 101: this.rpnidx[ch]=(this.rpnidx[ch]&0x7f)|(msg[2]<<7); break; /* rpn msb */ case 6: /* data entry msb */ switch (this.rpnidx[ch]) { case 0: this.brange[ch]=(msg[2]<<7)+(this.brange[ch]&0x7f); break; case 1: this.tuningF[ch]=(msg[2]<<7)+((this.tuningF[ch]+0x2000)&0x7f)-0x2000; break; case 2: this.tuningC[ch]=msg[2]-0x40; break; } break; case 38: /* data entry lsb */ switch (this.rpnidx[ch]) { case 0: this.brange[ch]=(this.brange[ch]&0x3f80)|msg[2]; break; case 1: this.tuningF[ch]=(((this.tuningF[ch]+0x2000)&0x3f80)|msg[2])-0x2000; break; case 2: break; } break; case 120: /* all sound off */ case 123: /* all notes off */ case 124: case 125: case 126: case 127: /* omni off/on mono/poly */ this.allSoundOff(ch); break; case 121: this.resetAllControllers(ch); break; } break; case 0xc0: this.setProgram(ch,msg[1]); break; case 0xe0: this.setBend(ch,(msg[1]+(msg[2]<<7)),t); break; case 0x90: this.noteOn(ch,msg[1],msg[2],t); break; case 0x80: this.noteOff(ch,msg[1],t); break; case 0xf0: if (msg[0] == 0xff) { this.reset(); break; } if(msg[0]!=254 && this.debug){ var ds=[]; for(let ii=0;ii= 8) { // Master Fine Tuning this.masterTuningF = (msg[6]*0x80 + msg[5] - 8192) / 8192; } if (msg[4]==4 && msg.length >= 8) { // Master Coarse Tuning this.masterTuningC = msg[6]-0x40; } } if (msg[1]==0x41 && msg[3]==0x42 && msg[4]==0x12 &&msg[5]==0x40) { // GS if ((msg[6]&0xf0)==0x10 && msg.length==11) { const c=[9,0,1,2,3,4,5,6,7,8,10,11,12,13,14,15][msg[6]&0xf]; if (msg[7]==0x15) { this.rhythm[c]=msg[8]; } else if (msg[7] >= 0x40 && msg[7] <= 0x4b) { // Scale Tuning this.scaleTuning[c][msg[7]-0x40] = (msg[8]-0x40) / 100; } } else if (msg[6]==0) { if (msg[7]==0 && msg.length==14) { // Master Tuning this.masterTuningF = (msg[8]*0x1000 + msg[9]*0x100 + msg[10]*0x10 + msg[11] - 0x400) / 1000; } else if (msg[7]==5 && msg.length==11) { // Master Transpose this.masterTuningC = msg[8]-0x40; } } } } break; } }, _createWave:(w)=>{ const imag=new Float32Array(w.length); const real=new Float32Array(w.length); for(let i=1;i{ return this.actx; }, setAudioContext:(actx,dest)=>{ this.audioContext=this.actx=actx; this.dest=dest; if(!dest) this.dest=actx.destination; this.tsdiff=performance.now()*.001-this.actx.currentTime; if(this.debug) console.log("TSDiff:"+this.tsdiff); this.out=this.actx.createGain(); this.comp=this.actx.createDynamicsCompressor(); var blen=this.actx.sampleRate*.5|0; this.convBuf=this.actx.createBuffer(2,blen,this.actx.sampleRate); this.noiseBuf={}; this.noiseBuf.n0=this.actx.createBuffer(1,blen,this.actx.sampleRate); this.noiseBuf.n1=this.actx.createBuffer(1,blen,this.actx.sampleRate); var d1=this.convBuf.getChannelData(0); var d2=this.convBuf.getChannelData(1); var dn=this.noiseBuf.n0.getChannelData(0); var dr=this.noiseBuf.n1.getChannelData(0); for(let i=0;i `; this.getAttr = (n,def)=>{ let v=this.getAttribute(n); if(v==""||v==null) return def; switch(typeof(def)){ case "number": if(v=="true") return 1; v=+v; if(isNaN(v)) return 0; return v; } return v; }; this.canvas = div.children[0]; this.appendChild(div); WebAudioTinySynthCore.bind(this)(this); const plist=this.properties; for(let k in plist){ const v = plist[k]; if(v.observer){ this["_"+k] = v.value; Object.defineProperty(this, k, { get:()=>{return this["_"+k]}, set:(val)=>{ this["_"+k] = val; this[v.observer](); } }); } else{ this[k]=v; } } for(let k in plist){ const v = plist[k]; this[k] = this.getAttr(k,v.value); } this.setQuality(1); this.init(); this._guiInit.bind(this)(); setInterval(this._guiUpdate.bind(this),100); } } window.customElements.define('webaudio-tinysynth', WebAudioTinySynthElement); } class WebAudioTinySynth { constructor(opt){ WebAudioTinySynthCore.bind(this)(this); for(let k in this.properties){ this[k]=this.properties[k].value; } this.setQuality(1); if(opt){ if(opt.useReverb!=undefined) this.useReverb=opt.useReverb; if(opt.quality!=undefined) this.setQuality(opt.quality); if(opt.voices!=undefined) this.setVoices(opt.voices); } this.init(); } } if(typeof exports === 'object' && typeof module !== 'undefined'){ module.exports = WebAudioTinySynth; } else if(typeof define === 'function' && define.amd){ define(function(){ return WebAudioTinySynth; }); } else{ window.WebAudioTinySynth = WebAudioTinySynth; } })(this);