summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js')
-rw-r--r--third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js376
1 files changed, 376 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js b/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js
new file mode 100644
index 0000000000..8e47411058
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js
@@ -0,0 +1,376 @@
+// Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+/**
+ * Opens the score stats inspector dialog.
+ * @param {String} dialogId: identifier of the dialog to show.
+ * @return {DOMElement} The dialog element that has been opened.
+ */
+function openScoreStatsInspector(dialogId) {
+ var dialog = document.getElementById(dialogId);
+ dialog.showModal();
+ return dialog;
+}
+
+/**
+ * Closes the score stats inspector dialog.
+ */
+function closeScoreStatsInspector() {
+ var dialog = document.querySelector('dialog[open]');
+ if (dialog == null)
+ return;
+ dialog.close();
+}
+
+/**
+ * Audio inspector class.
+ * @constructor
+ */
+function AudioInspector() {
+ console.debug('Creating an AudioInspector instance.');
+ this.audioPlayer_ = new Audio();
+ this.metadata_ = {};
+ this.currentScore_ = null;
+ this.audioInspector_ = null;
+ this.snackbarContainer_ = document.querySelector('#snackbar');
+
+ // Get base URL without anchors.
+ this.baseUrl_ = window.location.href;
+ var index = this.baseUrl_.indexOf('#');
+ if (index > 0)
+ this.baseUrl_ = this.baseUrl_.substr(0, index)
+ console.info('Base URL set to "' + window.location.href + '".');
+
+ window.event.stopPropagation();
+ this.createTextAreasForCopy_();
+ this.createAudioInspector_();
+ this.initializeEventHandlers_();
+
+ // When MDL is ready, parse the anchor (if any) to show the requested
+ // experiment.
+ var self = this;
+ document.querySelectorAll('header a')[0].addEventListener(
+ 'mdl-componentupgraded', function() {
+ if (!self.parseWindowAnchor()) {
+ // If not experiment is requested, open the first section.
+ console.info('No anchor parsing, opening the first section.');
+ document.querySelectorAll('header a > span')[0].click();
+ }
+ });
+}
+
+/**
+ * Parse the anchor in the window URL.
+ * @return {bool} True if the parsing succeeded.
+ */
+AudioInspector.prototype.parseWindowAnchor = function() {
+ var index = location.href.indexOf('#');
+ if (index == -1) {
+ console.debug('No # found in the URL.');
+ return false;
+ }
+
+ var anchor = location.href.substr(index - location.href.length + 1);
+ console.info('Anchor changed: "' + anchor + '".');
+
+ var parts = anchor.split('&');
+ if (parts.length != 3) {
+ console.info('Ignoring anchor with invalid number of fields.');
+ return false;
+ }
+
+ var openDialog = document.querySelector('dialog[open]');
+ try {
+ // Open the requested dialog if not already open.
+ if (!openDialog || openDialog.id != parts[1]) {
+ !openDialog || openDialog.close();
+ document.querySelectorAll('header a > span')[
+ parseInt(parts[0].substr(1))].click();
+ openDialog = openScoreStatsInspector(parts[1]);
+ }
+
+ // Trigger click on cell.
+ var cell = openDialog.querySelector('td.' + parts[2]);
+ cell.focus();
+ cell.click();
+
+ this.showNotification_('Experiment selected.');
+ return true;
+ } catch (e) {
+ this.showNotification_('Cannot select experiment :(');
+ console.error('Exception caught while selecting experiment: "' + e + '".');
+ }
+
+ return false;
+}
+
+/**
+ * Set up the inspector for a new score.
+ * @param {DOMElement} element: Element linked to the selected score.
+ */
+AudioInspector.prototype.selectedScoreChange = function(element) {
+ if (this.currentScore_ == element) { return; }
+ if (this.currentScore_ != null) {
+ this.currentScore_.classList.remove('selected-score');
+ }
+ this.currentScore_ = element;
+ this.currentScore_.classList.add('selected-score');
+ this.stopAudio();
+
+ // Read metadata.
+ var matches = element.querySelectorAll('input[type=hidden]');
+ this.metadata_ = {};
+ for (var index = 0; index < matches.length; ++index) {
+ this.metadata_[matches[index].name] = matches[index].value;
+ }
+
+ // Show the audio inspector interface.
+ var container = element.parentNode.parentNode.parentNode.parentNode;
+ var audioInspectorPlaceholder = container.querySelector(
+ '.audio-inspector-placeholder');
+ this.moveInspector_(audioInspectorPlaceholder);
+};
+
+/**
+ * Stop playing audio.
+ */
+AudioInspector.prototype.stopAudio = function() {
+ console.info('Pausing audio play out.');
+ this.audioPlayer_.pause();
+};
+
+/**
+ * Show a text message using the snackbar.
+ */
+AudioInspector.prototype.showNotification_ = function(text) {
+ try {
+ this.snackbarContainer_.MaterialSnackbar.showSnackbar({
+ message: text, timeout: 2000});
+ } catch (e) {
+ // Fallback to an alert.
+ alert(text);
+ console.warn('Cannot use snackbar: "' + e + '"');
+ }
+}
+
+/**
+ * Move the audio inspector DOM node into the given parent.
+ * @param {DOMElement} newParentNode: New parent for the inspector.
+ */
+AudioInspector.prototype.moveInspector_ = function(newParentNode) {
+ newParentNode.appendChild(this.audioInspector_);
+};
+
+/**
+ * Play audio file from url.
+ * @param {string} metadataFieldName: Metadata field name.
+ */
+AudioInspector.prototype.playAudio = function(metadataFieldName) {
+ if (this.metadata_[metadataFieldName] == undefined) { return; }
+ if (this.metadata_[metadataFieldName] == 'None') {
+ alert('The selected stream was not used during the experiment.');
+ return;
+ }
+ this.stopAudio();
+ this.audioPlayer_.src = this.metadata_[metadataFieldName];
+ console.debug('Audio source URL: "' + this.audioPlayer_.src + '"');
+ this.audioPlayer_.play();
+ console.info('Playing out audio.');
+};
+
+/**
+ * Create hidden text areas to copy URLs.
+ *
+ * For each dialog, one text area is created since it is not possible to select
+ * text on a text area outside of the active dialog.
+ */
+AudioInspector.prototype.createTextAreasForCopy_ = function() {
+ var self = this;
+ document.querySelectorAll('dialog.mdl-dialog').forEach(function(element) {
+ var textArea = document.createElement("textarea");
+ textArea.classList.add('url-copy');
+ textArea.style.position = 'fixed';
+ textArea.style.bottom = 0;
+ textArea.style.left = 0;
+ textArea.style.width = '2em';
+ textArea.style.height = '2em';
+ textArea.style.border = 'none';
+ textArea.style.outline = 'none';
+ textArea.style.boxShadow = 'none';
+ textArea.style.background = 'transparent';
+ textArea.style.fontSize = '6px';
+ element.appendChild(textArea);
+ });
+}
+
+/**
+ * Create audio inspector.
+ */
+AudioInspector.prototype.createAudioInspector_ = function() {
+ var buttonIndex = 0;
+ function getButtonHtml(icon, toolTipText, caption, metadataFieldName) {
+ var buttonId = 'audioInspectorButton' + buttonIndex++;
+ html = caption == null ? '' : caption;
+ html += '<button class="mdl-button mdl-js-button mdl-button--icon ' +
+ 'mdl-js-ripple-effect" id="' + buttonId + '">' +
+ '<i class="material-icons">' + icon + '</i>' +
+ '<div class="mdl-tooltip" data-mdl-for="' + buttonId + '">' +
+ toolTipText +
+ '</div>';
+ if (metadataFieldName != null) {
+ html += '<input type="hidden" value="' + metadataFieldName + '">'
+ }
+ html += '</button>'
+
+ return html;
+ }
+
+ // TODO(alessiob): Add timeline and highlight current track by changing icon
+ // color.
+
+ this.audioInspector_ = document.createElement('div');
+ this.audioInspector_.classList.add('audio-inspector');
+ this.audioInspector_.innerHTML =
+ '<div class="mdl-grid">' +
+ '<div class="mdl-layout-spacer"></div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'Simulated echo', 'E<sub>in</sub>',
+ 'echo_filepath') +
+ '</div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('stop', 'Stop playing [S]', null, '__stop__') +
+ '</div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'Render stream', 'R<sub>in</sub>',
+ 'render_filepath') +
+ '</div>' +
+ '<div class="mdl-layout-spacer"></div>' +
+ '</div>' +
+ '<div class="mdl-grid">' +
+ '<div class="mdl-layout-spacer"></div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'Capture stream (APM input) [1]',
+ 'Y\'<sub>in</sub>', 'capture_filepath') +
+ '</div>' +
+ '<div class="mdl-cell mdl-cell--2-col"><strong>APM</strong></div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'APM output [2]', 'Y<sub>out</sub>',
+ 'apm_output_filepath') +
+ '</div>' +
+ '<div class="mdl-layout-spacer"></div>' +
+ '</div>' +
+ '<div class="mdl-grid">' +
+ '<div class="mdl-layout-spacer"></div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'Echo-free capture stream',
+ 'Y<sub>in</sub>', 'echo_free_capture_filepath') +
+ '</div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'Clean capture stream',
+ 'Y<sub>clean</sub>', 'clean_capture_input_filepath') +
+ '</div>' +
+ '<div class="mdl-cell mdl-cell--2-col">' +
+ getButtonHtml('play_arrow', 'APM reference [3]', 'Y<sub>ref</sub>',
+ 'apm_reference_filepath') +
+ '</div>' +
+ '<div class="mdl-layout-spacer"></div>' +
+ '</div>';
+
+ // Add an invisible node as initial container for the audio inspector.
+ var parent = document.createElement('div');
+ parent.style.display = 'none';
+ this.moveInspector_(parent);
+ document.body.appendChild(parent);
+};
+
+/**
+ * Initialize event handlers.
+ */
+AudioInspector.prototype.initializeEventHandlers_ = function() {
+ var self = this;
+
+ // Score cells.
+ document.querySelectorAll('td.single-score-cell').forEach(function(element) {
+ element.onclick = function() {
+ self.selectedScoreChange(this);
+ }
+ });
+
+ // Copy anchor URLs icons.
+ if (document.queryCommandSupported('copy')) {
+ document.querySelectorAll('td.single-score-cell button').forEach(
+ function(element) {
+ element.onclick = function() {
+ // Find the text area in the dialog.
+ var textArea = element.closest('dialog').querySelector(
+ 'textarea.url-copy');
+
+ // Copy.
+ textArea.value = self.baseUrl_ + '#' + element.getAttribute(
+ 'data-anchor');
+ textArea.select();
+ try {
+ if (!document.execCommand('copy'))
+ throw 'Copy returned false';
+ self.showNotification_('Experiment URL copied.');
+ } catch (e) {
+ self.showNotification_('Cannot copy experiment URL :(');
+ console.error(e);
+ }
+ }
+ });
+ } else {
+ self.showNotification_(
+ 'The copy command is disabled. URL copy is not enabled.');
+ }
+
+ // Audio inspector buttons.
+ this.audioInspector_.querySelectorAll('button').forEach(function(element) {
+ var target = element.querySelector('input[type=hidden]');
+ if (target == null) { return; }
+ element.onclick = function() {
+ if (target.value == '__stop__') {
+ self.stopAudio();
+ } else {
+ self.playAudio(target.value);
+ }
+ };
+ });
+
+ // Dialog close handlers.
+ var dialogs = document.querySelectorAll('dialog').forEach(function(element) {
+ element.onclose = function() {
+ self.stopAudio();
+ }
+ });
+
+ // Keyboard shortcuts.
+ window.onkeyup = function(e) {
+ var key = e.keyCode ? e.keyCode : e.which;
+ switch (key) {
+ case 49: // 1.
+ self.playAudio('capture_filepath');
+ break;
+ case 50: // 2.
+ self.playAudio('apm_output_filepath');
+ break;
+ case 51: // 3.
+ self.playAudio('apm_reference_filepath');
+ break;
+ case 83: // S.
+ case 115: // s.
+ self.stopAudio();
+ break;
+ }
+ };
+
+ // Hash change.
+ window.onhashchange = function(e) {
+ self.parseWindowAnchor();
+ }
+};