wavesurfer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
};
|