wavesurfer 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/wavesurfer.rb +6 -0
- data/lib/wavesurfer/version.rb +3 -0
- data/vendor/assets/javascripts/plugin/wavesurfer.elan.js +252 -0
- data/vendor/assets/javascripts/plugin/wavesurfer.microphone.js +173 -0
- data/vendor/assets/javascripts/plugin/wavesurfer.minimap.js +200 -0
- data/vendor/assets/javascripts/plugin/wavesurfer.regions.js +390 -0
- data/vendor/assets/javascripts/plugin/wavesurfer.spectrogram.js +210 -0
- data/vendor/assets/javascripts/plugin/wavesurfer.timeline.js +196 -0
- data/vendor/assets/javascripts/src/drawer.canvas.js +134 -0
- data/vendor/assets/javascripts/src/drawer.js +193 -0
- data/vendor/assets/javascripts/src/mediaelement.js +160 -0
- data/vendor/assets/javascripts/src/util.js +132 -0
- data/vendor/assets/javascripts/src/wavesurfer.js +440 -0
- data/vendor/assets/javascripts/src/webaudio.js +385 -0
- data/vendor/assets/javascripts/wavesurfer-plugins.js +6 -0
- data/vendor/assets/javascripts/wavesurfer.js +6 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 681097b7ed76d7f145a5057975cbb28290a6c514
|
4
|
+
data.tar.gz: 6eae3e0b07cd65f61b0cb819b745e9a11ce25133
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 076cf51b74820f0880cc2b1338a42b424ccbf4d874d59b8cac15ac465744e44f2b8e108cab494a51fbe361817333920cea7e27b94d04c1fa7b3fe38d359ba541
|
7
|
+
data.tar.gz: 9dbb1ad884e6e81a92d5369ea3a1b0c4a6a862b7180608fe01531c1bef1f1cebeabaee6f2ea4c5a17e7b0a61be791e810af7f24d5fd893f2206055d4ab276a43
|
data/lib/wavesurfer.rb
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
WaveSurfer.ELAN = {
|
4
|
+
Types: {
|
5
|
+
ALIGNABLE_ANNOTATION: 'ALIGNABLE_ANNOTATION',
|
6
|
+
REF_ANNOTATION: 'REF_ANNOTATION'
|
7
|
+
},
|
8
|
+
|
9
|
+
init: function (params) {
|
10
|
+
this.data = null;
|
11
|
+
this.params = params;
|
12
|
+
this.container = 'string' == typeof params.container ?
|
13
|
+
document.querySelector(params.container) : params.container;
|
14
|
+
|
15
|
+
if (!this.container) {
|
16
|
+
throw Error('No container for ELAN');
|
17
|
+
}
|
18
|
+
|
19
|
+
this.bindClick();
|
20
|
+
|
21
|
+
if (params.url) {
|
22
|
+
this.load(params.url);
|
23
|
+
}
|
24
|
+
},
|
25
|
+
|
26
|
+
load: function (url) {
|
27
|
+
var my = this;
|
28
|
+
this.loadXML(url, function (xml) {
|
29
|
+
my.data = my.parseElan(xml);
|
30
|
+
my.render();
|
31
|
+
my.fireEvent('ready', my.data);
|
32
|
+
});
|
33
|
+
},
|
34
|
+
|
35
|
+
loadXML: function (url, callback) {
|
36
|
+
var xhr = new XMLHttpRequest();
|
37
|
+
xhr.open('GET', url, true);
|
38
|
+
xhr.responseType = 'document';
|
39
|
+
xhr.send();
|
40
|
+
xhr.addEventListener('load', function (e) {
|
41
|
+
callback && callback(e.target.responseXML);
|
42
|
+
});
|
43
|
+
},
|
44
|
+
|
45
|
+
parseElan: function (xml) {
|
46
|
+
var _forEach = Array.prototype.forEach;
|
47
|
+
var _map = Array.prototype.map;
|
48
|
+
|
49
|
+
var data = {
|
50
|
+
media: {},
|
51
|
+
timeOrder: {},
|
52
|
+
tiers: [],
|
53
|
+
annotations: {},
|
54
|
+
alignableAnnotations: []
|
55
|
+
};
|
56
|
+
|
57
|
+
var header = xml.querySelector('HEADER');
|
58
|
+
var inMilliseconds = header.getAttribute('TIME_UNITS') == 'milliseconds';
|
59
|
+
var media = header.querySelector('MEDIA_DESCRIPTOR');
|
60
|
+
data.media.url = media.getAttribute('MEDIA_URL');
|
61
|
+
data.media.type = media.getAttribute('MIME_TYPE');
|
62
|
+
|
63
|
+
var timeSlots = xml.querySelectorAll('TIME_ORDER TIME_SLOT');
|
64
|
+
var timeOrder = {};
|
65
|
+
_forEach.call(timeSlots, function (slot) {
|
66
|
+
var value = parseFloat(slot.getAttribute('TIME_VALUE'));
|
67
|
+
// If in milliseconds, convert to seconds with rounding
|
68
|
+
if (inMilliseconds) {
|
69
|
+
value = Math.round(value * 1e2) / 1e5;
|
70
|
+
}
|
71
|
+
timeOrder[slot.getAttribute('TIME_SLOT_ID')] = value;
|
72
|
+
});
|
73
|
+
|
74
|
+
data.tiers = _map.call(xml.querySelectorAll('TIER'), function (tier) {
|
75
|
+
return {
|
76
|
+
id: tier.getAttribute('TIER_ID'),
|
77
|
+
linguisticTypeRef: tier.getAttribute('LINGUISTIC_TYPE_REF'),
|
78
|
+
defaultLocale: tier.getAttribute('DEFAULT_LOCALE'),
|
79
|
+
annotations: _map.call(
|
80
|
+
tier.querySelectorAll('REF_ANNOTATION, ALIGNABLE_ANNOTATION'),
|
81
|
+
function (node) {
|
82
|
+
var annot = {
|
83
|
+
type: node.nodeName,
|
84
|
+
id: node.getAttribute('ANNOTATION_ID'),
|
85
|
+
ref: node.getAttribute('ANNOTATION_REF'),
|
86
|
+
value: node.querySelector('ANNOTATION_VALUE')
|
87
|
+
.textContent.trim()
|
88
|
+
};
|
89
|
+
|
90
|
+
if (this.Types.ALIGNABLE_ANNOTATION == annot.type) {
|
91
|
+
// Add start & end to alignable annotation
|
92
|
+
annot.start = timeOrder[node.getAttribute('TIME_SLOT_REF1')];
|
93
|
+
annot.end = timeOrder[node.getAttribute('TIME_SLOT_REF2')];
|
94
|
+
|
95
|
+
// Add to the list of alignable annotations
|
96
|
+
data.alignableAnnotations.push(annot);
|
97
|
+
}
|
98
|
+
|
99
|
+
// Additionally, put into the flat map of all annotations
|
100
|
+
data.annotations[annot.id] = annot;
|
101
|
+
|
102
|
+
return annot;
|
103
|
+
}, this
|
104
|
+
)
|
105
|
+
};
|
106
|
+
}, this);
|
107
|
+
|
108
|
+
// Create JavaScript references between annotations
|
109
|
+
data.tiers.forEach(function (tier) {
|
110
|
+
tier.annotations.forEach(function (annot) {
|
111
|
+
if (null != annot.ref) {
|
112
|
+
annot.reference = data.annotations[annot.ref];
|
113
|
+
}
|
114
|
+
}, this);
|
115
|
+
}, this);
|
116
|
+
|
117
|
+
// Sort alignable annotations by start & end
|
118
|
+
data.alignableAnnotations.sort(function (a, b) {
|
119
|
+
var d = a.start - b.start;
|
120
|
+
if (d == 0) {
|
121
|
+
d = b.end - a.end;
|
122
|
+
}
|
123
|
+
return d;
|
124
|
+
});
|
125
|
+
|
126
|
+
data.length = data.alignableAnnotations.length;
|
127
|
+
|
128
|
+
return data;
|
129
|
+
},
|
130
|
+
|
131
|
+
render: function () {
|
132
|
+
// apply tiers filter
|
133
|
+
var tiers = this.data.tiers;
|
134
|
+
if (this.params.tiers) {
|
135
|
+
tiers = tiers.filter(function (tier) {
|
136
|
+
return tier.id in this.params.tiers;
|
137
|
+
}, this);
|
138
|
+
}
|
139
|
+
|
140
|
+
// denormalize references to alignable annotations
|
141
|
+
var backRefs = {};
|
142
|
+
var indeces = {};
|
143
|
+
tiers.forEach(function (tier, index) {
|
144
|
+
tier.annotations.forEach(function (annot) {
|
145
|
+
if (annot.reference &&
|
146
|
+
annot.reference.type == this.Types.ALIGNABLE_ANNOTATION) {
|
147
|
+
if (!(annot.reference.id in backRefs)) {
|
148
|
+
backRefs[annot.ref] = {};
|
149
|
+
}
|
150
|
+
backRefs[annot.ref][index] = annot;
|
151
|
+
indeces[index] = true;
|
152
|
+
}
|
153
|
+
}, this);
|
154
|
+
}, this);
|
155
|
+
indeces = Object.keys(indeces).sort();
|
156
|
+
|
157
|
+
this.renderedAlignable = this.data.alignableAnnotations.filter(
|
158
|
+
function (alignable) {
|
159
|
+
return backRefs[alignable.id];
|
160
|
+
}
|
161
|
+
);
|
162
|
+
|
163
|
+
// table
|
164
|
+
var table = document.createElement('table');
|
165
|
+
table.className = 'wavesurfer-annotations';
|
166
|
+
|
167
|
+
// head
|
168
|
+
var thead = document.createElement('thead');
|
169
|
+
var headRow = document.createElement('tr');
|
170
|
+
thead.appendChild(headRow);
|
171
|
+
table.appendChild(thead);
|
172
|
+
var th = document.createElement('th');
|
173
|
+
th.textContent = 'Time';
|
174
|
+
th.className = 'wavesurfer-time';
|
175
|
+
headRow.appendChild(th);
|
176
|
+
indeces.forEach(function (index) {
|
177
|
+
var tier = tiers[index];
|
178
|
+
var th = document.createElement('th');
|
179
|
+
th.className = 'wavesurfer-tier-' + tier.id;
|
180
|
+
th.textContent = tier.id;
|
181
|
+
th.style.width = this.params.tiers[tier.id];
|
182
|
+
headRow.appendChild(th);
|
183
|
+
}, this);
|
184
|
+
|
185
|
+
// body
|
186
|
+
var tbody = document.createElement('tbody');
|
187
|
+
table.appendChild(tbody);
|
188
|
+
this.renderedAlignable.forEach(function (alignable) {
|
189
|
+
var row = document.createElement('tr');
|
190
|
+
row.id = 'wavesurfer-alignable-' + alignable.id;
|
191
|
+
tbody.appendChild(row);
|
192
|
+
|
193
|
+
var td = document.createElement('td');
|
194
|
+
td.className = 'wavesurfer-time';
|
195
|
+
td.textContent = alignable.start.toFixed(1) + '–' +
|
196
|
+
alignable.end.toFixed(1);
|
197
|
+
row.appendChild(td);
|
198
|
+
|
199
|
+
var backRef = backRefs[alignable.id];
|
200
|
+
indeces.forEach(function (index) {
|
201
|
+
var tier = tiers[index];
|
202
|
+
var td = document.createElement('td');
|
203
|
+
var annotation = backRef[index];
|
204
|
+
if (annotation) {
|
205
|
+
td.id = 'wavesurfer-annotation-' + annotation.id;
|
206
|
+
td.dataset.ref = alignable.id;
|
207
|
+
td.dataset.start = alignable.start;
|
208
|
+
td.dataset.end = alignable.end;
|
209
|
+
td.textContent = annotation.value;
|
210
|
+
}
|
211
|
+
td.className = 'wavesurfer-tier-' + tier.id;
|
212
|
+
row.appendChild(td);
|
213
|
+
}, this);
|
214
|
+
}, this);
|
215
|
+
|
216
|
+
this.container.innerHTML = '';
|
217
|
+
this.container.appendChild(table);
|
218
|
+
},
|
219
|
+
|
220
|
+
bindClick: function () {
|
221
|
+
var my = this;
|
222
|
+
this.container.addEventListener('click', function (e) {
|
223
|
+
var ref = e.target.dataset.ref;
|
224
|
+
if (null != ref) {
|
225
|
+
var annot = my.data.annotations[ref];
|
226
|
+
if (annot) {
|
227
|
+
my.fireEvent('select', annot.start, annot.end);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
});
|
231
|
+
},
|
232
|
+
|
233
|
+
getRenderedAnnotation: function (time) {
|
234
|
+
var result;
|
235
|
+
this.renderedAlignable.some(function (annotation) {
|
236
|
+
if (annotation.start <= time && annotation.end >= time) {
|
237
|
+
result = annotation;
|
238
|
+
return true;
|
239
|
+
}
|
240
|
+
return false;
|
241
|
+
});
|
242
|
+
return result;
|
243
|
+
},
|
244
|
+
|
245
|
+
getAnnotationNode: function (annotation) {
|
246
|
+
return document.getElementById(
|
247
|
+
'wavesurfer-alignable-' + annotation.id
|
248
|
+
);
|
249
|
+
}
|
250
|
+
};
|
251
|
+
|
252
|
+
WaveSurfer.util.extend(WaveSurfer.ELAN, WaveSurfer.Observer);
|
@@ -0,0 +1,173 @@
|
|
1
|
+
(function (root, factory) {
|
2
|
+
if (typeof define === 'function' && define.amd) {
|
3
|
+
define(['wavesurfer'], factory);
|
4
|
+
} else {
|
5
|
+
root.WaveSurfer.Microphone = factory(root.WaveSurfer);
|
6
|
+
}
|
7
|
+
}(this, function (WaveSurfer) {
|
8
|
+
'use strict';
|
9
|
+
|
10
|
+
WaveSurfer.Microphone = {
|
11
|
+
init: function (params) {
|
12
|
+
this.params = params;
|
13
|
+
|
14
|
+
var wavesurfer = this.wavesurfer = params.wavesurfer;
|
15
|
+
|
16
|
+
if (!this.wavesurfer) {
|
17
|
+
throw new Error('No WaveSurfer instance provided');
|
18
|
+
}
|
19
|
+
|
20
|
+
this.active = false;
|
21
|
+
this.paused = false;
|
22
|
+
|
23
|
+
// cross-browser getUserMedia
|
24
|
+
this.getUserMedia = (
|
25
|
+
navigator.getUserMedia ||
|
26
|
+
navigator.webkitGetUserMedia ||
|
27
|
+
navigator.mozGetUserMedia ||
|
28
|
+
navigator.msGetUserMedia
|
29
|
+
).bind(navigator);
|
30
|
+
|
31
|
+
// The buffer size in units of sample-frames.
|
32
|
+
// If specified, the bufferSize must be one of the following values:
|
33
|
+
// 256, 512, 1024, 2048, 4096, 8192, 16384. Defaults to 4096.
|
34
|
+
this.bufferSize = this.params.bufferSize || 4096;
|
35
|
+
|
36
|
+
// Integer specifying the number of channels for this node's input,
|
37
|
+
// defaults to 1. Values of up to 32 are supported.
|
38
|
+
this.numberOfInputChannels = this.params.numberOfInputChannels || 1;
|
39
|
+
|
40
|
+
// Integer specifying the number of channels for this node's output,
|
41
|
+
// defaults to 1. Values of up to 32 are supported.
|
42
|
+
this.numberOfOutputChannels = this.params.numberOfOutputChannels || 1;
|
43
|
+
|
44
|
+
// wavesurfer's AudioContext where we'll route the mic signal to
|
45
|
+
this.micContext = this.wavesurfer.backend.getAudioContext();
|
46
|
+
},
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Allow user to select audio input device, eg. microphone, and
|
50
|
+
* start the visualization.
|
51
|
+
*/
|
52
|
+
start: function() {
|
53
|
+
this.getUserMedia({
|
54
|
+
video: false,
|
55
|
+
audio: true
|
56
|
+
},
|
57
|
+
this.gotStream.bind(this),
|
58
|
+
this.deviceError.bind(this));
|
59
|
+
},
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Pause/resume visualization.
|
63
|
+
*/
|
64
|
+
togglePlay: function() {
|
65
|
+
if (!this.active) {
|
66
|
+
// start it first
|
67
|
+
this.start();
|
68
|
+
} else {
|
69
|
+
// toggle paused
|
70
|
+
this.paused = !this.paused;
|
71
|
+
|
72
|
+
if (this.paused) {
|
73
|
+
// disconnect sources so they can be used elsewhere
|
74
|
+
// (eg. during audio playback)
|
75
|
+
this.disconnect();
|
76
|
+
} else {
|
77
|
+
// resume visualization
|
78
|
+
this.connect();
|
79
|
+
}
|
80
|
+
}
|
81
|
+
},
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Stop the microphone and visualization.
|
85
|
+
*/
|
86
|
+
stop: function() {
|
87
|
+
if (this.active) {
|
88
|
+
this.active = false;
|
89
|
+
|
90
|
+
if (this.stream) {
|
91
|
+
this.stream.stop();
|
92
|
+
}
|
93
|
+
this.disconnect();
|
94
|
+
this.wavesurfer.empty();
|
95
|
+
}
|
96
|
+
},
|
97
|
+
|
98
|
+
/**
|
99
|
+
* Connect the media sources that feed the visualization.
|
100
|
+
*/
|
101
|
+
connect: function() {
|
102
|
+
if (this.stream !== undefined) {
|
103
|
+
// Create an AudioNode from the stream.
|
104
|
+
this.mediaStreamSource = this.micContext.createMediaStreamSource(this.stream);
|
105
|
+
|
106
|
+
this.levelChecker = this.micContext.createScriptProcessor(
|
107
|
+
this.bufferSize, this.numberOfInputChannels, this.numberOfOutputChannels);
|
108
|
+
this.mediaStreamSource.connect(this.levelChecker);
|
109
|
+
|
110
|
+
this.levelChecker.connect(this.micContext.destination);
|
111
|
+
this.levelChecker.onaudioprocess = this.reloadBuffer.bind(this);
|
112
|
+
}
|
113
|
+
},
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Disconnect the media sources that feed the visualization.
|
117
|
+
*/
|
118
|
+
disconnect: function() {
|
119
|
+
if (this.mediaStreamSource !== undefined) {
|
120
|
+
this.mediaStreamSource.disconnect();
|
121
|
+
}
|
122
|
+
|
123
|
+
if (this.levelChecker !== undefined) {
|
124
|
+
this.levelChecker.disconnect();
|
125
|
+
}
|
126
|
+
},
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Redraw the waveform.
|
130
|
+
*/
|
131
|
+
reloadBuffer: function(event) {
|
132
|
+
if (!this.paused) {
|
133
|
+
this.wavesurfer.empty();
|
134
|
+
this.wavesurfer.loadDecodedBuffer(event.inputBuffer);
|
135
|
+
}
|
136
|
+
},
|
137
|
+
|
138
|
+
/**
|
139
|
+
* Audio input device is ready.
|
140
|
+
*
|
141
|
+
* @param {LocalMediaStream} stream: the microphone's media stream.
|
142
|
+
*/
|
143
|
+
gotStream: function(stream) {
|
144
|
+
this.stream = stream;
|
145
|
+
this.active = true;
|
146
|
+
|
147
|
+
this.connect();
|
148
|
+
|
149
|
+
// notify listeners
|
150
|
+
this.fireEvent('deviceReady', stream);
|
151
|
+
},
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Destroy the microphone plugin.
|
155
|
+
*/
|
156
|
+
destroy: function(event) {
|
157
|
+
this.stop();
|
158
|
+
},
|
159
|
+
|
160
|
+
/**
|
161
|
+
* Device error callback.
|
162
|
+
*/
|
163
|
+
deviceError: function(code) {
|
164
|
+
// notify listeners
|
165
|
+
this.fireEvent('deviceError', code);
|
166
|
+
}
|
167
|
+
|
168
|
+
};
|
169
|
+
|
170
|
+
WaveSurfer.util.extend(WaveSurfer.Microphone, WaveSurfer.Observer);
|
171
|
+
|
172
|
+
return WaveSurfer.Microphone;
|
173
|
+
}));
|
@@ -0,0 +1,200 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/* Minimap */
|
4
|
+
WaveSurfer.Minimap = WaveSurfer.util.extend({}, WaveSurfer.Drawer, WaveSurfer.Drawer.Canvas, {
|
5
|
+
init: function (wavesurfer, params) {
|
6
|
+
this.wavesurfer = wavesurfer;
|
7
|
+
this.container = this.wavesurfer.drawer.container;
|
8
|
+
this.lastPos = this.wavesurfer.drawer.lastPos;
|
9
|
+
this.params = wavesurfer.util.extend(
|
10
|
+
{}, this.wavesurfer.drawer.params, {
|
11
|
+
showRegions: false,
|
12
|
+
showOverview: false,
|
13
|
+
overviewBorderColor: 'green',
|
14
|
+
overviewBorderSize: 2
|
15
|
+
}, params, {
|
16
|
+
scrollParent: false,
|
17
|
+
fillParent: true
|
18
|
+
}
|
19
|
+
);
|
20
|
+
|
21
|
+
this.width = 0;
|
22
|
+
this.height = this.params.height * this.params.pixelRatio;
|
23
|
+
|
24
|
+
this.createWrapper();
|
25
|
+
this.createElements();
|
26
|
+
|
27
|
+
if (WaveSurfer.Regions && this.params.showRegions) {
|
28
|
+
this.regions();
|
29
|
+
}
|
30
|
+
|
31
|
+
this.bindWaveSurferEvents();
|
32
|
+
this.bindMinimapEvents();
|
33
|
+
},
|
34
|
+
regions: function() {
|
35
|
+
var my = this;
|
36
|
+
this.regions = {};
|
37
|
+
|
38
|
+
this.wavesurfer.on('region-created', function(region) {
|
39
|
+
my.regions[region.id] = region;
|
40
|
+
my.renderRegions();
|
41
|
+
});
|
42
|
+
|
43
|
+
this.wavesurfer.on('region-updated', function(region) {
|
44
|
+
my.regions[region.id] = region;
|
45
|
+
my.renderRegions();
|
46
|
+
});
|
47
|
+
|
48
|
+
this.wavesurfer.on('region-removed', function(region) {
|
49
|
+
delete my.regions[region.id];
|
50
|
+
my.renderRegions();
|
51
|
+
});
|
52
|
+
},
|
53
|
+
renderRegions: function() {
|
54
|
+
var my = this;
|
55
|
+
var regionElements = this.wrapper.querySelectorAll('region');
|
56
|
+
for (var i = 0; i < regionElements.length; ++i) {
|
57
|
+
this.wrapper.removeChild(regionElements[i]);
|
58
|
+
}
|
59
|
+
|
60
|
+
Object.keys(this.regions).forEach(function(id){
|
61
|
+
var region = my.regions[id];
|
62
|
+
var width = (my.width * ((region.end - region.start) / my.wavesurfer.getDuration()));
|
63
|
+
var left = (my.width * (region.start / my.wavesurfer.getDuration()));
|
64
|
+
var regionElement = my.style(document.createElement('region'), {
|
65
|
+
height: 'inherit',
|
66
|
+
backgroundColor: region.color,
|
67
|
+
width: width + 'px',
|
68
|
+
left: left + 'px',
|
69
|
+
display: 'block',
|
70
|
+
position: 'absolute'
|
71
|
+
});
|
72
|
+
regionElement.classList.add(id);
|
73
|
+
my.wrapper.appendChild(regionElement);
|
74
|
+
});
|
75
|
+
},
|
76
|
+
createElements: function() {
|
77
|
+
WaveSurfer.Drawer.Canvas.createElements.call(this);
|
78
|
+
|
79
|
+
if (this.params.showOverview) {
|
80
|
+
this.overviewRegion = this.style(document.createElement('overview'), {
|
81
|
+
height: (this.wrapper.offsetHeight - (this.params.overviewBorderSize * 2)) + 'px',
|
82
|
+
width: '0px',
|
83
|
+
display: 'block',
|
84
|
+
position: 'absolute',
|
85
|
+
cursor: 'move',
|
86
|
+
border: this.params.overviewBorderSize + 'px solid ' + this.params.overviewBorderColor,
|
87
|
+
zIndex: 2,
|
88
|
+
opacity: this.params.overviewOpacity
|
89
|
+
});
|
90
|
+
|
91
|
+
this.wrapper.appendChild(this.overviewRegion);
|
92
|
+
}
|
93
|
+
},
|
94
|
+
|
95
|
+
bindWaveSurferEvents: function () {
|
96
|
+
var my = this;
|
97
|
+
this.wavesurfer.on('ready', this.render.bind(this));
|
98
|
+
this.wavesurfer.on('audioprocess', function (currentTime) {
|
99
|
+
my.progress(my.wavesurfer.backend.getPlayedPercents());
|
100
|
+
});
|
101
|
+
this.wavesurfer.on('seek', function(progress) {
|
102
|
+
my.progress(my.wavesurfer.backend.getPlayedPercents());
|
103
|
+
});
|
104
|
+
|
105
|
+
if (this.params.showOverview) {
|
106
|
+
this.wavesurfer.on('scroll', function(event) {
|
107
|
+
if (!my.draggingOverview) {
|
108
|
+
my.moveOverviewRegion(event.target.scrollLeft / my.ratio);
|
109
|
+
}
|
110
|
+
});
|
111
|
+
|
112
|
+
this.wavesurfer.drawer.wrapper.addEventListener('mouseover', function(event) {
|
113
|
+
if (my.draggingOverview) {
|
114
|
+
my.draggingOverview = false;
|
115
|
+
}
|
116
|
+
});
|
117
|
+
}
|
118
|
+
|
119
|
+
this.wavesurfer.on('destroy', this.destroy.bind(this));
|
120
|
+
},
|
121
|
+
|
122
|
+
bindMinimapEvents: function () {
|
123
|
+
var my = this;
|
124
|
+
var relativePositionX = 0;
|
125
|
+
var seek = true;
|
126
|
+
var positionMouseDown = {
|
127
|
+
clientX: 0,
|
128
|
+
clientY: 0
|
129
|
+
};
|
130
|
+
|
131
|
+
this.on('click', (function (e, position) {
|
132
|
+
if (seek) {
|
133
|
+
this.progress(position);
|
134
|
+
this.wavesurfer.seekAndCenter(position);
|
135
|
+
} else {
|
136
|
+
seek = true;
|
137
|
+
}
|
138
|
+
}).bind(this));
|
139
|
+
|
140
|
+
if (this.params.showOverview) {
|
141
|
+
this.overviewRegion.addEventListener('mousedown', function(event) {
|
142
|
+
my.draggingOverview = true;
|
143
|
+
relativePositionX = event.layerX;
|
144
|
+
positionMouseDown.clientX = event.clientX;
|
145
|
+
positionMouseDown.clientY = event.clientY;
|
146
|
+
});
|
147
|
+
|
148
|
+
this.wrapper.addEventListener('mousemove', function(event) {
|
149
|
+
if(my.draggingOverview) {
|
150
|
+
my.moveOverviewRegion(event.clientX - my.container.getBoundingClientRect().left - relativePositionX);
|
151
|
+
}
|
152
|
+
});
|
153
|
+
|
154
|
+
this.wrapper.addEventListener('mouseup', function(event) {
|
155
|
+
if (positionMouseDown.clientX - event.clientX === 0 && positionMouseDown.clientX - event.clientX === 0) {
|
156
|
+
seek = true;
|
157
|
+
my.draggingOverview = false;
|
158
|
+
} else if (my.draggingOverview) {
|
159
|
+
seek = false;
|
160
|
+
my.draggingOverview = false;
|
161
|
+
}
|
162
|
+
});
|
163
|
+
}
|
164
|
+
},
|
165
|
+
|
166
|
+
render: function () {
|
167
|
+
var len = this.getWidth();
|
168
|
+
var peaks = this.wavesurfer.backend.getPeaks(len);
|
169
|
+
this.drawPeaks(peaks, len);
|
170
|
+
|
171
|
+
if (this.params.showOverview) {
|
172
|
+
//get proportional width of overview region considering the respective
|
173
|
+
//width of the drawers
|
174
|
+
this.ratio = this.wavesurfer.drawer.width / this.width;
|
175
|
+
this.waveShowedWidth = this.wavesurfer.drawer.width / this.ratio;
|
176
|
+
this.waveWidth = this.wavesurfer.drawer.width;
|
177
|
+
this.overviewWidth = (this.width / this.ratio);
|
178
|
+
this.overviewPosition = 0;
|
179
|
+
this.overviewRegion.style.width = (this.overviewWidth - (this.params.overviewBorderSize * 2)) + 'px';
|
180
|
+
}
|
181
|
+
},
|
182
|
+
moveOverviewRegion: function(pixels) {
|
183
|
+
if (pixels < 0) {
|
184
|
+
this.overviewPosition = 0;
|
185
|
+
} else if (pixels + this.overviewWidth < this.width) {
|
186
|
+
this.overviewPosition = pixels;
|
187
|
+
} else {
|
188
|
+
this.overviewPosition = (this.width - this.overviewWidth);
|
189
|
+
}
|
190
|
+
this.overviewRegion.style.left = this.overviewPosition + 'px';
|
191
|
+
this.wavesurfer.drawer.wrapper.scrollLeft = this.overviewPosition * this.ratio;
|
192
|
+
}
|
193
|
+
});
|
194
|
+
|
195
|
+
|
196
|
+
WaveSurfer.initMinimap = function (params) {
|
197
|
+
var map = Object.create(WaveSurfer.Minimap);
|
198
|
+
map.init(this, params);
|
199
|
+
return map;
|
200
|
+
};
|