-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
52 lines (46 loc) · 1.77 KB
/
index.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
import allSettled from 'promise.allsettled';
import Sound from 'react-native-sound';
import Player from './Player';
// List of possible notes for soundfonts
const _notes = [ 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G' ];
const _notesWithOctaves = [ 'A0', 'Bb0', 'B0' ]; // A0, Bb0 and B0 are the only 0-octave notes with samples
_notes.forEach(note => {
for (let octave = 1; octave < 8; octave++) {
_notesWithOctaves.push(`${note}${octave}`);
}
});
const defaultInstrumentOptions = Object.freeze({
notes: _notesWithOctaves,
path: Sound.MAIN_BUNDLE, // defaults to res/raw
ext: 'mp3'
});
Sound.setCategory('Playback');
// This function is outside of 'Player' so as to not be exposed
const loadSound = (sounds, instrument, name, path, ext) => {
return new Promise((resolve, reject) => {
// 'new Sound' is very expensive and blocks resolve. Wrapping in setTimeout(cb, 0) allows renders in between
setTimeout(() => {
sounds[name] = new Sound(`${instrument}_${name.toLowerCase()}.${ext}`, path, error => {
if (error) {
if (__DEV__) {
console.warn(`Failed to load "${name}" (${instrument}) from "${path}": ${JSON.stringify(error)}`);
}
reject(error);
} else {
resolve(sounds[name]);
}
});
}, 0);
});
};
export default {
instrument: (instrument, options) => {
if (!instrument) return Promise.reject('instrument() requires instrument name as first argument.');
options = { ...defaultInstrumentOptions, ...options };
const { notes, path, ext, ...playerOptions } = options;
const sounds = {};
return allSettled(
notes.map(note => loadSound(sounds, instrument, note, path, ext))
).then(() => new Player(instrument, sounds, playerOptions));
},
};