From fbd4f85f2dab93d819e42d1b1dfc6e2b2125ddf2 Mon Sep 17 00:00:00 2001 From: alessiob Date: Tue, 4 Apr 2017 06:59:14 -0700 Subject: [PATCH] Javascript audio player for the exported HTML file. BUG=webrtc:7218 NOTRY=True Review-Url: https://codereview.webrtc.org/2721023002 Cr-Commit-Position: refs/heads/master@{#17529} --- .../test/py_quality_assessment/BUILD.gn | 1 + .../apm_quality_assessment_export.py | 4 +- .../quality_assessment/export.py | 29 ++- .../quality_assessment/results.css | 30 +++ .../quality_assessment/results.js | 186 ++++++++++++++++++ 5 files changed, 243 insertions(+), 7 deletions(-) create mode 100644 webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/BUILD.gn b/webrtc/modules/audio_processing/test/py_quality_assessment/BUILD.gn index 81ef562837..3f2fc418ca 100644 --- a/webrtc/modules/audio_processing/test/py_quality_assessment/BUILD.gn +++ b/webrtc/modules/audio_processing/test/py_quality_assessment/BUILD.gn @@ -46,6 +46,7 @@ copy("lib") { "quality_assessment/noise_generation_factory.py", "quality_assessment/noise_generation_unittest.py", "quality_assessment/results.css", + "quality_assessment/results.js", "quality_assessment/signal_processing.py", "quality_assessment/signal_processing_unittest.py", "quality_assessment/simulation.py", diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/apm_quality_assessment_export.py b/webrtc/modules/audio_processing/test/py_quality_assessment/apm_quality_assessment_export.py index 1b2fe36c52..350a5da379 100755 --- a/webrtc/modules/audio_processing/test/py_quality_assessment/apm_quality_assessment_export.py +++ b/webrtc/modules/audio_processing/test/py_quality_assessment/apm_quality_assessment_export.py @@ -134,8 +134,8 @@ def main(): score_path, _ = os.path.split(score_filepath) audio_in_filepath, audio_ref_filepath = ( data_access.Metadata.load_audio_in_ref_paths(score_path)) - audio_out_filepath = os.path.join( - score_path, audioproc_wrapper.AudioProcWrapper.OUTPUT_FILENAME) + audio_out_filepath = os.path.abspath(os.path.join( + score_path, audioproc_wrapper.AudioProcWrapper.OUTPUT_FILENAME)) # Add the score to the nested dictionary. scores[score_name][config_name][input_name][noise_name][noise_params] = { diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/export.py b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/export.py index 4b025023a3..a0cb41148d 100644 --- a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/export.py +++ b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/export.py @@ -18,7 +18,11 @@ class HtmlExport(object): # CSS file parameters. _CSS_FILEPATH = os.path.join(_PATH, 'results.css') - _INLINE_CSS = True + _INLINE_CSS = False + + # JS file parameters. + _JS_FILEPATH = os.path.join(_PATH, 'results.js') + _INLINE_JS = False _NEW_LINE = '\n' @@ -43,7 +47,7 @@ class HtmlExport(object): html = ( '' + self._build_header() + - '' + + '' + '

Results from {}

