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

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

More careful processing of 'position' to array index

File size: 23.7 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 var floor_position = Math.floor(position);
702
703 if (this.params.renderWave == 1) {
704 super.updateProgress(position);
705 }
706 else {
707
708 var canvas_width = this.canvases[0].wave.width;
709 // ****
710 //console.log("position = " + position + "/" + canvas_width);
711 //console.log(this);
712
713 var norm_arousal_val = this.norm_arousal_progress_timeline[floor_position];
714 var norm_valence_val = this.norm_valence_progress_timeline[floor_position];
715
716 // ****
717 //console.log("floor_position = " + floor_position + ", arousal = " + arousal_val + ", valence = " + valence_val);
718
719 // shift [-1,1] scale
720 /*
721 var css_norm_valence_alpha = 0.5 + (norm_arousal_val + 1.0)/4.0;
722 var css_norm_arousal_width = (norm_valence_val + 1.0) * 20;
723
724 this.style(this.progressWave, {
725 borderRightWidth: css_norm_arousal_width+'px',
726 borderRightColor: 'rgba(255,255,255,'+css_norm_valence_alpha+')'
727 });
728*/
729
730
731 var css_norm_arousal_alpha = 0.5 + (norm_arousal_val + 1.0)/4.0;
732 var css_norm_valence_width = (norm_valence_val + 1.0) * 20;
733
734 this.style(this.progressWave, {
735 borderRightWidth: css_norm_valence_width+'px',
736 borderRightColor: 'rgba(255,255,255,'+css_norm_arousal_alpha+')'
737 });
738
739 super.updateProgress(position);
740 }
741
742 var arousal_val = this.arousal_progress_timeline[floor_position];
743 var valence_val = this.valence_progress_timeline[floor_position];
744
745 //console.log("*** arousal_val [" + floor_position + "]" + " = " + arousal_val);
746
747 var arousal_val_3dp = Math.round(arousal_val*1000)/1000;
748 var valence_val_3dp = Math.round(valence_val*1000)/1000;
749
750 if (arousal_val_3dp >= 0) {
751 arousal_val_3dp = "&nbsp;" + arousal_val_3dp;
752 }
753
754 if (valence_val_3dp >= 0) {
755 valence_val_3dp = "&nbsp;" + valence_val_3dp;
756 }
757
758 if ($('#arousal-val').length) {
759 $('#arousal-val').html(arousal_val_3dp);
760 }
761 if ($('#valence-val').length) {
762 $('#valence-val').html(valence_val_3dp);
763 }
764
765 }
766
767}
Note: See TracBrowser for help on using the repository browser.