Mercurial > hg > webaudioevaluationtool
changeset 2436:25c1436706af
Merge branch 'master' of https://github.com/BrechtDeMan/WebAudioEvaluationTool
author | www-data <www-data@sucuk.dcs.qmul.ac.uk> |
---|---|
date | Thu, 02 Jun 2016 14:20:55 +0100 |
parents | d479fdc7221c (current diff) a78ebb1bdd8e (diff) |
children | 02df8de58e7b |
files | |
diffstat | 13 files changed, 208 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/docs/Instructions/Instructions.tex Fri May 27 15:20:59 2016 +0100 +++ b/docs/Instructions/Instructions.tex Thu Jun 02 14:20:55 2016 +0100 @@ -35,6 +35,8 @@ The SoundSoftware project page, including a Mercurial repository, is \url{https://code.soundsoftware.ac.uk/projects/webaudioevaluationtool/}. +\textbf{The most current version of these instructions can be found on \url{https://github.com/BrechtDeMan/WebAudioEvaluationTool/wiki}.} + \tableofcontents @@ -431,7 +433,6 @@ \item \texttt{randomiseOrder}: Boolean, optional. If true the audio fragments are presented randomly rather than the order specified. See Section~\ref{sec:randomisation}. Default is false. \item \texttt{repeatCount}: non-negative integer, optional. Specify the number of times to repeat the test page (re-present). Each presentation will appear as an individual page in the results. Default is 0. \item \texttt{loop}: Boolean, optional. If true, the audio elements will loop synchronously with each other. See \ref{sec:looping}. Default is false. - \item \texttt{showElementComments}: Boolean, optional. If true then there will be a comment box on the test page for each audio element presented, see Section~\ref{sec:commentboxes}. \item \texttt{loudness}: non-positive integer, optional. Set the LUFS target value for this page. Supersedes the \texttt{<setup>} loudness attribute for this page. See Section~\ref{sec:loudness} for more. \item \texttt{label}: enumeration, optional. Set the label to one of the following \begin{itemize} @@ -488,7 +489,7 @@ \begin{itemize} \item \texttt{title}: Min 0, max 1 occurence. The text content specifies the name of the axis as shown to the user. \item \texttt{interfaceoption}: Min 0, max unbounded. Specifies the interface options. See Section~\ref{sec:interfaceoption}. - \item \texttt{scales}: Min 0, max 1 occurence. Contains \texttt{<scalelabel>} nodes which define the displayed scales. See Section~\ref{sec:scales}. + \item \texttt{scales}: Min 0, max 1 occurence. Contains \texttt{<scalelabel>} nodes which define the displayed scales. See Section~\ref{sec:multiscale}. \end{itemize} \subsection{Audio Element} @@ -539,6 +540,7 @@ \end{itemize} \subsubsection{Multiple scales} + \label{sec:multiscale} In the case of multiple rating scales, e.g. when the stimuli are to be rated in terms of attributes `timbre' and `spatial impression', multiple interface nodes will have to be added, each specifying the title and annotations. This is where the \texttt{interface}'s \texttt{name} attribute is particularly important: use this to retrieve the rating values, comments and metrics associated with the specified interface. @@ -556,7 +558,7 @@ % Needs to be implemented in PHP and automated better, will complete soon - \subsubsection{Randomsation of page order} + \subsubsection{Randomisation of page order} The page order randomisation is set by the \texttt{<setup>} node attribute \texttt{randomise-order}, for example \texttt{<setup ... randomise-order=\texttt{\char`\"}true\texttt{\char`\"}>...</setup>} will randomise the test page order. When not set, the default is to \textbf{not} randomise the test page order. \subsubsection{Randomisation of axis order} @@ -580,13 +582,13 @@ \subsection{Sample rate} \label{sec:samplerate} - If you require the test to be conducted at a certain sample rate (i.e. you do not tolerate resampling of the elements to correspond with the system's sample rate), add \texttt{sampleRate="96000"} - where ``96000'' can be any support sample rate (in Hz) - so that a warning message is shown alerting the subject that their system's sample rate is different from this enforced sample rate. This is checked immediately after parsing and stops the page loading any other elements if this check has failed. + If you require the test to be conducted at a certain sample rate (i.e. you do not tolerate resampling of the elements to correspond with the system's sample rate), add \texttt{sampleRate="96000"} - where ``96000'' can be any supported sample rate (in Hz) - so that a warning message is shown alerting the subject that their system's sample rate is different from this enforced sample rate. This is checked immediately after parsing and stops the page loading any other elements if this check has failed. \subsection{Metrics} - The \texttt{Metric} node, which contains the metrics to be tracked during the complete test, is a child of the \texttt{setup} node, and it could look as follows. + The \texttt{metric} node, which contains the metrics to be tracked during the complete test, is a child of the \texttt{setup} node, and it could look as follows. \begin{lstlisting} -<Metric> +<metric> <metricEnable>testTimer</metricEnable> <metricEnable>elementTimer</metricEnable> <metricEnable>elementInitialPosition</metricEnable> @@ -594,14 +596,14 @@ <metricEnable>elementFlagListenedTo</metricEnable> <metricEnable>elementFlagMoved</metricEnable> <metricEnable>elementListenTracker</metricEnable> -</Metric> +</metric> \end{lstlisting} When in doubt, err on the inclusive side, as one never knows which information is needed in the future. Most of these metrics are necessary for post-processing scripts such as timeline\_view\_movement.py. % Brecht: should perhaps list somewhere what metrics are required for which analysis scripts. \subsubsection{Time test duration} \texttt{testTimer}\\ - One per test page. Presents the total test time from the first playback on the test page to the submission of the test page (exculding test time of the pre-/post- test surveys). This is presented in the results as \texttt{<metricresult id=\texttt{\char`\"}testTime\texttt{\char`\"}> 8.60299319727892 </metricresult>}. The time is in seconds. + One per test page. Presents the total test time from the first playback on the test page to the submission of the test page (excluding test time of the pre-/post- test surveys). This is presented in the results as \texttt{<metricresult id=\texttt{\char`\"}testTime\texttt{\char`\"}> 8.60299319727892 </metricresult>}. The time is in seconds. \subsubsection{Time fragment playback} \texttt{elementTimer}\\ @@ -631,7 +633,7 @@ \subsubsection{Outside Reference} Set type to `outside-reference'. This will place the object in a separate playback element clearly labelled as an outside reference. This is exempt of any movement checks but will still be included in any listening checks. \subsubsection{Hidden reference} - Set type to `reference'. The element will still be randomised as normal (if selected) and presented to the user. However the element will have the `reference' type in the results to quickly find it. The reference can be forced to be below a value before completing the test page by setting the attribute `marker' to be a value between 0 and 100 representing the integer value position it must be equal to or above. + Set type to `reference'. The element will still be randomised as normal (if selected) and presented to the user. However the element will have the `reference' type in the results to quickly find it. The reference can be forced to be above a value before completing the test page by setting the attribute `marker' to be a value between 0 and 100 representing the integer value position it must be equal to or above. \subsubsection{Hidden anchor} Set type to `anchor'. The element will still be randomised as normal (if selected) and presented to the user. However the element will have the `anchor' type in the results to quickly find it. The anchor can be forced to be below a value before completing the test page by setting the attribute `marker' to be a value between 0 and 100 representing the integer value position it must be equal to or below. @@ -701,11 +703,11 @@ \label{sec:loudness} % automatic loudness equalisation % guide to loudness.js - Each audio fragment on loading has its loudness calculated. The tool uses the EBU R 128 recommendation following the ITU-R BS.1770-4 loduness calculations to return the integreated LUFS loudness. The attribute \texttt{loudness} will set the loudness from the scope it is applied in. Applying it in the \texttt{<setup>} node will set the loudness for all test pages. Applying it in the \texttt{<page>} node will set the loudness for that page. Applying it in the \texttt{<audioelement>} node will set the loudness for that fragment. The scope is set locally, so if there is a loudness on both the \texttt{<page>} and \texttt{<setup>} nodes, that test page will take the value associated with the \texttt{<page>}. The loudness attribute is set in LUFS + Each audio fragment on loading has its loudness calculated. The tool uses the EBU R 128 recommendation following the ITU-R BS.1770-4 loudness calculations to return the integrated LUFS loudness. The attribute \texttt{loudness} will set the loudness from the scope it is applied in. Applying it in the \texttt{<setup>} node will set the loudness for all test pages. Applying it in the \texttt{<page>} node will set the loudness for that page. Applying it in the \texttt{<audioelement>} node will set the loudness for that fragment. The scope is set locally, so if there is a loudness on both the \texttt{<page>} and \texttt{<setup>} nodes, that test page will take the value associated with the \texttt{<page>}. The loudness attribute is set in LUFS \subsection{Comment Boxes} \label{sec:commentboxes} - There are two types of comment boxes which can be presented, those linked to the audio fragments on the page and those which pose a general question. The audio fragment boxes are shown by setting the attribute \texttt{showElementComments} to true of the page in question. This will then show a comment box below the main interface for every fragment on the page. There is some customisation around the text that accompanies the box, by default the text will read ``Comment on fragment'' followed by the fragment identifier (the number / letter shown by the interface). This `prefix' can be modified using the page node \texttt{<commentboxprefix>}, see Section~\ref{sec:page} for where to place this node in the document. The comment box prefix node takes no attribute and the text contained by the node represents to the prefix. For instance if we have a node \texttt{<commentboxprefix> Describe fragment </commentboxprefix>}, then the interface will show ``Describe fragment'' followed by the identifier. + There are two types of comment boxes which can be presented, those linked to the audio fragments on the page and those which pose a general question. When enabled, there is a comment box below the main interface for every fragment on the page. There is some customisation around the text that accompanies the box, by default the text will read ``Comment on fragment'' followed by the fragment identifier (the number / letter shown by the interface). This `prefix' can be modified using the page node \texttt{<commentboxprefix>}, see Section~\ref{sec:page} for where to place this node in the document. The comment box prefix node takes no attribute and the text contained by the node represents to the prefix. For instance if we have a node \texttt{<commentboxprefix> Describe fragment </commentboxprefix>}, then the interface will show ``Describe fragment'' followed by the identifier. The second type of comment box is slightly more complex because it can handle different types of response data. These are called comment questions because they are located in the comment section of the test but pose a specific question.
--- a/interfaces/AB.js Fri May 27 15:20:59 2016 +0100 +++ b/interfaces/AB.js Thu Jun 02 14:20:55 2016 +0100 @@ -315,14 +315,23 @@ } this.startPlayback = function() { - $('.comparator-button').text('Listen'); + if (this.parent.specification.parent.playOne || specification.playOne) { + $('.comparator-button').text('Wait'); + $('.comparator-button').attr("disabled","true"); + $(this.playback).css("disabled","false"); + } else { + $('.comparator-button').text('Listen'); + } $(this.playback).text('Stop'); this.playback.setAttribute("playstate","playing"); }; this.stopPlayback = function() { - $(this.playback).text('Listen'); - this.playback.setAttribute("playstate","ready"); + if (this.playback.getAttribute("playstate") == "playing") { + $('.comparator-button').text('Listen'); + $('.comparator-button').removeAttr("disabled"); + this.playback.setAttribute("playstate","ready"); + } }; this.exportXMLDOM = function(audioObject) {
--- a/interfaces/ABX.js Fri May 27 15:20:59 2016 +0100 +++ b/interfaces/ABX.js Thu Jun 02 14:20:55 2016 +0100 @@ -292,16 +292,23 @@ }; this.startPlayback = function() { - // Called when playback has begun - $('.comparator-button').text('Listen'); + if (this.parent.specification.parent.playOne || specification.playOne) { + $('.comparator-button').text('Wait'); + $('.comparator-button').attr("disabled","true"); + $(this.playback).css("disabled","false"); + } else { + $('.comparator-button').text('Listen'); + } $(this.playback).text('Stop'); this.playback.setAttribute("playstate","playing"); }; this.stopPlayback = function() { - // Called when playback has stopped. This gets called even if playback never started! - $(this.playback).text('Listen'); - this.playback.setAttribute("playstate","ready"); + if (this.playback.getAttribute("playstate") == "playing") { + $('.comparator-button').text('Listen'); + $('.comparator-button').removeAttr("disabled"); + this.playback.setAttribute("playstate","ready"); + } }; this.getValue = function() {
--- a/interfaces/ape.js Fri May 27 15:20:59 2016 +0100 +++ b/interfaces/ape.js Thu Jun 02 14:20:55 2016 +0100 @@ -621,6 +621,7 @@ this.parent = audioObject; this.trackSliderObjects = []; this.label = null; + this.playing = false; switch(audioObject.specification.parent.label) { case "letter": this.label = String.fromCharCode(97 + index); @@ -669,15 +670,24 @@ $(name).addClass('track-slider-playing'); $('.comment-div').removeClass('comment-box-playing'); $('#comment-div-'+this.parent.id).addClass('comment-box-playing'); - var outsideReference = document.getElementById('outside-reference'); - if (outsideReference != undefined) - $(outsideReference).removeClass('track-slider-playing'); + $('.outside-reference').removeClass('track-slider-playing'); + this.playing = true; + + if (this.parent.specification.parent.playOne || specification.playOne) { + $('.track-slider').addClass('track-slider-disabled'); + $('.outside-reference').addClass('track-slider-disabled'); + } }; this.stopPlayback = function() { - var name = ".track-slider-"+this.parent.id; - $(name).removeClass('track-slider-playing'); - $('#comment-div-'+this.parent.id).removeClass('comment-box-playing'); + if (this.playing) { + this.playing = false; + var name = ".track-slider-"+this.parent.id; + $(name).removeClass('track-slider-playing'); + $('#comment-div-'+this.parent.id).removeClass('comment-box-playing'); + $('.track-slider').removeClass('track-slider-disabled'); + $('.outside-reference').removeClass('track-slider-disabled'); + } }; this.exportXMLDOM = function(audioObject) { // Called by the audioObject holding this element. Must be present
--- a/interfaces/discrete.js Fri May 27 15:20:59 2016 +0100 +++ b/interfaces/discrete.js Thu Jun 02 14:20:55 2016 +0100 @@ -355,13 +355,21 @@ if (outsideReference != null) { $(outsideReference).removeClass('track-slider-playing'); } + if (this.parent.specification.parent.playOne || specification.playOne) { + $('.track-slider-button').text = "Wait"; + $('.track-slider-button').attr("disabled","true"); + } } this.stopPlayback = function() { // Called by audioObject when playback stops - this.play.setAttribute("playstate","ready"); - $(this.holder).removeClass('track-slider-playing'); - this.play.textContent = "Play"; + if (this.play.getAttribute("playstate") == "playing") { + this.play.setAttribute("playstate","ready"); + $(this.holder).removeClass('track-slider-playing'); + $('.track-slider-button').text = "Play"; + this.play.textContent = "Play"; + $('.track-slider-button').removeAttr("disabled"); + } } this.getValue = function()
--- a/js/core.js Fri May 27 15:20:59 2016 +0100 +++ b/js/core.js Thu Jun 02 14:20:55 2016 +0100 @@ -1309,6 +1309,7 @@ this.parent.users[i].bufferLoaded(this); } } + interfaceContext.lightbox.post("Error","Could not load resource "+this.parent.url); } this.progress = 0; @@ -1623,7 +1624,7 @@ if (this.interfaceDOM != null) { this.interfaceDOM.enable(); } - this.onplayGain = decibelToLinear(this.specification.gain)*this.buffer.buffer.playbackGain; + this.onplayGain = decibelToLinear(this.specification.gain)*(this.buffer.buffer.playbackGain||1.0); this.storeDOM.setAttribute('playGain',linearToDecibel(this.onplayGain)); }; @@ -1672,7 +1673,7 @@ }; if (!audioEngineContext.loopPlayback || !audioEngineContext.synchPlayback) { this.metric.startListening(audioEngineContext.timer.getTestTime()); - this.outputGain.gain.setValueAtTime(this.onplayGain,startTime); + this.outputGain.gain.setValueAtTime(this.onplayGain,0.0); this.interfaceDOM.startPlayback(); } else { this.outputGain.gain.setValueAtTime(0.0,startTime);
--- a/js/loudness.js Fri May 27 15:20:59 2016 +0100 +++ b/js/loudness.js Thu Jun 02 14:20:55 2016 +0100 @@ -19,7 +19,9 @@ // timescale -> M or Momentary (returns Array), S or Short (returns Array), // I or Integrated (default, returns number) // target -> default is -23 LUFS but can be any LUFS measurement. - + if(navigator.platform == 'iPad' || navigator.platform == 'iPhone') { + buffer.ready(); + } if (buffer == undefined) { return 0;
--- a/js/specification.js Fri May 27 15:20:59 2016 +0100 +++ b/js/specification.js Thu Jun 02 14:20:55 2016 +0100 @@ -13,6 +13,7 @@ this.crossFade = null; this.preSilence = null; this.postSilence = null; + this.playOne = null; // nodes this.metrics = null; @@ -120,7 +121,6 @@ { case 'pre': case 'before': - if (this.preTest != null){console.log("Already a pre/before test survey defined! Ignoring second!!");} else { this.preTest = new this.surveyNode(this); this.preTest.decode(this,survey[i]); @@ -128,7 +128,6 @@ break; case 'post': case 'after': - if (this.postTest != null){console.log("Already a post/after test survey defined! Ignoring second!!");} else { this.postTest = new this.surveyNode(this); this.postTest.decode(this,survey[i]); @@ -448,6 +447,7 @@ this.preTest = null; this.postTest = null; this.interfaces = []; + this.playOne = null; this.commentBoxPrefix = "Comment on track"; this.audioElements = []; this.commentQuestions = [];
--- a/python/pythonServer.py Fri May 27 15:20:59 2016 +0100 +++ b/python/pythonServer.py Thu Jun 02 14:20:55 2016 +0100 @@ -4,13 +4,13 @@ # http://stackoverflow.com/questions/9079036/detect-python-version-at-runtime import sys -from os import walk -from os import path -from os import listdir import inspect import os import pickle import datetime +import operator +import xml.etree.ElementTree as ET +import copy if sys.version_info[0] == 2: # Version 2.x @@ -28,14 +28,14 @@ PSEUDO_PATH = '../tests/' pseudo_files = [] -for filename in listdir(PSEUDO_PATH): +for filename in os.listdir(PSEUDO_PATH): print(filename) if filename.endswith('.xml'): pseudo_files.append(filename) curSaveIndex = 0; curFileName = 'test-0.xml' -while(path.isfile('../saves/'+curFileName)): +while(os.path.isfile('../saves/'+curFileName)): curSaveIndex += 1; curFileName = 'test-'+str(curSaveIndex)+'.xml' @@ -60,7 +60,7 @@ lenSt = len(st) fmt = st[lenSt-1].rsplit('.') fpath = "../"+urllib2.unquote(s.path) - size = path.getsize(fpath) + size = os.path.getsize(fpath) fileDump = open(fpath) s.send_response(200) @@ -160,6 +160,61 @@ curSaveIndex += 1 curFileName = 'test-'+str(curSaveIndex)+'.xml' +def poolXML(s): + pool = ET.parse('../tests/pool.xml') + root = pool.getroot() + setupNode = root.find("setup"); + poolSize = setupNode.get("poolSize",0); + if (poolSize == 0): + s.path = s.path.split("/php",1)[0]+"/tests/pool/xml" + processFile(s) + return + poolSize = int(poolSize) + # Set up the store will all the test page key nodes + pages = {}; + for page in root.iter("page"): + id = page.get("id") + pages[id] = 0 + # Read the saves and determine the completed pages + for filename in os.listdir("../saves/"): + if filename.endswith(".xml"): + save = ET.parse("../saves/"+filename) + save_root = save.getroot(); + if (save_root.find("waet").get("url") == "http://localhost:8000/php/pool.php"): + for page in save_root.findall("./page"): + id = page.get("ref") + pages[id] = pages[id] + 1 + + # Sort the dictionary + rot_pages = {} + for key, value in pages.items(): + if (value in rot_pages): + rot_pages[value].append(key) + else: + rot_pages[value] = [key] + + Keys = list(rot_pages) + print ("Current pool state:") + print (rot_pages) + + return_node = ET.fromstring('<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"/>'); + return_node.append(copy.deepcopy(root.find("setup"))) + page_elements = root.findall("page") + + # Now append the pages + i = 0 + while(len(return_node.findall("page")) < poolSize): + if (i > 0): + for page in return_node.iter("page"): + page.set("alwaysInclude","true") + for id in rot_pages[Keys[i]]: + return_node.append(copy.deepcopy(root.find('./page[@id="'+id+'"]'))) + i=i+1 + s.send_response(200) + s.send_header("Content-type", "text/xml") + s.end_headers() + s.wfile.write(ET.tostring(return_node)) + def http_do_HEAD(s): s.send_response(200) s.send_header("Content-type", "text/html") @@ -171,6 +226,8 @@ send404(request) elif (request.path.split('?',1)[0] == "/php/keygen.php"): keygen(request); + elif (request.path.split('?',1)[0] == "/php/pool.php"): + poolXML(request); else: request.path = request.path.split('?',1)[0] if (request.path == '/'):
--- a/tests/examples/AB_example.xml Fri May 27 15:20:59 2016 +0100 +++ b/tests/examples/AB_example.xml Thu Jun 02 14:20:55 2016 +0100 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="AB" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" sampleRate="44100"> + <setup interface="AB" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" sampleRate="44100" playOne="true"> <survey location="before"> <surveyentry type="question" id="sessionId" mandatory="true"> <statement>Please enter your name.</statement>
--- a/tests/pool.xml Fri May 27 15:20:59 2016 +0100 +++ b/tests/pool.xml Thu Jun 02 14:20:55 2016 +0100 @@ -1,69 +1,69 @@ <?xml version="1.0" encoding="UTF-8" ?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="likert" projectReturn="save.php" crossFade="3.0" poolSize="3"> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentMoved"/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' showElementComments='true' loudness="-23"> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-1" name="track-0" type="outside-reference"/> - <audioelement url="1.wav" id="track-2"/> - </page> - <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' showElementComments='true' loudness="-23"> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-3" name="track-0" type="outside-reference"/> - <audioelement url="2.wav" id="track-4"/> - </page> - <page id='test-2' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' showElementComments='true' loudness="-23"> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-5" name="track-0" type="outside-reference"/> - <audioelement url="3.wav" id="track-6"/> - </page> - <page id='test-3' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' showElementComments='true' loudness="-23"> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-7" name="track-0" type="outside-reference"/> - <audioelement url="4.wav" id="track-8"/> - </page> -</waet> + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="likert" projectReturn="save.php" crossFade="3.0" poolSize="3"> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentMoved" /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-1" name="track-0" type="outside-reference" /> + <audioelement url="1.wav" id="track-2" /> + </page> + <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-3" name="track-0" type="outside-reference" /> + <audioelement url="2.wav" id="track-4" /> + </page> + <page id='test-2' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-5" name="track-0" type="outside-reference" /> + <audioelement url="3.wav" id="track-6" /> + </page> + <page id='test-3' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-7" name="track-0" type="outside-reference" /> + <audioelement url="4.wav" id="track-8" /> + </page> + </waet>
--- a/xml/test-schema.xsd Fri May 27 15:20:59 2016 +0100 +++ b/xml/test-schema.xsd Thu Jun 02 14:20:55 2016 +0100 @@ -26,6 +26,8 @@ </xs:restriction> </xs:simpleType> </xs:attribute> + + <xs:attribute name="playOne" type="xs:boolean" default="false"/> <!-- define complex elements--> <xs:element name="waet"> @@ -62,6 +64,7 @@ </xs:attribute> <xs:attribute ref="preSilence" /> <xs:attribute ref="postSilence" /> + <xs:attribute ref="playOne" /> </xs:complexType> </xs:element> @@ -97,6 +100,7 @@ <xs:attribute ref="alwaysInclude" /> <xs:attribute ref="preSilence" /> <xs:attribute ref="postSilence" /> + <xs:attribute ref="playOne" /> </xs:complexType> </xs:element>