source: gs3-extensions/mars-src/trunk/src/wavesurfer-renderer/drawer.spectrummulticanvas.js@ 35193

Last change on this file since 35193 was 35193, checked in by davidb, 3 years ago

NaN was occuring on some computed values. This was eventually traced to the JSON retrieved via AJAX return an array of string values. Now changed to be Number format in AJAX callback

File size: 23.5 KB
Line 
1import MultiCanvas from './drawer.multicanvas';
2import * as util from './util';
3import CanvasEntry from './drawer.canvasentry';
4
5/**
6 * Calculate FFT - Based on https://github.com/corbanbrook/dsp.js
7 */
8/* eslint-disable complexity, no-redeclare, no-var, one-var */
9const FFT = function(bufferSize, sampleRate, windowFunc, alpha) {
10 this.bufferSize = bufferSize;
11 this.sampleRate = sampleRate;
12 this.bandwidth = (2 / bufferSize) * (sampleRate / 2);
13
14 this.sinTable = new Float32Array(bufferSize);
15 this.cosTable = new Float32Array(bufferSize);
16 this.windowValues = new Float32Array(bufferSize);
17 this.reverseTable = new Uint32Array(bufferSize);
18
19 this.peakBand = 0;
20 this.peak = 0;
21
22 var i;
23 switch (windowFunc) {
24 case 'bartlett':
25 for (i = 0; i < bufferSize; i++) {
26 this.windowValues[i] =
27 (2 / (bufferSize - 1)) *
28 ((bufferSize - 1) / 2 - Math.abs(i - (bufferSize - 1) / 2));
29 }
30 break;
31 case 'bartlettHann':
32 for (i = 0; i < bufferSize; i++) {
33 this.windowValues[i] =
34 0.62 -
35 0.48 * Math.abs(i / (bufferSize - 1) - 0.5) -
36 0.38 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1));
37 }
38 break;
39 case 'blackman':
40 alpha = alpha || 0.16;
41 for (i = 0; i < bufferSize; i++) {
42 this.windowValues[i] =
43 (1 - alpha) / 2 -
44 0.5 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1)) +
45 (alpha / 2) *
46 Math.cos((4 * Math.PI * i) / (bufferSize - 1));
47 }
48 break;
49 case 'cosine':
50 for (i = 0; i < bufferSize; i++) {
51 this.windowValues[i] = Math.cos(
52 (Math.PI * i) / (bufferSize - 1) - Math.PI / 2
53 );
54 }
55 break;
56 case 'gauss':
57 alpha = alpha || 0.25;
58 for (i = 0; i < bufferSize; i++) {
59 this.windowValues[i] = Math.pow(
60 Math.E,
61 -0.5 *
62 Math.pow(
63 (i - (bufferSize - 1) / 2) /
64 ((alpha * (bufferSize - 1)) / 2),
65 2
66 )
67 );
68 }
69 break;
70 case 'hamming':
71 for (i = 0; i < bufferSize; i++) {
72 this.windowValues[i] =
73 0.54 -
74 0.46 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1));
75 }
76 break;
77 case 'hann':
78 case undefined:
79 for (i = 0; i < bufferSize; i++) {
80 this.windowValues[i] =
81 0.5 * (1 - Math.cos((Math.PI * 2 * i) / (bufferSize - 1)));
82 }
83 break;
84 case 'lanczoz':
85 for (i = 0; i < bufferSize; i++) {
86 this.windowValues[i] =
87 Math.sin(Math.PI * ((2 * i) / (bufferSize - 1) - 1)) /
88 (Math.PI * ((2 * i) / (bufferSize - 1) - 1));
89 }
90 break;
91 case 'rectangular':
92 for (i = 0; i < bufferSize; i++) {
93 this.windowValues[i] = 1;
94 }
95 break;
96 case 'triangular':
97 for (i = 0; i < bufferSize; i++) {
98 this.windowValues[i] =
99 (2 / bufferSize) *
100 (bufferSize / 2 - Math.abs(i - (bufferSize - 1) / 2));
101 }
102 break;
103 default:
104 throw Error("No such window function '" + windowFunc + "'");
105 }
106
107 var limit = 1;
108 var bit = bufferSize >> 1;
109 var i;
110
111 while (limit < bufferSize) {
112 for (i = 0; i < limit; i++) {
113 this.reverseTable[i + limit] = this.reverseTable[i] + bit;
114 }
115
116 limit = limit << 1;
117 bit = bit >> 1;
118 }
119
120 for (i = 0; i < bufferSize; i++) {
121 this.sinTable[i] = Math.sin(-Math.PI / i);
122 this.cosTable[i] = Math.cos(-Math.PI / i);
123 }
124
125 this.calculateSpectrum = function(buffer) {
126 // Locally scope variables for speed up
127 var bufferSize = this.bufferSize,
128 cosTable = this.cosTable,
129 sinTable = this.sinTable,
130 reverseTable = this.reverseTable,
131 real = new Float32Array(bufferSize),
132 imag = new Float32Array(bufferSize),
133 bSi = 2 / this.bufferSize,
134 sqrt = Math.sqrt,
135 rval,
136 ival,
137 mag,
138 spectrum = new Float32Array(bufferSize / 2);
139
140 var k = Math.floor(Math.log(bufferSize) / Math.LN2);
141
142 if (Math.pow(2, k) !== bufferSize) {
143 throw 'Invalid buffer size, must be a power of 2.';
144 }
145 if (bufferSize !== buffer.length) {
146 throw 'Supplied buffer is not the same size as defined FFT. FFT Size: ' +
147 bufferSize +
148 ' Buffer Size: ' +
149 buffer.length;
150 }
151
152 var halfSize = 1,
153 phaseShiftStepReal,
154 phaseShiftStepImag,
155 currentPhaseShiftReal,
156 currentPhaseShiftImag,
157 off,
158 tr,
159 ti,
160 tmpReal;
161
162 for (var i = 0; i < bufferSize; i++) {
163 real[i] =
164 buffer[reverseTable[i]] * this.windowValues[reverseTable[i]];
165 imag[i] = 0;
166 }
167
168 while (halfSize < bufferSize) {
169 phaseShiftStepReal = cosTable[halfSize];
170 phaseShiftStepImag = sinTable[halfSize];
171
172 currentPhaseShiftReal = 1;
173 currentPhaseShiftImag = 0;
174
175 for (var fftStep = 0; fftStep < halfSize; fftStep++) {
176 var i = fftStep;
177
178 while (i < bufferSize) {
179 off = i + halfSize;
180 tr =
181 currentPhaseShiftReal * real[off] -
182 currentPhaseShiftImag * imag[off];
183 ti =
184 currentPhaseShiftReal * imag[off] +
185 currentPhaseShiftImag * real[off];
186
187 real[off] = real[i] - tr;
188 imag[off] = imag[i] - ti;
189 real[i] += tr;
190 imag[i] += ti;
191
192 i += halfSize << 1;
193 }
194
195 tmpReal = currentPhaseShiftReal;
196 currentPhaseShiftReal =
197 tmpReal * phaseShiftStepReal -
198 currentPhaseShiftImag * phaseShiftStepImag;
199 currentPhaseShiftImag =
200 tmpReal * phaseShiftStepImag +
201 currentPhaseShiftImag * phaseShiftStepReal;
202 }
203
204 halfSize = halfSize << 1;
205 }
206
207 for (var i = 0, N = bufferSize / 2; i < N; i++) {
208 rval = real[i];
209 ival = imag[i];
210 mag = bSi * sqrt(rval * rval + ival * ival);
211
212 if (mag > this.peak) {
213 this.peakBand = i;
214 this.peak = mag;
215 }
216 spectrum[i] = mag;
217 }
218 return spectrum;
219 };
220};
221/* eslint-enable complexity, no-redeclare, no-var, one-var */
222
223
224/**
225 * Experimental SpectrumMultiCanvas renderer for wavesurfer.
226 *
227 * A `SpectrumMultiCanvas` consists of one or more `CanvasEntry` instances, depending
228 * on the zoom level.
229 */
230export default class SpectrumMultiCanvas extends MultiCanvas {
231 /**
232 * @param {HTMLElement} container The container node of the wavesurfer instance
233 * @param {WavesurferParams} params The wavesurfer initialisation options
234 */
235 constructor(container, params) {
236 super(container, params);
237
238 if (params.colorMap) {
239 if (params.colorMap.length < 256) {
240 throw new Error('Colormap must contain 256 elements');
241 }
242 for (let i = 0; i < params.colorMap.length; i++) {
243 const cmEntry = params.colorMap[i];
244 if ((cmEntry.length !== 4) && (cmEntry.length !== 3)) {
245 throw new Error(
246 'ColorMap entries must contain 3 (rgb) or 4 (rgba) values'
247 );
248 }
249 }
250 this.colorMap = params.colorMap;
251 } else {
252 this.colorMap = [];
253 for (let i = 0; i < 256; i++) {
254 const val = (255 - i) / 256;
255 this.colorMap.push([val, val, val, 1]);
256 }
257 }
258
259 if (params.avDataUrl) {
260 this.avDataUrl = params.avDataUrl;
261 }
262 }
263
264 /**
265 * Initialize the drawer
266 */
267 init() {
268 super.init();
269
270 if (this.avDataUrl) {
271 this.loadFrequenciesData(this.avDataUrl);
272 } else {
273 console.error("No Arousal+Valence (AV) Data URL provided");
274 }
275 }
276
277 normaliseAVVals(vals)
278 {
279 var norm_vals = new Array(vals.length);
280
281 var max_val = 0;
282 for (var i=0; i<vals.length; i++) {
283 var abs_val = Math.abs(vals[i]);
284 if (abs_val > max_val) {
285 max_val = abs_val;
286 }
287 }
288
289 var scale_factor = (max_val < 0.8) ? 0.8 : max_val;
290
291 for (var i=0; i<vals.length; i++) {
292 var val = vals[i];
293 var norm_val = scale_factor * val / max_val;
294 norm_vals[i] = norm_val;
295 }
296
297 return norm_vals;
298 }
299
300 createAVProgressTimelineData(arousal_vals,valence_vals, my)
301 {
302 //console.log("**** createAVProgressTimelineData");
303 var canvas_width = this.canvases[0].wave.width;
304 //console.log("**** canvas width = " + canvas_width);
305
306 //console.log(" arousal_val = " + JSON.stringify(arousal_vals));
307 //console.log("this.arousal_val = " + JSON.stringify(this.arousal_vals));
308
309 //this.arousal_vals = arousal_vals;
310 //this.valence_vals = valence_vals;
311
312 this.arousal_vals.unshift(0);
313 this.valence_vals.unshift(0);
314
315 this.norm_arousal_vals = this.normaliseAVVals(this.arousal_vals);
316 this.norm_valence_vals = this.normaliseAVVals(this.valence_vals);
317
318 const time_slice = 6; // 6 secs
319 const frame_overlap = 3; // 3 secs
320
321 this.timeline_steps = new Array();
322 this.timeline_steps.unshift(0);
323
324 var num_vals = this.arousal_vals.length;
325 var t = time_slice;
326 var n = 1;
327
328 while (n<num_vals) {
329 this.timeline_steps[n] = t;
330 t += frame_overlap;
331 n++;
332 }
333 const total_duration = t;
334 //console.log("*** n = " + n);
335 //console.log("*** total duration = " + total_duration);
336
337 this.timeline_steps[n] = total_duration;
338 this.arousal_vals[n] = 0;
339 this.valence_vals[n] = 0;
340 this.norm_arousal_vals[n] = 0;
341 this.norm_valence_vals[n] = 0;
342 num_vals++;
343
344 this.arousal_progress_timeline = new Array();
345 this.valence_progress_timeline = new Array();
346
347 this.norm_arousal_progress_timeline = new Array();
348 this.norm_valence_progress_timeline = new Array();
349
350 for (var i=1; i<num_vals; i++) {
351 const start_t = this.timeline_steps[i-1];
352 const end_t = this.timeline_steps[i];
353 const start_ts = Math.round((start_t / total_duration) * canvas_width);
354 const end_ts = Math.round((end_t / total_duration) * canvas_width);
355
356 const start_arousal = this.arousal_vals[i-1];
357 const start_valence = this.valence_vals[i-1];
358 const end_arousal = this.arousal_vals[i];
359 const end_valence = this.valence_vals[i];
360
361 const norm_start_arousal = this.norm_arousal_vals[i-1];
362 const norm_start_valence = this.norm_valence_vals[i-1];
363 const norm_end_arousal = this.norm_arousal_vals[i];
364 const norm_end_valence = this.norm_valence_vals[i];
365
366 const ts_diff = end_ts - start_ts;
367 const arousal_diff = end_arousal - start_arousal;
368 const valence_diff = end_valence - start_valence;
369 const norm_arousal_diff = norm_end_arousal - norm_start_arousal;
370 const norm_valence_diff = norm_end_valence - norm_start_valence;
371
372 var local_ts = 0;
373 //console.log("*** start_ts = " + start_ts + ", end_ts = " + end_ts + " (ts_diff = " + ts_diff +")");
374 //console.log("*** start_arousal = " + start_arousal + ", end_arousal = " + end_arousal);
375 //console.log("*** norm_start_arousal = " + norm_start_arousal + ", norm_end_arousal = " + norm_end_arousal);
376
377 for (var ts=start_ts; ts<end_ts; ts++) {
378 var local_proportion = local_ts / ts_diff;
379 var interpolated_arousal = start_arousal + (local_proportion * arousal_diff);
380 var interpolated_valence = start_valence + (local_proportion * valence_diff);
381 var norm_interpolated_arousal = norm_start_arousal + (local_proportion * norm_arousal_diff);
382 var norm_interpolated_valence = norm_start_valence + (local_proportion * norm_valence_diff);
383
384 this.arousal_progress_timeline[ts] = interpolated_arousal;
385 this.valence_progress_timeline[ts] = interpolated_valence;
386
387 this.norm_arousal_progress_timeline[ts] = norm_interpolated_arousal;
388 this.norm_valence_progress_timeline[ts] = norm_interpolated_valence;
389
390 local_ts++;
391 }
392 }
393
394 //console.log(this);
395 console.log("Generated interpolated AV progress timeline");
396 }
397
398 loadFrequenciesData(url) {
399 //var that = this;
400
401 const request = this.wavesurfer.util.fetchFile({ url: url });
402
403 request.on('success', data => {
404 console.log("loadFrequenceisData: Retrieved AV URL data");
405 console.log(data);
406 //console.log("*** this = ");
407 //console.log(this);
408 //console.log("*** that = ");
409 //console.log(that);
410 //this.arousal_vals = data.arousal.slice(); // **** slice() does array copy
411 //this.valence_vals = data.valence.slice(); // **** slice() does array copy
412
413 // The following two lines use map() to both:
414 // convert the JSON string vals to numbers
415 // generate a fresh array of values (rather than a shared ref) which is what we want
416 this.arousal_vals = data.arousal.map((v) => Number(v));
417 this.valence_vals = data.valence.map((v) => Number(v));
418
419 //this.createAVProgressTimelineData(arousal_vals, valence_vals, this); // **** need to pass in 'this' ??
420 });
421
422 request.on('error', e => this.fireEvent('error', e));
423
424 return request;
425 }
426
427 /**
428 * Update cursor style
429 */
430
431 updateCursor() {
432 if (this.params.renderWave == 1) {
433 super.updateCursor();
434 }
435 else {
436 this.style(this.progressWave, {
437 //borderRightWidth: this.params.cursorSpectrumWidth + 'px',
438 //borderRightColor: this.params.cursorSpectrumColor
439 borderRightWidth: '4px',
440 borderRightColor: 'rgba(255,255,255,0.3)'
441 });
442 }
443 }
444
445
446
447 drawPeaks(peaks, length, start, end) {
448 if (this.params.renderWave == 1) {
449 super.drawPeaks(peaks,length,start,end);
450 if ($( "#av-display" ).length) {
451 $( "#av-display" ).show();
452 }
453 //this.createAVProgressTimelineData(this.arousal_vals, this.valence_vals, this); // **** need to pass in 'this' ??
454 }
455 else {
456 if (!this.setWidth(length)) {
457 this.clearWave();
458 }
459
460 this.getFrequencies(this.drawSpectrogram);
461 }
462 }
463
464 resample(oldMatrix) {
465 const columnsNumber = this.width;
466 const newMatrix = [];
467
468 const oldPiece = 1 / oldMatrix.length;
469 const newPiece = 1 / columnsNumber;
470 let i;
471
472 for (i = 0; i < columnsNumber; i++) {
473 const column = new Array(oldMatrix[0].length);
474 let j;
475
476 for (j = 0; j < oldMatrix.length; j++) {
477 const oldStart = j * oldPiece;
478 const oldEnd = oldStart + oldPiece;
479 const newStart = i * newPiece;
480 const newEnd = newStart + newPiece;
481
482 const overlap =
483 oldEnd <= newStart || newEnd <= oldStart
484 ? 0
485 : Math.min(
486 Math.max(oldEnd, newStart),
487 Math.max(newEnd, oldStart)
488 ) -
489 Math.max(
490 Math.min(oldEnd, newStart),
491 Math.min(newEnd, oldStart)
492 );
493 let k;
494 /* eslint-disable max-depth */
495 if (overlap > 0) {
496 for (k = 0; k < oldMatrix[0].length; k++) {
497 if (column[k] == null) {
498 column[k] = 0;
499 }
500 column[k] += (overlap / newPiece) * oldMatrix[j][k];
501 }
502 }
503 /* eslint-enable max-depth */
504 }
505
506 const intColumn = new Uint8Array(oldMatrix[0].length);
507 let m;
508
509 for (m = 0; m < oldMatrix[0].length; m++) {
510 intColumn[m] = column[m];
511 }
512
513 newMatrix.push(intColumn);
514 }
515
516 return newMatrix;
517 }
518
519 drawSpectrogram(frequenciesData, my) {
520 console.log("*** spectrummultican as::drawSpectrum() spec ....spec.length = " + frequenciesData.length)
521 console.log(frequenciesData);
522 //const spectrCc = my.spectrCc;
523 //const length = my.wavesurfer.backend.getDuration();
524 //const height = my.height;
525 //const pixels = my.resample(frequenciesData);
526 //const heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;
527
528 const canvas = my.canvases[0].wave;
529 const spectrCc = canvas.getContext('2d');
530 const length = my.wavesurfer.backend.getDuration();
531 const height = canvas.height;
532 const pixels = my.resample(frequenciesData);
533 const heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;
534
535 // now double it!
536 const scaledHeightFactor = heightFactor * 2;
537
538
539 let i;
540 let j;
541
542 for (i = 0; i < pixels.length; i++) {
543 for (j = 0; j < pixels[i].length; j++) {
544 const colorMap = my.colorMap[pixels[i][j]]; // ****
545 if (colorMap.length == 4) {
546 //my.spectrCc.fillStyle =
547 spectrCc.fillStyle =
548 'rgba(' +
549 colorMap[0] * 256 +
550 ', ' +
551 colorMap[1] * 256 +
552 ', ' +
553 colorMap[2] * 256 +
554 ',' +
555 colorMap[3] +
556 ')';
557 }
558 else {
559 //my.spectrCc.fillStyle =
560 spectrCc.fillStyle =
561 'rgb(' +
562 colorMap[0] * 256 +
563 ', ' +
564 colorMap[1] * 256 +
565 ', ' +
566 colorMap[2] * 256 +
567 ')';
568 }
569
570 //my.spectrCc.fillRect(
571 spectrCc.fillRect(
572 i,
573 height - j * scaledHeightFactor,
574 1,
575 scaledHeightFactor
576 );
577 }
578 }
579
580 my.createAVProgressTimelineData(my.arousal_vals, my.valence_vals, my); // **** need to pass in 'this' ??
581 }
582
583 getFrequencies(callback) {
584 const fftSamples = this.fftSamples || 512;
585 const buffer = (this.buffer = this.wavesurfer.backend.buffer);
586 if (buffer == null) return; // **** GS3 edit
587 const channelOne = buffer.getChannelData(0);
588 const bufferLength = buffer.length;
589 const sampleRate = buffer.sampleRate;
590 const frequencies = [];
591
592 if (!buffer) {
593 this.fireEvent('error', 'Web Audio buffer is not available');
594 return;
595 }
596
597 let noverlap = this.noverlap;
598 if (!noverlap) {
599 const uniqueSamplesPerPx = buffer.length / this.canvases[0].wave.width; // **** GS3 edit
600 noverlap = Math.max(0, Math.round(fftSamples - uniqueSamplesPerPx));
601 }
602
603 const fft = new FFT(
604 fftSamples,
605 sampleRate,
606 this.windowFunc,
607 this.alpha
608 );
609 const maxSlicesCount = Math.floor(
610 bufferLength / (fftSamples - noverlap)
611 );
612 let currentOffset = 0;
613
614 while (currentOffset + fftSamples < channelOne.length) {
615 const segment = channelOne.slice(
616 currentOffset,
617 currentOffset + fftSamples
618 );
619 const spectrum = fft.calculateSpectrum(segment);
620 const array = new Uint8Array(fftSamples / 2);
621 let j;
622 for (j = 0; j < fftSamples / 2; j++) {
623 array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);
624 }
625 frequencies.push(array);
626 currentOffset += fftSamples - noverlap;
627 }
628 callback(frequencies, this);
629 }
630
631
632 /**
633 * Draw a rectangle on the multi-canvas
634 *
635 * @param {number} x X-position of the rectangle
636 * @param {number} y Y-position of the rectangle
637 * @param {number} width Width of the rectangle
638 * @param {number} height Height of the rectangle
639 * @param {number} radius Radius of the rectangle
640 */
641 /*
642 fillRect(x, y, width, height, radius) {
643 const startCanvas = Math.floor(x / this.maxCanvasWidth);
644 const endCanvas = Math.min(
645 Math.ceil((x + width) / this.maxCanvasWidth) + 1,
646 this.canvases.length
647 );
648 let i = startCanvas;
649 for (i; i < endCanvas; i++) {
650 const entry = this.canvases[i];
651 const leftOffset = i * this.maxCanvasWidth;
652
653 const intersection = {
654 x1: Math.max(x, i * this.maxCanvasWidth),
655 y1: y,
656 x2: Math.min(
657 x + width,
658 i * this.maxCanvasWidth + entry.wave.width
659 ),
660 y2: y + height
661 };
662
663 if (intersection.x1 < intersection.x2) {
664 this.setFillStyles(entry);
665
666 entry.fillRects(
667 intersection.x1 - leftOffset,
668 intersection.y1,
669 intersection.x2 - intersection.x1,
670 intersection.y2 - intersection.y1,
671 radius
672 );
673 }
674 }
675 }
676 */
677
678
679 /**
680 * Render the new progress
681 *
682 * @param {number} position X-offset of progress position in pixels
683 */
684 /*
685 updateProgress(position) {
686 this.style(this.progressWave, { width: position + 'px' });
687 }
688 */
689
690 /**
691 * Render the new progress
692 *
693 * @param {number} position X-offset of progress position in pixels
694 */
695 updateProgress(position) {
696
697 if (!this.arousal_progress_timeline) {
698 this.createAVProgressTimelineData(this.arousal_vals, this.valence_vals, this); // **** need to pass in 'this' ??
699 }
700
701 if (this.params.renderWave == 1) {
702 super.updateProgress(position);
703 }
704 else {
705
706 var canvas_width = this.canvases[0].wave.width;
707 // ****
708 //console.log("position = " + position + "/" + canvas_width);
709 //console.log(this);
710
711 var norm_arousal_val = this.norm_arousal_progress_timeline[position];
712 var norm_valence_val = this.norm_valence_progress_timeline[position];
713
714 // ****
715 //console.log("position = " + position + ", arousal = " + arousal_val + ", valence = " + valence_val);
716
717 // shift [-1,1] scale
718 /*
719 var css_norm_valence_alpha = 0.5 + (norm_arousal_val + 1.0)/4.0;
720 var css_norm_arousal_width = (norm_valence_val + 1.0) * 20;
721
722 this.style(this.progressWave, {
723 borderRightWidth: css_norm_arousal_width+'px',
724 borderRightColor: 'rgba(255,255,255,'+css_norm_valence_alpha+')'
725 });
726*/
727
728
729 var css_norm_arousal_alpha = 0.5 + (norm_arousal_val + 1.0)/4.0;
730 var css_norm_valence_width = (norm_valence_val + 1.0) * 20;
731
732 this.style(this.progressWave, {
733 borderRightWidth: css_norm_valence_width+'px',
734 borderRightColor: 'rgba(255,255,255,'+css_norm_arousal_alpha+')'
735 });
736
737 super.updateProgress(position);
738 }
739
740 var arousal_val = this.arousal_progress_timeline[position];
741 var valence_val = this.valence_progress_timeline[position];
742
743 var arousal_val_3dp = Math.round(arousal_val*1000)/1000;
744 var valence_val_3dp = Math.round(valence_val*1000)/1000;
745
746 if (arousal_val_3dp >= 0) {
747 arousal_val_3dp = "&nbsp;" + arousal_val_3dp;
748 }
749
750 if (valence_val_3dp >= 0) {
751 valence_val_3dp = "&nbsp;" + valence_val_3dp;
752 }
753
754 if ($('#arousal-val').length) {
755 $('#arousal-val').html(arousal_val_3dp);
756 }
757 if ($('#valence-val').length) {
758 $('#valence-val').html(valence_val_3dp);
759 }
760
761 }
762
763}
Note: See TracBrowser for help on using the repository browser.