-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathload.js
147 lines (129 loc) · 4.49 KB
/
load.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'use strict'
var base64 = require('./base64')
var isBuffer = require('is-buffer')
// Given a regex, return a function that test if against a string
function fromRegex (r) {
return function (o) { return typeof o === 'string' && r.test(o) }
}
// Try to apply a prefix to a name
function prefix (pre, name) {
return typeof pre === 'string' ? pre + name
: typeof pre === 'function' ? pre(name)
: name
}
/**
* Load one or more audio files
*
*
* Possible option keys:
*
* - __from__ {Function|String}: a function or string to convert from file names to urls.
* If is a string it will be prefixed to the name:
* `load('snare.mp3', { from: 'http://audio.net/samples/' })`
* If it's a function it receives the file name and should return the url as string.
* - __only__ {Array} - when loading objects, if provided, only the given keys
* will be included in the decoded object:
* `load('piano.json', { only: ['C2', 'D2'] })`
*
* @param {Object} source - the object to be loaded
* @param {Object} options - (Optional) the load options for that object
* @param {Object} defaultValue - (Optional) the default value to return as
* in a promise if not valid loader found
*/
function load (source, options, defVal) {
var loader =
// Basic audio loading
isArrayBuffer(source) || isBuffer(source) ? decodeBuffer
: isAudioFileName(source) ? loadAudioFile
: isPromise(source) ? loadPromise
// Compound objects
: isArray(source) ? loadArrayData
: isObject(source) ? loadObjectData
: isJsonFileName(source) ? loadJsonFile
// Base64 encoded audio
: isBase64Audio(source) ? loadBase64Audio
: isJsFileName(source) ? loadMidiJSFile
: null
var opts = options || {}
var promise = loader ? loader(source, opts)
: defVal ? Promise.resolve(defVal)
: Promise.reject('Source not valid (' + source + ')')
return promise.then(function (data) {
opts.ready(null, data)
return data
}, function (err) {
opts.ready(err)
throw err
})
}
// BASIC AUDIO LOADING
// ===================
// Load (decode) an array buffer
function isArrayBuffer (o) { return o instanceof ArrayBuffer }
function decodeBuffer (array, options) {
return options.decode(array)
}
// Load an audio filename
var isAudioFileName = fromRegex(/\.(mp3|wav|ogg|m4a)(\?.*)?$/i)
function loadAudioFile (name, options) {
var url = prefix(options.from, name)
return load(options.fetch(url, 'arraybuffer'), options)
}
// Load the result of a promise
function isPromise (o) { return o && typeof o.then === 'function' }
function loadPromise (promise, options) {
return promise.then(function (value) {
return load(value, options)
})
}
// COMPOUND OBJECTS
// ================
// Try to load all the items of an array
var isArray = Array.isArray
function loadArrayData (array, options) {
return Promise.all(array.map(function (data) {
return load(data, options, data)
}))
}
// Try to load all the values of a key/value object
function isObject (o) { return o && typeof o === 'object' }
function loadObjectData (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(value, options, value).then(function (audio) {
dest[key] = audio
})
})
return Promise.all(promises).then(function () { return dest })
}
// Load the content of a JSON file
var isJsonFileName = fromRegex(/\.json(\?.*)?$/i)
function loadJsonFile (name, options) {
var url = prefix(options.from, name)
return load(options.fetch(url, 'text').then(JSON.parse), options)
}
// BASE64 ENCODED FORMATS
// ======================
// Load strings with Base64 encoded audio
var isBase64Audio = fromRegex(/^data:audio/)
function loadBase64Audio (source, options) {
var i = source.indexOf(',')
return load(base64.decode(source.slice(i + 1)).buffer, options)
}
// Load .js files with MidiJS soundfont prerendered audio
var isJsFileName = fromRegex(/\.js(\?.*)?$/i)
function loadMidiJSFile (name, options) {
var url = prefix(options.from, name)
return load(options.fetch(url, 'text').then(midiJsToJson), options)
}
// convert a MIDI.js javascript soundfont file to json
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