comparison core.js @ 278:8020152a36af

Pull into main
author Nicholas Jillings <nicholas.jillings@eecs.qmul.ac.uk>
date Fri, 24 Jul 2015 18:59:39 +0100
parents 724f72092fa7
children 7e9c38fa7499
comparison
equal deleted inserted replaced
264:4345ba8a1b6e 278:8020152a36af
103 this.popup.style.zIndex = 3; 103 this.popup.style.zIndex = 3;
104 this.popup.style.visibility = 'visible'; 104 this.popup.style.visibility = 'visible';
105 var blank = document.getElementsByClassName('testHalt')[0]; 105 var blank = document.getElementsByClassName('testHalt')[0];
106 blank.style.zIndex = 2; 106 blank.style.zIndex = 2;
107 blank.style.visibility = 'visible'; 107 blank.style.visibility = 'visible';
108 $(window).keypress(function(e){
109 if (e.keyCode == 13 && popup.popup.style.visibility == 'visible')
110 {
111 // Enter key pressed
112 var textarea = $(popup.popupContent).find('textarea');
113 if (textarea.length != 0)
114 {
115 if (textarea[0] == document.activeElement)
116 {return;}
117 }
118 popup.buttonProceed.onclick();
119 }
120 });
108 }; 121 };
109 122
110 this.hidePopup = function(){ 123 this.hidePopup = function(){
111 this.popup.style.zIndex = -1; 124 this.popup.style.zIndex = -1;
112 this.popup.style.visibility = 'hidden'; 125 this.popup.style.visibility = 'hidden';
210 if (node.step != null) {input.step = node.step;} 223 if (node.step != null) {input.step = node.step;}
211 this.popupContent.appendChild(input); 224 this.popupContent.appendChild(input);
212 } 225 }
213 this.popupContent.appendChild(this.buttonProceed); 226 this.popupContent.appendChild(this.buttonProceed);
214 if(this.currentIndex+1 == this.popupOptions.length) { 227 if(this.currentIndex+1 == this.popupOptions.length) {
215 this.buttonProceed.textContent = 'Submit'; 228 if (this.responses.nodeName == "PRETEST") {
229 this.buttonProceed.textContent = 'Start';
230 } else {
231 this.buttonProceed.textContent = 'Submit';
232 }
216 } else { 233 } else {
217 this.buttonProceed.textContent = 'Next'; 234 this.buttonProceed.textContent = 'Next';
218 } 235 }
219 if(this.currentIndex > 0) 236 if(this.currentIndex > 0)
220 this.popupContent.appendChild(this.buttonPrevious); 237 this.popupContent.appendChild(this.buttonPrevious);
535 552
536 // New check if we need to randomise the test order 553 // New check if we need to randomise the test order
537 if (specification.randomiseOrder) 554 if (specification.randomiseOrder)
538 { 555 {
539 specification.audioHolders = randomiseOrder(specification.audioHolders); 556 specification.audioHolders = randomiseOrder(specification.audioHolders);
557 for (var i=0; i<specification.audioHolders.length; i++)
558 {
559 specification.audioHolders[i].presentedId = i;
560 }
540 } 561 }
541 562
542 $(specification.audioHolders).each(function(index,elem){ 563 $(specification.audioHolders).each(function(index,elem){
543 testState.stateMap.push(elem); 564 testState.stateMap.push(elem);
544 }); 565 });
629 }; 650 };
630 xmlhttp.onreadystatechange = function() { 651 xmlhttp.onreadystatechange = function() {
631 console.log(xmlhttp.status); 652 console.log(xmlhttp.status);
632 if (xmlhttp.status != 200 && xmlhttp.readyState == 4) { 653 if (xmlhttp.status != 200 && xmlhttp.readyState == 4) {
633 createProjectSave(null); 654 createProjectSave(null);
655 } else {
656 popup.showPopup();
657 popup.popupContent.innerHTML = null;
658 popup.popupContent.textContent = "Thank you for performing this listening test";
634 } 659 }
635 }; 660 };
636 xmlhttp.send(file); 661 xmlhttp.send(file);
637 } 662 }
638 } 663 }
711 if (this.audioObjectsReady == false) { 736 if (this.audioObjectsReady == false) {
712 this.audioObjectsReady = this.checkAllReady(); 737 this.audioObjectsReady = this.checkAllReady();
713 } 738 }
714 if (this.audioObjectsReady == true) { 739 if (this.audioObjectsReady == true) {
715 this.timer.startTest(); 740 this.timer.startTest();
741 if (this.loopPlayback)
742 {this.setSynchronousLoop();}
716 this.status = 1; 743 this.status = 1;
717 } 744 }
718 } 745 }
719 if (this.status== 1) { 746 if (this.status== 1) {
720 if (id == undefined) { 747 if (id == undefined) {
799 console.log('WAIT -- audioObject '+i+' not ready yet!'); 826 console.log('WAIT -- audioObject '+i+' not ready yet!');
800 ready = false; 827 ready = false;
801 }; 828 };
802 } 829 }
803 return ready; 830 return ready;
831 };
832
833 this.setSynchronousLoop = function() {
834 // Pads the signals so they are all exactly the same length
835 if (this.audioObjectsReady)
836 {
837 var length = 0;
838 var lens = [];
839 var maxId;
840 for (var i=0; i<this.audioObjects.length; i++)
841 {
842 lens.push(this.audioObjects[i].buffer.length);
843 if (length < this.audioObjects[i].buffer.length)
844 {
845 length = this.audioObjects[i].buffer.length;
846 maxId = i;
847 }
848 }
849 // Perform difference
850 for (var i=0; i<lens.length; i++)
851 {
852 lens[i] = length - lens[i];
853 }
854 // Extract the audio and zero-pad
855 for (var i=0; i<lens.length; i++)
856 {
857 var orig = this.audioObjects[i].buffer;
858 var hold = audioContext.createBuffer(orig.numberOfChannels,length,orig.sampleRate);
859 for (var c=0; c<orig.numberOfChannels; c++)
860 {
861 var inData = hold.getChannelData(c);
862 var outData = orig.getChannelData(c);
863 for (var n=0; n<orig.length; n++)
864 {inData[n] = outData[n];}
865 }
866 this.audioObjects[i].buffer = hold;
867 delete orig;
868 }
869 }
804 }; 870 };
805 871
806 } 872 }
807 873
808 function audioObject(id) { 874 function audioObject(id) {
903 // Create callback to decode the data asynchronously 969 // Create callback to decode the data asynchronously
904 request.onloadend = function() { 970 request.onloadend = function() {
905 audioContext.decodeAudioData(request.response, function(decodedData) { 971 audioContext.decodeAudioData(request.response, function(decodedData) {
906 audioObj.buffer = decodedData; 972 audioObj.buffer = decodedData;
907 audioObj.state = 1; 973 audioObj.state = 1;
974 if (audioObj.specification.type != 'outsidereference')
975 {audioObj.interfaceDOM.enable();}
908 }, function(){ 976 }, function(){
909 // Should only be called if there was an error, but sometimes gets called continuously 977 // Should only be called if there was an error, but sometimes gets called continuously
910 // Check here if the error is genuine 978 // Check here if the error is genuine
911 if (audioObj.state == 0 || audioObj.buffer == undefined) { 979 if (audioObj.state == 0 || audioObj.buffer == undefined) {
912 // Genuine error 980 // Genuine error
934 file.setAttribute('duration',this.buffer.duration); 1002 file.setAttribute('duration',this.buffer.duration);
935 root.appendChild(file); 1003 root.appendChild(file);
936 if (this.specification.type != 'outsidereference') { 1004 if (this.specification.type != 'outsidereference') {
937 root.appendChild(this.interfaceDOM.exportXMLDOM(this)); 1005 root.appendChild(this.interfaceDOM.exportXMLDOM(this));
938 root.appendChild(this.commentDOM.exportXMLDOM(this)); 1006 root.appendChild(this.commentDOM.exportXMLDOM(this));
1007 if(this.specification.type == 'anchor') {
1008 root.setAttribute('anchor',true);
1009 } else if(this.specification.type == 'reference') {
1010 root.setAttribute('reference',true);
1011 }
939 } 1012 }
940 root.appendChild(this.metric.exportXMLDOM()); 1013 root.appendChild(this.metric.exportXMLDOM());
941 return root; 1014 return root;
942 }; 1015 };
943 } 1016 }
1310 this.max = Number(this.max); 1383 this.max = Number(this.max);
1311 } 1384 }
1312 } 1385 }
1313 } else if (this.type == 'anchor' || this.type == 'reference') { 1386 } else if (this.type == 'anchor' || this.type == 'reference') {
1314 this.value = Number(child.textContent); 1387 this.value = Number(child.textContent);
1388 this.enforce = child.getAttribute('enforce');
1389 if (this.enforce == 'true') {this.enforce = true;}
1390 else {this.enforce = false;}
1315 } 1391 }
1316 }; 1392 };
1317 this.options = []; 1393 this.options = [];
1318 if (commonInterfaceNode != undefined) { 1394 if (commonInterfaceNode != undefined) {
1319 var child = commonInterfaceNode.firstElementChild; 1395 var child = commonInterfaceNode.firstElementChild;
1403 this.enabled = name; 1479 this.enabled = name;
1404 }; 1480 };
1405 1481
1406 this.audioHolderNode = function(parent,xml) { 1482 this.audioHolderNode = function(parent,xml) {
1407 this.type = 'audioHolder'; 1483 this.type = 'audioHolder';
1484 this.presentedId = parent.audioHolders.length;
1408 this.interfaceNode = function(DOM) { 1485 this.interfaceNode = function(DOM) {
1409 var title = DOM.getElementsByTagName('title'); 1486 var title = DOM.getElementsByTagName('title');
1410 if (title.length == 0) {this.title = null;} 1487 if (title.length == 0) {this.title = null;}
1411 else {this.title = title[0].textContent;} 1488 else {this.title = title[0].textContent;}
1412 this.options = parent.commonInterface.options; 1489 this.options = parent.commonInterface.options;
1432 else {this.reference = false;} 1509 else {this.reference = false;}
1433 1510
1434 this.marker = xml.getAttribute('marker'); 1511 this.marker = xml.getAttribute('marker');
1435 if (this.marker == null) {this.marker = undefined;} 1512 if (this.marker == null) {this.marker = undefined;}
1436 1513
1437 if (this.anchor == true && this.marker == undefined) { 1514 if (this.anchor == true) {
1515 if (this.marker != undefined) {this.enforce = true;}
1516 else {this.enforce = enforceAnchor;}
1438 this.marker = anchor; 1517 this.marker = anchor;
1439 } 1518 }
1440 else if (this.reference == true && this.marker == undefined) { 1519 else if (this.reference == true) {
1520 if (this.marker != undefined) {this.enforce = true;}
1521 else {this.enforce = enforceReference;}
1441 this.marker = reference; 1522 this.marker = reference;
1442 } 1523 }
1443 1524
1444 if (this.marker != undefined) { 1525 if (this.marker != undefined) {
1445 this.marker = Number(this.marker); 1526 this.marker = Number(this.marker);
1499 else {this.loop == false;} 1580 else {this.loop == false;}
1500 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;} 1581 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;}
1501 else {this.elementComments = false;} 1582 else {this.elementComments = false;}
1502 1583
1503 var anchor = xml.getElementsByTagName('anchor'); 1584 var anchor = xml.getElementsByTagName('anchor');
1585 var enforceAnchor = false;
1504 if (anchor.length == 0) { 1586 if (anchor.length == 0) {
1505 // Find anchor in commonInterface; 1587 // Find anchor in commonInterface;
1506 for (var i=0; i<parent.commonInterface.options.length; i++) { 1588 for (var i=0; i<parent.commonInterface.options.length; i++) {
1507 if(parent.commonInterface.options[i].type == 'anchor') { 1589 if(parent.commonInterface.options[i].type == 'anchor') {
1508 anchor = parent.commonInterface.options[i].value; 1590 anchor = parent.commonInterface.options[i].value;
1591 enforceAnchor = parent.commonInterface.options[i].enforce;
1509 break; 1592 break;
1510 } 1593 }
1511 } 1594 }
1512 if (typeof(anchor) == "object") { 1595 if (typeof(anchor) == "object") {
1513 anchor = null; 1596 anchor = null;
1515 } else { 1598 } else {
1516 anchor = anchor[0].textContent; 1599 anchor = anchor[0].textContent;
1517 } 1600 }
1518 1601
1519 var reference = xml.getElementsByTagName('anchor'); 1602 var reference = xml.getElementsByTagName('anchor');
1603 var enforceReference = false;
1520 if (reference.length == 0) { 1604 if (reference.length == 0) {
1521 // Find anchor in commonInterface; 1605 // Find anchor in commonInterface;
1522 for (var i=0; i<parent.commonInterface.options.length; i++) { 1606 for (var i=0; i<parent.commonInterface.options.length; i++) {
1523 if(parent.commonInterface.options[i].type == 'reference') { 1607 if(parent.commonInterface.options[i].type == 'reference') {
1524 reference = parent.commonInterface.options[i].value; 1608 reference = parent.commonInterface.options[i].value;
1609 enforceReference = parent.commonInterface.options[i].enforce;
1525 break; 1610 break;
1526 } 1611 }
1527 } 1612 }
1528 if (typeof(reference) == "object") { 1613 if (typeof(reference) == "object") {
1529 reference = null; 1614 reference = null;
1941 2026
1942 this.update = function() { 2027 this.update = function() {
1943 // Update the playhead position, startPlay must be called 2028 // Update the playhead position, startPlay must be called
1944 if (this.timePerPixel > 0) { 2029 if (this.timePerPixel > 0) {
1945 var time = this.playbackObject.getCurrentPosition(); 2030 var time = this.playbackObject.getCurrentPosition();
1946 var width = 490; 2031 if (time > 0) {
1947 var pix = Math.floor(time/this.timePerPixel); 2032 var width = 490;
1948 this.scrubberHead.style.left = pix+'px'; 2033 var pix = Math.floor(time/this.timePerPixel);
1949 if (this.maxTime > 60.0) { 2034 this.scrubberHead.style.left = pix+'px';
1950 var secs = time%60; 2035 if (this.maxTime > 60.0) {
1951 var mins = Math.floor((time-secs)/60); 2036 var secs = time%60;
1952 secs = secs.toString(); 2037 var mins = Math.floor((time-secs)/60);
1953 secs = secs.substr(0,2); 2038 secs = secs.toString();
1954 mins = mins.toString(); 2039 secs = secs.substr(0,2);
1955 this.curTimeSpan.textContent = mins+':'+secs; 2040 mins = mins.toString();
2041 this.curTimeSpan.textContent = mins+':'+secs;
2042 } else {
2043 time = time.toString();
2044 this.curTimeSpan.textContent = time.substr(0,4);
2045 }
1956 } else { 2046 } else {
1957 time = time.toString(); 2047 this.scrubberHead.style.left = '0px';
1958 this.curTimeSpan.textContent = time.substr(0,4); 2048 if (this.maxTime < 60) {
2049 this.curTimeSpan.textContent = '0.00';
2050 } else {
2051 this.curTimeSpan.textContent = '00:00';
2052 }
1959 } 2053 }
1960 } 2054 }
1961 }; 2055 };
1962 2056
1963 this.interval = undefined; 2057 this.interval = undefined;
1964 2058
1965 this.start = function() { 2059 this.start = function() {
1966 if (this.playbackObject != undefined && this.interval == undefined) { 2060 if (this.playbackObject != undefined && this.interval == undefined) {
1967 this.interval = setInterval(function(){interfaceContext.playhead.update();},100); 2061 if (this.maxTime < 60) {
2062 this.interval = setInterval(function(){interfaceContext.playhead.update();},10);
2063 } else {
2064 this.interval = setInterval(function(){interfaceContext.playhead.update();},100);
2065 }
1968 } 2066 }
1969 }; 2067 };
1970 this.stop = function() { 2068 this.stop = function() {
1971 clearInterval(this.interval); 2069 clearInterval(this.interval);
1972 this.interval = undefined; 2070 this.interval = undefined;
2071 if (this.maxTime < 60) {
2072 this.curTimeSpan.textContent = '0.00';
2073 } else {
2074 this.curTimeSpan.textContent = '00:00';
2075 }
1973 }; 2076 };
1974 }; 2077 };
1975 2078
1976 // Global Checkers 2079 // Global Checkers
1977 // These functions will help enforce the checkers 2080 // These functions will help enforce the checkers
1979 { 2082 {
1980 var audioHolder = testState.currentStateMap[testState.currentIndex]; 2083 var audioHolder = testState.currentStateMap[testState.currentIndex];
1981 if (audioHolder.anchorId != null) 2084 if (audioHolder.anchorId != null)
1982 { 2085 {
1983 var audioObject = audioEngineContext.audioObjects[audioHolder.anchorId]; 2086 var audioObject = audioEngineContext.audioObjects[audioHolder.anchorId];
1984 if (audioObject.interfaceDOM.getValue() > audioObject.specification.marker) 2087 if (audioObject.interfaceDOM.getValue() > audioObject.specification.marker && audioObject.interfaceDOM.enforce == true)
1985 { 2088 {
1986 // Anchor is not set below 2089 // Anchor is not set below
1987 console.log('Anchor node not below marker value'); 2090 console.log('Anchor node not below marker value');
1988 alert('Please keep listening'); 2091 alert('Please keep listening');
1989 return false; 2092 return false;
1996 { 2099 {
1997 var audioHolder = testState.currentStateMap[testState.currentIndex]; 2100 var audioHolder = testState.currentStateMap[testState.currentIndex];
1998 if (audioHolder.referenceId != null) 2101 if (audioHolder.referenceId != null)
1999 { 2102 {
2000 var audioObject = audioEngineContext.audioObjects[audioHolder.referenceId]; 2103 var audioObject = audioEngineContext.audioObjects[audioHolder.referenceId];
2001 if (audioObject.interfaceDOM.getValue() < audioObject.specification.marker) 2104 if (audioObject.interfaceDOM.getValue() < audioObject.specification.marker && audioObject.interfaceDOM.enforce == true)
2002 { 2105 {
2003 // Anchor is not set below 2106 // Anchor is not set below
2004 console.log('Reference node not above marker value'); 2107 console.log('Reference node not above marker value');
2005 alert('Please keep listening'); 2108 alert('Please keep listening');
2006 return false; 2109 return false;