'.format(self._output_filepath) + self._NEW_LINE.join(tables) + '' + @@ -58,19 +62,34 @@ class HtmlExport(object): """ html = ['', 'Results'] + # Function to append the lines of a text file to html. + def _embed_file(filepath): + with open(filepath) as f: + for l in f: + html.append(l.strip()) + # CSS. if self._INLINE_CSS: # Embed. html.append('') else: # Link. html.append(''.format(self._CSS_FILEPATH)) + # Javascript. + if self._INLINE_JS: + # Embed. + html.append('') + else: + # Link. + html.append(''.format( + self._JS_FILEPATH)) + html.append('') return self._NEW_LINE.join(html) diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.css b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.css index 313b7111dc..bae25a3489 100644 --- a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.css +++ b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.css @@ -58,3 +58,33 @@ table tbody tr td .value{ padding: 1px; font-size: 0.8em; } + +.inspector{ + background-color: #FFF; + border: 3px solid #000; + display: block; + padding: 0.5em; + position: fixed; + right: 1em; + top: 1em; +} + +.inspector .property{ + margin-bottom: 1em; +} + +.inspector .property .name{ + font-weight: bold; +} + +.inspector .property .value{ + padding-left: 0.5em; +} + +.inspector .buttons{ + margin-top: 1em; +} + +.inspector .buttons button{ + margin: 0 0.25em; +} diff --git a/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js new file mode 100644 index 0000000000..68e4ff93ac --- /dev/null +++ b/webrtc/modules/audio_processing/test/py_quality_assessment/quality_assessment/results.js @@ -0,0 +1,186 @@ +// 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. + +/** + * Inspector UI class. + * @constructor + */ +function Inspector() { + this.audioPlayer_ = new Audio(); + this.inspectorNode_ = document.createElement('div'); + this.divNoiseGenerator_ = document.createElement('div'); + this.divNoiseParameters_ = document.createElement('div'); + this.buttonPlayAudioIn_ = document.createElement('button'); + this.buttonPlayAudioOut_ = document.createElement('button'); + this.buttonPlayAudioRef_ = document.createElement('button'); + this.buttonStopAudio_ = document.createElement('button'); + + this.selectedItem_ = null; + this.audioInUrl_ = null; + this.audioOutUrl_ = null; + this.audioRefUrl_ = null; +} + +/** + * Initialize. + */ +Inspector.prototype.init = function() { + window.event.stopPropagation(); + + // Create inspector UI. + this.buildInspector_(); + var body = document.getElementsByTagName('body')[0]; + body.appendChild(this.inspectorNode_); + + // Bind click handler. + var self = this; + var items = document.getElementsByClassName('score'); + for (var index = 0; index < items.length; index++) { + items[index].onclick = function() { + self.openInspector(this); + }; + } + + // Bind pressed key handlers. + var self = this; + window.onkeyup = function(e) { + var key = e.keyCode ? e.keyCode : e.which; + switch (key) { + case 49: // 1. + self.playAudioIn(); + break; + case 50: // 2. + self.playAudioOut(); + break; + case 51: // 3. + self.playAudioRef(); + break; + case 83: // S. + case 115: // s. + self.stopAudio(); + break; + } + }; +}; + +/** + * Open the inspector. + * @param {DOMElement} target: score element that has been clicked. + */ +Inspector.prototype.openInspector = function(target) { + if (this.selectedItem_ != null) { + this.selectedItem_.classList.remove('selected'); + } + this.selectedItem_ = target; + this.selectedItem_.classList.add('selected'); + + var target = this.selectedItem_.querySelector('.noise-desc'); + var noiseName = target.querySelector('input[name=noise_name]').value; + var noiseParams = target.querySelector('input[name=noise_params]').value; + var audioIn = target.querySelector('input[name=audio_in]').value; + var audioOut = target.querySelector('input[name=audio_out]').value; + var audioRef = target.querySelector('input[name=audio_ref]').value; + + this.divNoiseGenerator_.innerHTML = noiseName; + this.divNoiseParameters_.innerHTML = noiseParams; + + this.audioInUrl_ = audioIn; + this.audioOutUrl_ = audioOut; + this.audioRefUrl_ = audioRef; +}; + +/** + * Play APM audio input signal. + */ +Inspector.prototype.playAudioIn = function() { + this.play_(this.audioInUrl_); +}; + +/** + * Play APM audio output signal. + */ +Inspector.prototype.playAudioOut = function() { + this.play_(this.audioOutUrl_); +}; + +/** + * Play APM audio reference signal. + */ +Inspector.prototype.playAudioRef = function() { + this.play_(this.audioRefUrl_); +}; + +/** + * Stop playing audio. + */ +Inspector.prototype.stopAudio = function() { + this.audioPlayer_.pause(); +}; + +/** + * Play audio file from url. + * @param {string} url + */ +Inspector.prototype.play_ = function(url) { + if (url == null) { + alert('Select a score first.'); + return; + } + + this.audioPlayer_.src = url; + this.audioPlayer_.play(); +}; + +/** + * Build inspector. + */ +Inspector.prototype.buildInspector_ = function() { + var self = this; + + this.inspectorNode_.setAttribute('class', 'inspector'); + this.inspectorNode_.innerHTML = '
' + + '
noise generator
' + + '
' + + '
' + + '
parameters
' + + '
' + + '
'; + + // Add value nodes. + function addValueNode(node, parent_selector) { + node.setAttribute('class', 'value'); + node.innerHTML = '-'; + var parentNode = self.inspectorNode_.querySelector(parent_selector); + parentNode.appendChild(node); + } + addValueNode(this.divNoiseGenerator_, 'div.noise-generator'); + addValueNode(this.divNoiseParameters_, 'div.noise-parmas'); + + // Add buttons. + var buttonsNode = this.inspectorNode_.querySelector('div.buttons'); + function addButton(node, caption, callback) { + node.innerHTML = caption; + buttonsNode.appendChild(node); + node.onclick = callback.bind(self); + } + addButton(this.buttonPlayAudioIn_, 'A_in (1)', + this.playAudioIn); + addButton(this.buttonPlayAudioOut_, 'A_out (2)', + this.playAudioOut); + addButton(this.buttonPlayAudioRef_, 'A_ref (3)', + this.playAudioRef); + addButton(this.buttonStopAudio_, 'Stop', this.stopAudio); +}; + +/** + * Instance and initialize the inspector. + */ +function initialize() { + var inspector = new Inspector(); + inspector.init(); +}