From 122836cbf480adf24a88f10539f797b2c9f00e11 Mon Sep 17 00:00:00 2001
From: danigb
Date: Mon, 6 Jun 2016 23:37:53 +0200
Subject: [PATCH] Add support to MusyngKite soundfont
---
CHANGELOG.md | 8 +-
README.md | 27 +-
dist/soundfont-player.js | 7 +-
dist/soundfont-player.min.js | 2 +-
.../acoustic_grand_piano-ogg.js | 0
examples/assets/fluidR3.json | 130 +++++++++
examples/assets/musyngkite.json | 130 +++++++++
examples/local-piano.js | 2 +-
examples/musyngkite.js | 29 ++
instruments.json | 256 +++++++++---------
lib/index.js | 26 +-
lib/legacy.js | 10 +
musyngkite.json | 130 +++++++++
names/fluidR3.json | 130 +++++++++
names/musyngkite.json | 130 +++++++++
package.json | 4 +-
test/soundfont-player-test.js | 14 +
17 files changed, 874 insertions(+), 161 deletions(-)
rename examples/{soundfonts => assets}/acoustic_grand_piano-ogg.js (100%)
create mode 100644 examples/assets/fluidR3.json
create mode 100644 examples/assets/musyngkite.json
create mode 100644 examples/musyngkite.js
create mode 100644 musyngkite.json
create mode 100644 names/fluidR3.json
create mode 100644 names/musyngkite.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2178141..8544eed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,16 @@
CHANGELOG
+[0.10.0]
+- Add support to MusyngKite soundfonts.
+- `instrument` can be partially applied with an AudioContext instance
+- Deprecate noteToMidi
+
+[0.9.2] Update sample-player
+[0.9.1] Use sample-player
[0.9.0]
- Load soundfonts directly from github.io (https://github.com/gleitz/midi-js-soundfonts/issues/9)
- New API
- Deprecate old API
-
[0.8.4]
- Use audio-loader
- Use note-parser instead of note-midi and note-freq
diff --git a/README.md b/README.md
index a2c949b..91825c1 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,8 @@ It is a much simpler and lightweight replacement for [MIDI.js](https://github.co
- Easily connect to a Web MIDI API `MidiInput`
- Schedule a list of notes
+It uses [audio-loader](https://github.com/danigb/audio-loader) to load soundfont files and [sample-player](https://github.com/danigb/sample-player) to play the sounds.
+
## Usage
[Download the distribution file](https://raw.githubusercontent.com/danigb/soundfont-player/master/dist/soundfont-player.min.js) and include it in your html...
@@ -63,10 +65,11 @@ The instrument object returned by the promise has the following properties:
- play: A function to play notes from the buffer with the signature
`play(note, time, duration, options)`
-
The valid options are:
-- `nameToUrl` : a function to convert from instrument names to URL
+- `format`: can be 'mp3' or 'ogg'
+- `soundfont`: can be 'FluidR3_GM' or 'MusyngKite'
+- `nameToUrl`: a function to convert from instrument names to URL
- `destination`: by default Soundfont uses the `audioContext.destination` but you can override it.
- `gain`: the gain (volume) of the player (1 by default)
- `adsr`: the amplitude envelope as array of `[attack, decay, sustain, release]`
@@ -85,7 +88,8 @@ limit the number of notes you want and reduce the time to load the instrument.
**Example**
```js
var Soundfont = require('sounfont-player')
-Soundfont.instrument('marimba').then(function (marimba) {
+var ac = new AudioContext()
+Soundfont.instrument(ac, 'marimba', { soundfont: 'MusyngKite' }).then(function (marimba) {
marimba.play('C4')
})
```
@@ -126,22 +130,22 @@ Connect a player to a midi input
See [sample-player](https://github.com/danigb/sample-player) for more information.
-## nameToUrl(name, format) ⇒ String
+## nameToUrl(name, soundfont, format) ⇒ String
Given an instrument name returns a URL to to the Benjamin Gleitzman's
package of [pre-rendered sound fonts](https://github.com/gleitz/midi-js-soundfonts)
-**Kind**: global function
**Returns**: String
- the Soundfont file url
| Param | Type | Description |
| --- | --- | --- |
| name | String
| instrument name |
+| soundfont | String
| (Optional) 'FluidR3_GM' or 'MusyngKite' ('FluidR3_GM' by default) |
| format | String
| (Optional) Can be 'mp3' or 'ogg' (mp3 by default) |
**Example**
```js
var Soundfont = require('soundfont-player')
-Soundfont.nameToUrl('marimba', 'mp3')
+Soundfont.nameToUrl('marimba', null, 'ogg') // => http://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/marimba-ogg.js
```
## Run the tests, examples and build the library distribution file
@@ -166,14 +170,17 @@ To run pure javascript examples `npm install -g beefy` then `beefy examples/pian
## Available instruments
-You can grab a [json file](https://github.com/danigb/soundfont-player/blob/master/instruments.json) with all the instrument names, or require it:
+Download the json files:
+ - [FluidR3_GM]()
+ - [MusyngKite]()
+
+Or require it:
```js
-var instrumentNames = require('soundfont-player/instruments.json')
+var fluidNames = require('soundfont-player/names/fuildR3.json')
+var musyngNames = require('soundfont-player/names/musyngkite.json')
```
-The complete list [is here](https://github.com/danigb/soundfont-player/blob/master/INSTRUMENTS.md)
-
## Resources
- SoundFont technical specification: http://freepats.zenvoid.org/sf2/sfspec24.pdf
diff --git a/dist/soundfont-player.js b/dist/soundfont-player.js
index 90b01a3..4141e1a 100644
--- a/dist/soundfont-player.js
+++ b/dist/soundfont-player.js
@@ -61,15 +61,18 @@ function isSoundfontURL (name) {
* package of [pre-rendered sound fonts](https://github.com/gleitz/midi-js-soundfonts)
*
* @param {String} name - instrument name
+ * @param {String} soundfont - (Optional) the soundfont name. One of 'FluidR3_GM'
+ * or 'MusyngKite' ('FluidR3_GM' by default)
* @param {String} format - (Optional) Can be 'mp3' or 'ogg' (mp3 by default)
* @returns {String} the Soundfont file url
* @example
* var Soundfont = require('soundfont-player')
* Soundfont.nameToUrl('marimba', 'mp3')
*/
-function nameToUrl (name, format) {
+function nameToUrl (name, sf, format) {
format = format === 'ogg' ? format : 'mp3'
- return 'http://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/' + name + '-' + format + '.js'
+ sf = sf === 'MusyngKite' ? sf : 'FluidR3_GM'
+ return 'http://gleitz.github.io/midi-js-soundfonts/' + sf + '/' + name + '-' + format + '.js'
}
// In the 1.0.0 release it will be:
diff --git a/dist/soundfont-player.min.js b/dist/soundfont-player.min.js
index d4223f8..10d2d7e 100644
--- a/dist/soundfont-player.min.js
+++ b/dist/soundfont-player.min.js
@@ -1 +1 @@
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0&¬e<129?+note:parser.midi(note);var freq=midi?parser.midiToFreq(midi,440):null;if(!freq)return;duration=duration||.2;options=options||{};var destination=options.destination||defaultOptions.destination||ctx.destination;var vcoType=options.vcoType||defaultOptions.vcoType||"sine";var gain=options.gain||defaultOptions.gain||.4;var vco=ctx.createOscillator();vco.type=vcoType;vco.frequency.value=freq;var vca=ctx.createGain();vca.gain.value=gain;vco.connect(vca);vca.connect(destination);vco.start(time);if(duration>0)vco.stop(time+duration);return vco}}module.exports=Soundfont},{"note-parser":6}],3:[function(require,module,exports){"use strict";function b64ToUint6(nChr){return nChr>64&&nChr<91?nChr-65:nChr>96&&nChr<123?nChr-71:nChr>47&&nChr<58?nChr+4:nChr===43?62:nChr===47?63:0}function decode(sBase64,nBlocksSize){var sB64Enc=sBase64.replace(/[^A-Za-z0-9\+\/]/g,"");var nInLen=sB64Enc.length;var nOutLen=nBlocksSize?Math.ceil((nInLen*3+1>>2)/nBlocksSize)*nBlocksSize:nInLen*3+1>>2;var taBytes=new Uint8Array(nOutLen);for(var nMod3,nMod4,nUint24=0,nOutIdx=0,nInIdx=0;nInIdx>>(16>>>nMod3&24)&255}nUint24=0}}return taBytes}module.exports={decode:decode}},{}],4:[function(require,module,exports){"use strict";module.exports=function(url,type){return new Promise(function(done,reject){var req=new XMLHttpRequest;if(type)req.responseType=type;req.open("GET",url);req.onload=function(){req.status===200?done(req.response):reject(Error(req.statusText))};req.onerror=function(){reject(Error("Network Error"))};req.send()})}},{}],5:[function(require,module,exports){"use strict";var base64=require("./base64");var fetch=require("./fetch");function fromRegex(r){return function(o){return typeof o==="string"&&r.test(o)}}function prefix(pre,name){return typeof pre==="string"?pre+name:typeof pre==="function"?pre(name):name}function load(ac,source,options,defVal){var loader=isArrayBuffer(source)?loadArrayBuffer:isAudioFileName(source)?loadAudioFile:isPromise(source)?loadPromise:isArray(source)?loadArrayData:isObject(source)?loadObjectData:isJsonFileName(source)?loadJsonFile:isBase64Audio(source)?loadBase64Audio:isJsFileName(source)?loadMidiJSFile:null;var opts=options||{};return loader?loader(ac,source,opts):defVal?Promise.resolve(defVal):Promise.reject("Source not valid ("+source+")")}load.fetch=fetch;function isArrayBuffer(o){return o instanceof ArrayBuffer}function loadArrayBuffer(ac,array,options){return new Promise(function(done,reject){ac.decodeAudioData(array,function(buffer){done(buffer)},function(){reject("Can't decode audio data ("+array.slice(0,30)+"...)")})})}var isAudioFileName=fromRegex(/\.(mp3|wav|ogg)(\?.*)?$/i);function loadAudioFile(ac,name,options){var url=prefix(options.from,name);return load(ac,load.fetch(url,"arraybuffer"),options)}function isPromise(o){return o&&typeof o.then==="function"}function loadPromise(ac,promise,options){return promise.then(function(value){return load(ac,value,options)})}var isArray=Array.isArray;function loadArrayData(ac,array,options){return Promise.all(array.map(function(data){return load(ac,data,options,data)}))}function isObject(o){return o&&typeof o==="object"}function loadObjectData(ac,obj,options){var dest={};var promises=Object.keys(obj).map(function(key){if(options.only&&options.only.indexOf(key)===-1)return null;var value=obj[key];return load(ac,value,options,value).then(function(audio){dest[key]=audio})});return Promise.all(promises).then(function(){return dest})}var isJsonFileName=fromRegex(/\.json(\?.*)?$/i);function loadJsonFile(ac,name,options){var url=prefix(options.from,name);return load(ac,load.fetch(url,"text").then(JSON.parse),options)}var isBase64Audio=fromRegex(/^data:audio/);function loadBase64Audio(ac,source,options){var i=source.indexOf(",");return load(ac,base64.decode(source.slice(i+1)).buffer,options)}var isJsFileName=fromRegex(/\.js(\?.*)?$/i);function loadMidiJSFile(ac,name,options){var url=prefix(options.from,name);return load(ac,load.fetch(url,"text").then(midiJsToJson),options)}function midiJsToJson(data){var begin=data.indexOf("MIDI.Soundfont.");if(begin<0)throw Error("Invalid MIDI.js Soundfont format");begin=data.indexOf("=",begin)+2;var end=data.lastIndexOf(",");return JSON.parse(data.slice(begin,end)+"}")}if(typeof module==="object"&&module.exports)module.exports=load;if(typeof window!=="undefined")window.loadAudio=load},{"./base64":3,"./fetch":4}],6:[function(require,module,exports){"use strict";var REGEX=/^([a-gA-G])(#{1,}|b{1,}|x{1,}|)(-?\d*)\s*(.*)\s*$/;function regex(){return REGEX}var SEMITONES=[0,2,4,5,7,9,11];function parse(str,isTonic,tuning){if(typeof str!=="string")return null;var m=REGEX.exec(str);if(!m||!isTonic&&m[4])return null;var p={letter:m[1].toUpperCase(),acc:m[2].replace(/x/g,"##")};p.pc=p.letter+p.acc;p.step=(p.letter.charCodeAt(0)+3)%7;p.alt=p.acc[0]==="b"?-p.acc.length:p.acc.length;p.chroma=SEMITONES[p.step]+p.alt;if(m[3]){p.oct=+m[3];p.midi=p.chroma+12*(p.oct+1);p.freq=midiToFreq(p.midi,tuning)}if(isTonic)p.tonicOf=m[4];return p}function midiToFreq(midi,tuning){return Math.pow(2,(midi-69)/12)*(tuning||440)}var parser={parse:parse,regex:regex,midiToFreq:midiToFreq};var FNS=["letter","acc","pc","step","alt","chroma","oct","midi","freq"];FNS.forEach(function(name){parser[name]=function(src){var p=parse(src);return p&&typeof p[name]!=="undefined"?p[name]:null}});module.exports=parser},{}],7:[function(require,module,exports){module.exports=function(player){player.on=function(event,cb){if(arguments.length===1&&typeof event==="function")return player.on("event",event);var prop="on"+event;var old=player[prop];player[prop]=old?chain(old,cb):cb;return player};return player};function chain(fn1,fn2){return function(a,b,c,d){fn1(a,b,c,d);fn2(a,b,c,d)}}},{}],8:[function(require,module,exports){"use strict";var player=require("./player");var events=require("./events");var notes=require("./notes");var scheduler=require("./scheduler");var midi=require("./midi");function SamplePlayer(ac,source,options){return midi(scheduler(notes(events(player(ac,source,options)))))}if(typeof module==="object"&&module.exports)module.exports=SamplePlayer;if(typeof window!=="undefined")window.SamplePlayer=SamplePlayer},{"./events":7,"./midi":9,"./notes":10,"./player":11,"./scheduler":12}],9:[function(require,module,exports){var midimessage=require("midimessage");module.exports=function(player){player.listenToMidi=function(input,options){var started={};var opts=options||{};var gain=opts.gain||function(vel){return vel/127};input.onmidimessage=function(msg){var mm=msg.messageType?msg:midimessage(msg);if(mm.messageType==="noteon"&&mm.velocity===0){mm.messageType="noteoff"}if(opts.channel&&mm.channel!==opts.channel)return;switch(mm.messageType){case"noteon":started[mm.key]=player.play(mm.key,0,{gain:gain(mm.velocity)});break;case"noteoff":if(started[mm.key]){started[mm.key].stop();delete started[mm.key]}break}};return player};return player}},{midimessage:14}],10:[function(require,module,exports){"use strict";var note=require("note-parser");var isMidi=function(n){return n!==null&&n!==[]&&n>=0&&n<129};var toMidi=function(n){return isMidi(n)?+n:note.midi(n)};module.exports=function(player){if(player.buffers){var map=player.opts.map;var toKey=typeof map==="function"?map:toMidi;var mapper=function(name){return name?toKey(name)||name:null};player.buffers=mapBuffers(player.buffers,mapper);var start=player.start;player.start=function(name,when,options){var key=mapper(name);var dec=key%1;if(dec){key=Math.floor(key);options=Object.assign(options||{},{cents:Math.floor(dec*100)})}return start(key,when,options)}}return player};function mapBuffers(buffers,toKey){return Object.keys(buffers).reduce(function(mapped,name){mapped[toKey(name)]=buffers[name];return mapped},{})}},{"note-parser":6}],11:[function(require,module,exports){"use strict";var ADSR=require("adsr");var EMPTY={};var DEFAULTS={gain:1,adsr:[.01,.1,.9,.3],loop:false,cents:0,loopStart:0,loopEnd:0};function SamplePlayer(ac,source,options){var connected=false;var nextId=0;var tracked={};var out=ac.createGain();out.gain.value=1;var opts=Object.assign({},DEFAULTS,options);var player={ac:ac,out:out,opts:opts};if(source instanceof AudioBuffer)player.buffer=source;else player.buffers=source;player.start=function(name,when,options){if(player.buffer&&name!==null)return player.start(null,name,when);var buffer=name?player.buffers[name]:player.buffer;if(!buffer){console.warn("Buffer "+name+" not found.");return}else if(!connected){console.warn("SamplePlayer not connected to any node.");return}var opts=options||EMPTY;when=when||ac.currentTime;player.emit("start",when,name,opts);var node=createNode(name,buffer,opts);node.id=track(name,node);node.env.start(when);node.source.start(when);if(opts.duration)node.stop(when+opts.duration);return node};player.play=function(n,w,o){player.start(n,w,o)};player.stop=function(when,ids){var node;ids=ids||Object.keys(tracked);return ids.map(function(id){node=tracked[id];if(!node)return null;node.stop(when);return node.id})};player.connect=function(dest){connected=true;out.connect(dest);return player};player.emit=function(event,when,obj,opts){if(player.onevent)player.onevent(event,when,obj,opts);var fn=player["on"+event];if(fn)fn(when,obj,opts)};return player;function track(name,node){node.id=nextId++;tracked[node.id]=node;node.source.onended=function(){var now=ac.currentTime;node.source.disconnect();node.env.disconnect();node.disconnect();player.emit("ended",now,name)};return node.id}function createNode(name,buffer,options){var node=ac.createGain();node.gain.value=0;node.connect(out);node.env=envelope(ac,options.adsr||opts.adsr);node.env.value.value=options.gain||opts.gain;node.env.connect(node.gain);node.source=ac.createBufferSource();node.source.buffer=buffer;node.source.connect(node);node.source.loop=options.loop||opts.loop;node.source.playbackRate.value=centsToRate(options.cents||opts.cents);node.source.loopStart=options.loopStart||opts.loopStart;node.source.loopEnd=options.loopEnd||opts.loopEnd;node.stop=function(when){var time=when||ac.currentTime;player.emit("stop",time,name);var stopAt=node.env.stop(time);node.source.stop(stopAt)};return node}}function envelope(ac,adsr){var env=ADSR(ac);env.attack=adsr[0];env.decay=adsr[1];env.sustain=adsr[2];env.release=adsr[3];return env}function centsToRate(cents){return cents?Math.pow(2,cents/1200):1}module.exports=SamplePlayer},{adsr:13}],12:[function(require,module,exports){"use strict";var isArr=Array.isArray;var isObj=function(o){return o&&typeof o==="object"};var OPTS={};module.exports=function(player){player.schedule=function(time,events){var now=player.ac.currentTime;var when=time=end){value=end}return value}},{}],14:[function(require,module,exports){(function(global){(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.midimessage=e()}})(function(){var e,t,s;return function o(e,t,s){function a(n,i){if(!t[n]){if(!e[n]){var l=typeof require=="function"&&require;if(!i&&l)return l(n,!0);if(r)return r(n,!0);var h=new Error("Cannot find module '"+n+"'");throw h.code="MODULE_NOT_FOUND",h}var c=t[n]={exports:{}};e[n][0].call(c.exports,function(t){var s=e[n][1][t];return a(s?s:t)},c,c.exports,o,e,t,s)}return t[n].exports}var r=typeof require=="function"&&require;for(var n=0;n0&¬e<129?+note:parser.midi(note);var freq=midi?parser.midiToFreq(midi,440):null;if(!freq)return;duration=duration||.2;options=options||{};var destination=options.destination||defaultOptions.destination||ctx.destination;var vcoType=options.vcoType||defaultOptions.vcoType||"sine";var gain=options.gain||defaultOptions.gain||.4;var vco=ctx.createOscillator();vco.type=vcoType;vco.frequency.value=freq;var vca=ctx.createGain();vca.gain.value=gain;vco.connect(vca);vca.connect(destination);vco.start(time);if(duration>0)vco.stop(time+duration);return vco}}module.exports=Soundfont},{"note-parser":6}],3:[function(require,module,exports){"use strict";function b64ToUint6(nChr){return nChr>64&&nChr<91?nChr-65:nChr>96&&nChr<123?nChr-71:nChr>47&&nChr<58?nChr+4:nChr===43?62:nChr===47?63:0}function decode(sBase64,nBlocksSize){var sB64Enc=sBase64.replace(/[^A-Za-z0-9\+\/]/g,"");var nInLen=sB64Enc.length;var nOutLen=nBlocksSize?Math.ceil((nInLen*3+1>>2)/nBlocksSize)*nBlocksSize:nInLen*3+1>>2;var taBytes=new Uint8Array(nOutLen);for(var nMod3,nMod4,nUint24=0,nOutIdx=0,nInIdx=0;nInIdx>>(16>>>nMod3&24)&255}nUint24=0}}return taBytes}module.exports={decode:decode}},{}],4:[function(require,module,exports){"use strict";module.exports=function(url,type){return new Promise(function(done,reject){var req=new XMLHttpRequest;if(type)req.responseType=type;req.open("GET",url);req.onload=function(){req.status===200?done(req.response):reject(Error(req.statusText))};req.onerror=function(){reject(Error("Network Error"))};req.send()})}},{}],5:[function(require,module,exports){"use strict";var base64=require("./base64");var fetch=require("./fetch");function fromRegex(r){return function(o){return typeof o==="string"&&r.test(o)}}function prefix(pre,name){return typeof pre==="string"?pre+name:typeof pre==="function"?pre(name):name}function load(ac,source,options,defVal){var loader=isArrayBuffer(source)?loadArrayBuffer:isAudioFileName(source)?loadAudioFile:isPromise(source)?loadPromise:isArray(source)?loadArrayData:isObject(source)?loadObjectData:isJsonFileName(source)?loadJsonFile:isBase64Audio(source)?loadBase64Audio:isJsFileName(source)?loadMidiJSFile:null;var opts=options||{};return loader?loader(ac,source,opts):defVal?Promise.resolve(defVal):Promise.reject("Source not valid ("+source+")")}load.fetch=fetch;function isArrayBuffer(o){return o instanceof ArrayBuffer}function loadArrayBuffer(ac,array,options){return new Promise(function(done,reject){ac.decodeAudioData(array,function(buffer){done(buffer)},function(){reject("Can't decode audio data ("+array.slice(0,30)+"...)")})})}var isAudioFileName=fromRegex(/\.(mp3|wav|ogg)(\?.*)?$/i);function loadAudioFile(ac,name,options){var url=prefix(options.from,name);return load(ac,load.fetch(url,"arraybuffer"),options)}function isPromise(o){return o&&typeof o.then==="function"}function loadPromise(ac,promise,options){return promise.then(function(value){return load(ac,value,options)})}var isArray=Array.isArray;function loadArrayData(ac,array,options){return Promise.all(array.map(function(data){return load(ac,data,options,data)}))}function isObject(o){return o&&typeof o==="object"}function loadObjectData(ac,obj,options){var dest={};var promises=Object.keys(obj).map(function(key){if(options.only&&options.only.indexOf(key)===-1)return null;var value=obj[key];return load(ac,value,options,value).then(function(audio){dest[key]=audio})});return Promise.all(promises).then(function(){return dest})}var isJsonFileName=fromRegex(/\.json(\?.*)?$/i);function loadJsonFile(ac,name,options){var url=prefix(options.from,name);return load(ac,load.fetch(url,"text").then(JSON.parse),options)}var isBase64Audio=fromRegex(/^data:audio/);function loadBase64Audio(ac,source,options){var i=source.indexOf(",");return load(ac,base64.decode(source.slice(i+1)).buffer,options)}var isJsFileName=fromRegex(/\.js(\?.*)?$/i);function loadMidiJSFile(ac,name,options){var url=prefix(options.from,name);return load(ac,load.fetch(url,"text").then(midiJsToJson),options)}function midiJsToJson(data){var begin=data.indexOf("MIDI.Soundfont.");if(begin<0)throw Error("Invalid MIDI.js Soundfont format");begin=data.indexOf("=",begin)+2;var end=data.lastIndexOf(",");return JSON.parse(data.slice(begin,end)+"}")}if(typeof module==="object"&&module.exports)module.exports=load;if(typeof window!=="undefined")window.loadAudio=load},{"./base64":3,"./fetch":4}],6:[function(require,module,exports){"use strict";var REGEX=/^([a-gA-G])(#{1,}|b{1,}|x{1,}|)(-?\d*)\s*(.*)\s*$/;function regex(){return REGEX}var SEMITONES=[0,2,4,5,7,9,11];function parse(str,isTonic,tuning){if(typeof str!=="string")return null;var m=REGEX.exec(str);if(!m||!isTonic&&m[4])return null;var p={letter:m[1].toUpperCase(),acc:m[2].replace(/x/g,"##")};p.pc=p.letter+p.acc;p.step=(p.letter.charCodeAt(0)+3)%7;p.alt=p.acc[0]==="b"?-p.acc.length:p.acc.length;p.chroma=SEMITONES[p.step]+p.alt;if(m[3]){p.oct=+m[3];p.midi=p.chroma+12*(p.oct+1);p.freq=midiToFreq(p.midi,tuning)}if(isTonic)p.tonicOf=m[4];return p}function midiToFreq(midi,tuning){return Math.pow(2,(midi-69)/12)*(tuning||440)}var parser={parse:parse,regex:regex,midiToFreq:midiToFreq};var FNS=["letter","acc","pc","step","alt","chroma","oct","midi","freq"];FNS.forEach(function(name){parser[name]=function(src){var p=parse(src);return p&&typeof p[name]!=="undefined"?p[name]:null}});module.exports=parser},{}],7:[function(require,module,exports){module.exports=function(player){player.on=function(event,cb){if(arguments.length===1&&typeof event==="function")return player.on("event",event);var prop="on"+event;var old=player[prop];player[prop]=old?chain(old,cb):cb;return player};return player};function chain(fn1,fn2){return function(a,b,c,d){fn1(a,b,c,d);fn2(a,b,c,d)}}},{}],8:[function(require,module,exports){"use strict";var player=require("./player");var events=require("./events");var notes=require("./notes");var scheduler=require("./scheduler");var midi=require("./midi");function SamplePlayer(ac,source,options){return midi(scheduler(notes(events(player(ac,source,options)))))}if(typeof module==="object"&&module.exports)module.exports=SamplePlayer;if(typeof window!=="undefined")window.SamplePlayer=SamplePlayer},{"./events":7,"./midi":9,"./notes":10,"./player":11,"./scheduler":12}],9:[function(require,module,exports){var midimessage=require("midimessage");module.exports=function(player){player.listenToMidi=function(input,options){var started={};var opts=options||{};var gain=opts.gain||function(vel){return vel/127};input.onmidimessage=function(msg){var mm=msg.messageType?msg:midimessage(msg);if(mm.messageType==="noteon"&&mm.velocity===0){mm.messageType="noteoff"}if(opts.channel&&mm.channel!==opts.channel)return;switch(mm.messageType){case"noteon":started[mm.key]=player.play(mm.key,0,{gain:gain(mm.velocity)});break;case"noteoff":if(started[mm.key]){started[mm.key].stop();delete started[mm.key]}break}};return player};return player}},{midimessage:14}],10:[function(require,module,exports){"use strict";var note=require("note-parser");var isMidi=function(n){return n!==null&&n!==[]&&n>=0&&n<129};var toMidi=function(n){return isMidi(n)?+n:note.midi(n)};module.exports=function(player){if(player.buffers){var map=player.opts.map;var toKey=typeof map==="function"?map:toMidi;var mapper=function(name){return name?toKey(name)||name:null};player.buffers=mapBuffers(player.buffers,mapper);var start=player.start;player.start=function(name,when,options){var key=mapper(name);var dec=key%1;if(dec){key=Math.floor(key);options=Object.assign(options||{},{cents:Math.floor(dec*100)})}return start(key,when,options)}}return player};function mapBuffers(buffers,toKey){return Object.keys(buffers).reduce(function(mapped,name){mapped[toKey(name)]=buffers[name];return mapped},{})}},{"note-parser":6}],11:[function(require,module,exports){"use strict";var ADSR=require("adsr");var EMPTY={};var DEFAULTS={gain:1,adsr:[.01,.1,.9,.3],loop:false,cents:0,loopStart:0,loopEnd:0};function SamplePlayer(ac,source,options){var connected=false;var nextId=0;var tracked={};var out=ac.createGain();out.gain.value=1;var opts=Object.assign({},DEFAULTS,options);var player={ac:ac,out:out,opts:opts};if(source instanceof AudioBuffer)player.buffer=source;else player.buffers=source;player.start=function(name,when,options){if(player.buffer&&name!==null)return player.start(null,name,when);var buffer=name?player.buffers[name]:player.buffer;if(!buffer){console.warn("Buffer "+name+" not found.");return}else if(!connected){console.warn("SamplePlayer not connected to any node.");return}var opts=options||EMPTY;when=when||ac.currentTime;player.emit("start",when,name,opts);var node=createNode(name,buffer,opts);node.id=track(name,node);node.env.start(when);node.source.start(when);if(opts.duration)node.stop(when+opts.duration);return node};player.play=function(n,w,o){player.start(n,w,o)};player.stop=function(when,ids){var node;ids=ids||Object.keys(tracked);return ids.map(function(id){node=tracked[id];if(!node)return null;node.stop(when);return node.id})};player.connect=function(dest){connected=true;out.connect(dest);return player};player.emit=function(event,when,obj,opts){if(player.onevent)player.onevent(event,when,obj,opts);var fn=player["on"+event];if(fn)fn(when,obj,opts)};return player;function track(name,node){node.id=nextId++;tracked[node.id]=node;node.source.onended=function(){var now=ac.currentTime;node.source.disconnect();node.env.disconnect();node.disconnect();player.emit("ended",now,name)};return node.id}function createNode(name,buffer,options){var node=ac.createGain();node.gain.value=0;node.connect(out);node.env=envelope(ac,options.adsr||opts.adsr);node.env.value.value=options.gain||opts.gain;node.env.connect(node.gain);node.source=ac.createBufferSource();node.source.buffer=buffer;node.source.connect(node);node.source.loop=options.loop||opts.loop;node.source.playbackRate.value=centsToRate(options.cents||opts.cents);node.source.loopStart=options.loopStart||opts.loopStart;node.source.loopEnd=options.loopEnd||opts.loopEnd;node.stop=function(when){var time=when||ac.currentTime;player.emit("stop",time,name);var stopAt=node.env.stop(time);node.source.stop(stopAt)};return node}}function envelope(ac,adsr){var env=ADSR(ac);env.attack=adsr[0];env.decay=adsr[1];env.sustain=adsr[2];env.release=adsr[3];return env}function centsToRate(cents){return cents?Math.pow(2,cents/1200):1}module.exports=SamplePlayer},{adsr:13}],12:[function(require,module,exports){"use strict";var isArr=Array.isArray;var isObj=function(o){return o&&typeof o==="object"};var OPTS={};module.exports=function(player){player.schedule=function(time,events){var now=player.ac.currentTime;var when=time=end){value=end}return value}},{}],14:[function(require,module,exports){(function(global){(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.midimessage=e()}})(function(){var e,t,s;return function o(e,t,s){function a(n,i){if(!t[n]){if(!e[n]){var l=typeof require=="function"&&require;if(!i&&l)return l(n,!0);if(r)return r(n,!0);var h=new Error("Cannot find module '"+n+"'");throw h.code="MODULE_NOT_FOUND",h}var c=t[n]={exports:{}};e[n][0].call(c.exports,function(t){var s=e[n][1][t];return a(s?s:t)},c,c.exports,o,e,t,s)}return t[n].exports}var r=typeof require=="function"&&require;for(var n=0;nIf you can\'t hear the piano, open the development console
'
function localUrl (name) {
- return 'examples/' + name + '-ogg.js'
+ return 'examples/assets/' + name + '-ogg.js'
}
sf.instrument(ac, 'acoustic_grand_piano', {
nameToUrl: localUrl,
diff --git a/examples/musyngkite.js b/examples/musyngkite.js
new file mode 100644
index 0000000..9589dcb
--- /dev/null
+++ b/examples/musyngkite.js
@@ -0,0 +1,29 @@
+/* global AudioContext */
+var ac = new AudioContext()
+var sf = require('..')
+var names = require('../assets/musyngkite.json')
+var NOTES = [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72]
+
+function loadAndPlay (name) {
+ console.log('Loading... ', name)
+ sf.instrument(ac, name, { soundfont: 'MusyngKite' }).then(function (player) {
+ console.log('Loaded')
+ player.schedule(ac.currentTime, NOTES.map(function (n, i) {
+ return [i * 0.5, n]
+ }))
+ })
+}
+
+function viewName (name) {
+ return '' + name + '
'
+}
+
+document.body.innerHTML = '' + names.map(viewName).join('') + '
'
+
+var links = document.querySelectorAll('a')
+for (var i = 0; i < links.length; i++) {
+ var a = links.item(i)
+ a.onclick = function (e) {
+ loadAndPlay(e.target.text)
+ }
+}
diff --git a/instruments.json b/instruments.json
index a450070..6293080 100644
--- a/instruments.json
+++ b/instruments.json
@@ -1,130 +1,130 @@
[
- "accordion",
- "acoustic_bass",
- "acoustic_grand_piano",
- "acoustic_guitar_nylon",
- "acoustic_guitar_steel",
- "agogo",
- "alto_sax",
- "applause",
- "bagpipe",
- "banjo",
- "baritone_sax",
- "bassoon",
- "bird_tweet",
- "blown_bottle",
- "brass_section",
- "breath_noise",
- "bright_acoustic_piano",
- "celesta",
- "cello",
- "choir_aahs",
- "church_organ",
- "clarinet",
- "clavinet",
- "contrabass",
- "distortion_guitar",
- "drawbar_organ",
- "dulcimer",
- "electric_bass_finger",
- "electric_bass_pick",
- "electric_grand_piano",
- "electric_guitar_clean",
- "electric_guitar_jazz",
- "electric_guitar_muted",
- "electric_piano_1",
- "electric_piano_2",
- "english_horn",
- "fiddle",
- "flute",
- "french_horn",
- "fretless_bass",
- "fx_1_rain",
- "fx_2_soundtrack",
- "fx_3_crystal",
- "fx_4_atmosphere",
- "fx_5_brightness",
- "fx_6_goblins",
- "fx_7_echoes",
- "fx_8_scifi",
- "glockenspiel",
- "guitar_fret_noise",
- "guitar_harmonics",
- "gunshot",
- "harmonica",
- "harpsichord",
- "helicopter",
- "honkytonk_piano",
- "kalimba",
- "koto",
- "lead_1_square",
- "lead_2_sawtooth",
- "lead_3_calliope",
- "lead_4_chiff",
- "lead_5_charang",
- "lead_6_voice",
- "lead_7_fifths",
- "lead_8_bass__lead",
- "marimba",
- "melodic_tom",
- "music_box",
- "muted_trumpet",
- "oboe",
- "ocarina",
- "orchestra_hit",
- "orchestral_harp",
- "overdriven_guitar",
- "pad_1_new_age",
- "pad_2_warm",
- "pad_3_polysynth",
- "pad_4_choir",
- "pad_5_bowed",
- "pad_6_metallic",
- "pad_7_halo",
- "pad_8_sweep",
- "pan_flute",
- "percussive_organ",
- "piccolo",
- "pizzicato_strings",
- "recorder",
- "reed_organ",
- "reverse_cymbal",
- "rock_organ",
- "seashore",
- "shakuhachi",
- "shamisen",
- "shanai",
- "sitar",
- "slap_bass_1",
- "slap_bass_2",
- "soprano_sax",
- "steel_drums",
- "string_ensemble_1",
- "string_ensemble_2",
- "synth_bass_1",
- "synth_bass_2",
- "synth_brass_1",
- "synth_brass_2",
- "synth_choir",
- "synth_drum",
- "synth_strings_1",
- "synth_strings_2",
- "taiko_drum",
- "tango_accordion",
- "telephone_ring",
- "tenor_sax",
- "timpani",
- "tinkle_bell",
- "tremolo_strings",
- "trombone",
- "trumpet",
- "tuba",
- "tubular_bells",
- "vibraphone",
- "viola",
- "violin",
- "voice_oohs",
- "whistle",
- "woodblock",
- "xylophone"
+ "accordion",
+ "acoustic_bass",
+ "acoustic_grand_piano",
+ "acoustic_guitar_nylon",
+ "acoustic_guitar_steel",
+ "agogo",
+ "alto_sax",
+ "applause",
+ "bagpipe",
+ "banjo",
+ "baritone_sax",
+ "bassoon",
+ "bird_tweet",
+ "blown_bottle",
+ "brass_section",
+ "breath_noise",
+ "bright_acoustic_piano",
+ "celesta",
+ "cello",
+ "choir_aahs",
+ "church_organ",
+ "clarinet",
+ "clavinet",
+ "contrabass",
+ "distortion_guitar",
+ "drawbar_organ",
+ "dulcimer",
+ "electric_bass_finger",
+ "electric_bass_pick",
+ "electric_grand_piano",
+ "electric_guitar_clean",
+ "electric_guitar_jazz",
+ "electric_guitar_muted",
+ "electric_piano_1",
+ "electric_piano_2",
+ "english_horn",
+ "fiddle",
+ "flute",
+ "french_horn",
+ "fretless_bass",
+ "fx_1_rain",
+ "fx_2_soundtrack",
+ "fx_3_crystal",
+ "fx_4_atmosphere",
+ "fx_5_brightness",
+ "fx_6_goblins",
+ "fx_7_echoes",
+ "fx_8_scifi",
+ "glockenspiel",
+ "guitar_fret_noise",
+ "guitar_harmonics",
+ "gunshot",
+ "harmonica",
+ "harpsichord",
+ "helicopter",
+ "honkytonk_piano",
+ "kalimba",
+ "koto",
+ "lead_1_square",
+ "lead_2_sawtooth",
+ "lead_3_calliope",
+ "lead_4_chiff",
+ "lead_5_charang",
+ "lead_6_voice",
+ "lead_7_fifths",
+ "lead_8_bass__lead",
+ "marimba",
+ "melodic_tom",
+ "music_box",
+ "muted_trumpet",
+ "oboe",
+ "ocarina",
+ "orchestra_hit",
+ "orchestral_harp",
+ "overdriven_guitar",
+ "pad_1_new_age",
+ "pad_2_warm",
+ "pad_3_polysynth",
+ "pad_4_choir",
+ "pad_5_bowed",
+ "pad_6_metallic",
+ "pad_7_halo",
+ "pad_8_sweep",
+ "pan_flute",
+ "percussive_organ",
+ "piccolo",
+ "pizzicato_strings",
+ "recorder",
+ "reed_organ",
+ "reverse_cymbal",
+ "rock_organ",
+ "seashore",
+ "shakuhachi",
+ "shamisen",
+ "shanai",
+ "sitar",
+ "slap_bass_1",
+ "slap_bass_2",
+ "soprano_sax",
+ "steel_drums",
+ "string_ensemble_1",
+ "string_ensemble_2",
+ "synth_bass_1",
+ "synth_bass_2",
+ "synth_brass_1",
+ "synth_brass_2",
+ "synth_choir",
+ "synth_drum",
+ "synth_strings_1",
+ "synth_strings_2",
+ "taiko_drum",
+ "tango_accordion",
+ "telephone_ring",
+ "tenor_sax",
+ "timpani",
+ "tinkle_bell",
+ "tremolo_strings",
+ "trombone",
+ "trumpet",
+ "tuba",
+ "tubular_bells",
+ "vibraphone",
+ "viola",
+ "violin",
+ "voice_oohs",
+ "whistle",
+ "woodblock",
+ "xylophone"
]
diff --git a/lib/index.js b/lib/index.js
index 4d4f3a5..f0c9d6f 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,6 +1,5 @@
'use strict'
-var note = require('note-parser')
var load = require('audio-loader')
var player = require('sample-player')
@@ -17,6 +16,8 @@ var player = require('sample-player')
*
* The valid options are:
*
+ * - `format`: the soundfont format. 'mp3' by default. Can be 'ogg'
+ * - `soundfont`: the soundfont name. 'FluidR3_GM' by default. Can be 'MusyngKite'
* - `nameToUrl` : a function to convert from instrument names to URL
* - `destination`: by default Soundfont uses the `audioContext.destination` but you can override it.
* - `gain`: the gain of the player (1 by default)
@@ -37,11 +38,11 @@ var player = require('sample-player')
* })
*/
function instrument (ac, name, options) {
+ if (arguments.length === 1) return function (n, o) { return instrument(ac, n, o) }
var opts = options || {}
var isUrl = opts.isSoundfontURL || isSoundfontURL
- var url = isUrl(name) ? name
- : opts.nameToUrl ? opts.nameToUrl(name)
- : nameToUrl(name)
+ var toUrl = opts.nameToUrl || nameToUrl
+ var url = isUrl(name) ? name : toUrl(name, opts.soundfont, opts.format)
return load(ac, url, { only: opts.only || opts.notes }).then(function (buffers) {
var p = player(ac, buffers, opts).connect(ac.destination)
@@ -60,15 +61,18 @@ function isSoundfontURL (name) {
* package of [pre-rendered sound fonts](https://github.com/gleitz/midi-js-soundfonts)
*
* @param {String} name - instrument name
+ * @param {String} soundfont - (Optional) the soundfont name. One of 'FluidR3_GM'
+ * or 'MusyngKite' ('FluidR3_GM' by default)
* @param {String} format - (Optional) Can be 'mp3' or 'ogg' (mp3 by default)
* @returns {String} the Soundfont file url
* @example
* var Soundfont = require('soundfont-player')
* Soundfont.nameToUrl('marimba', 'mp3')
*/
-function nameToUrl (name, format) {
+function nameToUrl (name, sf, format) {
format = format === 'ogg' ? format : 'mp3'
- return 'http://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/' + name + '-' + format + '.js'
+ sf = sf === 'MusyngKite' ? sf : 'FluidR3_GM'
+ return 'http://gleitz.github.io/midi-js-soundfonts/' + sf + '/' + name + '-' + format + '.js'
}
// In the 1.0.0 release it will be:
@@ -77,15 +81,5 @@ var Soundfont = require('./legacy')
Soundfont.instrument = instrument
Soundfont.nameToUrl = nameToUrl
-/**
- * Given a note name, return the note midi number
- *
- * @name noteToMidi
- * @function
- * @param {String} noteName
- * @return {Integer} the note midi number or null if not a valid note name
- */
-Soundfont.noteToMidi = note.midi
-
if (typeof module === 'object' && module.exports) module.exports = Soundfont
if (typeof window !== 'undefined') window.Soundfont = Soundfont
diff --git a/lib/legacy.js b/lib/legacy.js
index 182f924..61de7ff 100644
--- a/lib/legacy.js
+++ b/lib/legacy.js
@@ -127,4 +127,14 @@ function oscillatorPlayer (ctx, defaultOptions) {
}
}
+/**
+ * Given a note name, return the note midi number
+ *
+ * @name noteToMidi
+ * @function
+ * @param {String} noteName
+ * @return {Integer} the note midi number or null if not a valid note name
+ */
+Soundfont.noteToMidi = parser.midi
+
module.exports = Soundfont
diff --git a/musyngkite.json b/musyngkite.json
new file mode 100644
index 0000000..35d1441
--- /dev/null
+++ b/musyngkite.json
@@ -0,0 +1,130 @@
+[
+ "accordion",
+ "acoustic_bass",
+ "acoustic_grand_piano",
+ "acoustic_guitar_nylon",
+ "acoustic_guitar_steel",
+ "agogo",
+ "alto_sax",
+ "applause",
+ "bag_pipe",
+ "banjo",
+ "baritone_sax",
+ "bassoon",
+ "bird_tweet",
+ "blown_bottle",
+ "brass_section",
+ "breath_noise",
+ "bright_acoustic_piano",
+ "celesta",
+ "cello",
+ "choir_aahs",
+ "church_organ",
+ "clarinet",
+ "clavichord",
+ "contrabass",
+ "distortion_guitar",
+ "drawbar_organ",
+ "dulcimer",
+ "electric_bass_finger",
+ "electric_bass_pick",
+ "electric_grand_piano",
+ "electric_guitar_clean",
+ "electric_guitar_jazz",
+ "electric_guitar_muted",
+ "electric_piano_1",
+ "electric_piano_2",
+ "english_horn",
+ "fiddle",
+ "flute",
+ "french_horn",
+ "fretless_bass",
+ "fx_1_rain",
+ "fx_2_soundtrack",
+ "fx_3_crystal",
+ "fx_4_atmosphere",
+ "fx_5_brightness",
+ "fx_6_goblins",
+ "fx_7_echoes",
+ "fx_8_scifi",
+ "glockenspiel",
+ "guitar_fret_noise",
+ "guitar_harmonics",
+ "gunshot",
+ "harmonica",
+ "harpsichord",
+ "helicopter",
+ "honkytonk_piano",
+ "kalimba",
+ "koto",
+ "lead_1_square",
+ "lead_2_sawtooth",
+ "lead_3_calliope",
+ "lead_4_chiff",
+ "lead_5_charang",
+ "lead_6_voice",
+ "lead_7_fifths",
+ "lead_8_bass_lead",
+ "marimba",
+ "melodic_tom",
+ "music_box",
+ "muted_trumpet",
+ "oboe",
+ "ocarina",
+ "orchestra_hit",
+ "orchestral_harp",
+ "overdriven_guitar",
+ "pad_1_new_age",
+ "pad_2_warm",
+ "pad_3_polysynth",
+ "pad_4_choir",
+ "pad_5_bowed",
+ "pad_6_metallic",
+ "pad_7_halo",
+ "pad_8_sweep",
+ "pan_flute",
+ "percussive_organ",
+ "piccolo",
+ "pizzicato_strings",
+ "recorder",
+ "reed_organ",
+ "reverse_cymbal",
+ "rock_organ",
+ "seashore",
+ "shakuhachi",
+ "shamisen",
+ "shanai",
+ "sitar",
+ "slap_bass_1",
+ "slap_bass_2",
+ "soprano_sax",
+ "steel_drums",
+ "string_ensemble_1",
+ "string_ensemble_2",
+ "synth_bass_1",
+ "synth_bass_2",
+ "synth_drum",
+ "synth_voice",
+ "synthbrass_1",
+ "synthbrass_2",
+ "synthstrings_1",
+ "synthstrings_2",
+ "taiko_drum",
+ "tango_accordion",
+ "telephone_ring",
+ "tenor_sax",
+ "timpani",
+ "tinkle_bell",
+ "tremolo_strings",
+ "trombone",
+ "trumpet",
+ "tuba",
+ "tubular_bells",
+ "vibraphone",
+ "viola",
+ "violin",
+ "voice_oohs",
+ "whistle",
+ "woodblock",
+ "xylophone"
+]
\ No newline at end of file
diff --git a/names/fluidR3.json b/names/fluidR3.json
new file mode 100644
index 0000000..6293080
--- /dev/null
+++ b/names/fluidR3.json
@@ -0,0 +1,130 @@
+[
+ "accordion",
+ "acoustic_bass",
+ "acoustic_grand_piano",
+ "acoustic_guitar_nylon",
+ "acoustic_guitar_steel",
+ "agogo",
+ "alto_sax",
+ "applause",
+ "bagpipe",
+ "banjo",
+ "baritone_sax",
+ "bassoon",
+ "bird_tweet",
+ "blown_bottle",
+ "brass_section",
+ "breath_noise",
+ "bright_acoustic_piano",
+ "celesta",
+ "cello",
+ "choir_aahs",
+ "church_organ",
+ "clarinet",
+ "clavinet",
+ "contrabass",
+ "distortion_guitar",
+ "drawbar_organ",
+ "dulcimer",
+ "electric_bass_finger",
+ "electric_bass_pick",
+ "electric_grand_piano",
+ "electric_guitar_clean",
+ "electric_guitar_jazz",
+ "electric_guitar_muted",
+ "electric_piano_1",
+ "electric_piano_2",
+ "english_horn",
+ "fiddle",
+ "flute",
+ "french_horn",
+ "fretless_bass",
+ "fx_1_rain",
+ "fx_2_soundtrack",
+ "fx_3_crystal",
+ "fx_4_atmosphere",
+ "fx_5_brightness",
+ "fx_6_goblins",
+ "fx_7_echoes",
+ "fx_8_scifi",
+ "glockenspiel",
+ "guitar_fret_noise",
+ "guitar_harmonics",
+ "gunshot",
+ "harmonica",
+ "harpsichord",
+ "helicopter",
+ "honkytonk_piano",
+ "kalimba",
+ "koto",
+ "lead_1_square",
+ "lead_2_sawtooth",
+ "lead_3_calliope",
+ "lead_4_chiff",
+ "lead_5_charang",
+ "lead_6_voice",
+ "lead_7_fifths",
+ "lead_8_bass__lead",
+ "marimba",
+ "melodic_tom",
+ "music_box",
+ "muted_trumpet",
+ "oboe",
+ "ocarina",
+ "orchestra_hit",
+ "orchestral_harp",
+ "overdriven_guitar",
+ "pad_1_new_age",
+ "pad_2_warm",
+ "pad_3_polysynth",
+ "pad_4_choir",
+ "pad_5_bowed",
+ "pad_6_metallic",
+ "pad_7_halo",
+ "pad_8_sweep",
+ "pan_flute",
+ "percussive_organ",
+ "piccolo",
+ "pizzicato_strings",
+ "recorder",
+ "reed_organ",
+ "reverse_cymbal",
+ "rock_organ",
+ "seashore",
+ "shakuhachi",
+ "shamisen",
+ "shanai",
+ "sitar",
+ "slap_bass_1",
+ "slap_bass_2",
+ "soprano_sax",
+ "steel_drums",
+ "string_ensemble_1",
+ "string_ensemble_2",
+ "synth_bass_1",
+ "synth_bass_2",
+ "synth_brass_1",
+ "synth_brass_2",
+ "synth_choir",
+ "synth_drum",
+ "synth_strings_1",
+ "synth_strings_2",
+ "taiko_drum",
+ "tango_accordion",
+ "telephone_ring",
+ "tenor_sax",
+ "timpani",
+ "tinkle_bell",
+ "tremolo_strings",
+ "trombone",
+ "trumpet",
+ "tuba",
+ "tubular_bells",
+ "vibraphone",
+ "viola",
+ "violin",
+ "voice_oohs",
+ "whistle",
+ "woodblock",
+ "xylophone"
+]
diff --git a/names/musyngkite.json b/names/musyngkite.json
new file mode 100644
index 0000000..35d1441
--- /dev/null
+++ b/names/musyngkite.json
@@ -0,0 +1,130 @@
+[
+ "accordion",
+ "acoustic_bass",
+ "acoustic_grand_piano",
+ "acoustic_guitar_nylon",
+ "acoustic_guitar_steel",
+ "agogo",
+ "alto_sax",
+ "applause",
+ "bag_pipe",
+ "banjo",
+ "baritone_sax",
+ "bassoon",
+ "bird_tweet",
+ "blown_bottle",
+ "brass_section",
+ "breath_noise",
+ "bright_acoustic_piano",
+ "celesta",
+ "cello",
+ "choir_aahs",
+ "church_organ",
+ "clarinet",
+ "clavichord",
+ "contrabass",
+ "distortion_guitar",
+ "drawbar_organ",
+ "dulcimer",
+ "electric_bass_finger",
+ "electric_bass_pick",
+ "electric_grand_piano",
+ "electric_guitar_clean",
+ "electric_guitar_jazz",
+ "electric_guitar_muted",
+ "electric_piano_1",
+ "electric_piano_2",
+ "english_horn",
+ "fiddle",
+ "flute",
+ "french_horn",
+ "fretless_bass",
+ "fx_1_rain",
+ "fx_2_soundtrack",
+ "fx_3_crystal",
+ "fx_4_atmosphere",
+ "fx_5_brightness",
+ "fx_6_goblins",
+ "fx_7_echoes",
+ "fx_8_scifi",
+ "glockenspiel",
+ "guitar_fret_noise",
+ "guitar_harmonics",
+ "gunshot",
+ "harmonica",
+ "harpsichord",
+ "helicopter",
+ "honkytonk_piano",
+ "kalimba",
+ "koto",
+ "lead_1_square",
+ "lead_2_sawtooth",
+ "lead_3_calliope",
+ "lead_4_chiff",
+ "lead_5_charang",
+ "lead_6_voice",
+ "lead_7_fifths",
+ "lead_8_bass_lead",
+ "marimba",
+ "melodic_tom",
+ "music_box",
+ "muted_trumpet",
+ "oboe",
+ "ocarina",
+ "orchestra_hit",
+ "orchestral_harp",
+ "overdriven_guitar",
+ "pad_1_new_age",
+ "pad_2_warm",
+ "pad_3_polysynth",
+ "pad_4_choir",
+ "pad_5_bowed",
+ "pad_6_metallic",
+ "pad_7_halo",
+ "pad_8_sweep",
+ "pan_flute",
+ "percussive_organ",
+ "piccolo",
+ "pizzicato_strings",
+ "recorder",
+ "reed_organ",
+ "reverse_cymbal",
+ "rock_organ",
+ "seashore",
+ "shakuhachi",
+ "shamisen",
+ "shanai",
+ "sitar",
+ "slap_bass_1",
+ "slap_bass_2",
+ "soprano_sax",
+ "steel_drums",
+ "string_ensemble_1",
+ "string_ensemble_2",
+ "synth_bass_1",
+ "synth_bass_2",
+ "synth_drum",
+ "synth_voice",
+ "synthbrass_1",
+ "synthbrass_2",
+ "synthstrings_1",
+ "synthstrings_2",
+ "taiko_drum",
+ "tango_accordion",
+ "telephone_ring",
+ "tenor_sax",
+ "timpani",
+ "tinkle_bell",
+ "tremolo_strings",
+ "trombone",
+ "trumpet",
+ "tuba",
+ "tubular_bells",
+ "vibraphone",
+ "viola",
+ "violin",
+ "voice_oohs",
+ "whistle",
+ "woodblock",
+ "xylophone"
+]
\ No newline at end of file
diff --git a/package.json b/package.json
index a4a8f12..609b47a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "soundfont-player",
- "version": "0.9.3",
+ "version": "0.9.4",
"description": "Lightweight soundfont (music instrument) loader and player for WebAudio API",
"main": "lib/index.js",
"scripts": {
@@ -27,7 +27,7 @@
"url": "https://github.com/danigb/soundfont-player/issues"
},
"dependencies": {
- "audio-loader": "^0.4.0",
+ "audio-loader": "^0.5.0",
"note-parser": "^1.1.0",
"sample-player": "^0.5.2"
},
diff --git a/test/soundfont-player-test.js b/test/soundfont-player-test.js
index 4e82278..0f43187 100644
--- a/test/soundfont-player-test.js
+++ b/test/soundfont-player-test.js
@@ -43,4 +43,18 @@ describe('Soundfont player', function () {
})
})
})
+ describe('Build urls', function () {
+ it('get default url', function () {
+ assert.equal(Soundfont.nameToUrl('marimba'),
+ 'http://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/marimba-mp3.js')
+ })
+ it('get MusyngKite url', function () {
+ assert.equal(Soundfont.nameToUrl('marimba', 'MusyngKite'),
+ 'http://gleitz.github.io/midi-js-soundfonts/MusyngKite/marimba-mp3.js')
+ })
+ it('accepts ogg', function () {
+ assert.equal(Soundfont.nameToUrl('marimba', null, 'ogg'),
+ 'http://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/marimba-ogg.js')
+ })
+ })
})