-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathindex.js
More file actions
125 lines (94 loc) · 3.07 KB
/
Copy pathindex.js
File metadata and controls
125 lines (94 loc) · 3.07 KB
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
var setterGetterify = require('setter-getterify');
var DCBias = require('openmusic-dcbias');
function SamplePlayer(context) {
var node = context.createGain();
var nodeProperties = {
buffer: null,
loop: false,
loopStart: 0,
loopEnd: 0,
pitchBend: null
};
var bufferSourcesCount = 0;
var bufferSources = {};
var bufferSourceProperties = {};
var pitchBend = DCBias(context);
nodeProperties.pitchBend = pitchBend.gain;
pitchBend.gain.setValueAtTime(0, context.currentTime);
setterGetterify(node, nodeProperties, {
afterSetting: onNodePropertySet
});
// TODO: player can be mono or poly i.e. only one buffer can play at a given time or many can overlap
node.start = function(when, offset, duration) {
var buffer = nodeProperties['buffer'];
if(!buffer) {
console.info('OpenMusic SamplePlayer: no buffer to play, so byeee!');
return;
}
when = when !== undefined ? when : 0;
offset = offset !== undefined ? offset : 0;
// TODO This is mega ugly but urgh what is going on urgh
// if I just pass 'undefined' as duration Chrome doesn't play anything
if(window.webkitAudioContext) {
console.log('correcting for chrome aghh');
var sampleLength = buffer.length;
duration = duration !== undefined ? duration : sampleLength - offset;
}
// Mono: invalidate all scheduled bufferSources to make sure only one is played (retrig mode)
// TODO implement invalidation code ...
pitchBend.start();
// Poly: it's fine, just add a new one to the list
var bs = makeBufferSource();
// console.log('start', 'when', when, 'offset', offset, 'duration', duration);
bs.start(when, offset, duration);
};
node.stop = function(when) {
// For ease of development, we'll just stop to all the sources and empty the queue
// If you need to re-schedule them, you'll need to call start() again.
var keys = Object.keys(bufferSources);
keys.forEach(function(k) {
var source = bufferSources[k];
source.stop(when);
removeFromQueue(source);
});
pitchBend.stop(when);
};
node.cancelScheduledEvents = function(when) {
// TODO: when/if there is automation
};
return node;
//~~~
function makeBufferSource() {
var source = context.createBufferSource();
source.addEventListener('ended', onBufferEnded);
source.connect(node);
source.id = bufferSourcesCount++;
bufferSources[source.id] = source;
pitchBend.connect(source.playbackRate);
Object.keys(nodeProperties).forEach(function(name) {
source[name] = nodeProperties[name];
});
return source;
}
function onBufferEnded(e) {
var source = e.target;
source.stop();
source.disconnect();
pitchBend.disconnect(source.playbackRate);
// also remove from list
removeFromQueue(source);
}
function onNodePropertySet(property, value) {
var keys = Object.keys(bufferSources);
keys.forEach(function(k) {
var src = bufferSources[k];
src.loopStart = nodeProperties.loopStart;
src.loopEnd = nodeProperties.loopEnd;
src.loop = nodeProperties.loop;
});
}
function removeFromQueue(source) {
delete bufferSources[source.id];
}
}
module.exports = SamplePlayer;