summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorBen Zhang <benzh@chromium.org>2016-08-09 19:55:36 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-08-11 12:24:44 -0700
commitb826967966bfab552d80d0609f9830eec9905c13 (patch)
treeb91be8ce3b0068643d810b6b9e924cf9b91afb4d /scripts
parent31ad060013574bbf3cec5e20c63e6b3c0986ab1b (diff)
downloadadhd-b826967966bfab552d80d0609f9830eec9905c13.tar.gz
scripts: Fix audio-tuning frontend with new WebAudio biquad filter implementation
The spec of WebAudio biquad filter "lowpass" and "highpass" has been changed. Chrome's implementation was changed in 53.0.2768.0. The new implementation uses the Audio EQ Cookbook formula, different from the original one, but still expects Q in dB. See https://github.com/WebAudio/web-audio-api/issues/771 This patch adds detection of the filter implementation. If the browser uses the new formula, conversion of Q is made to simulate the original filter frequency response with the new formula. This ensures the audio-tuning playback is always consistent with the current CRAS DSP implementation, on any browser verion. BUG=chrome-os-partner:55365 TEST=DRC/EQ testing on Chrome before/after the filter change Change-Id: I3e67a9b87f94b228d173fa08dcaa0fe4df5ac64e Signed-off-by: Ben Zhang <benzh@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/367551 Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/audio_tuning/frontend/audio.js83
1 files changed, 73 insertions, 10 deletions
diff --git a/scripts/audio_tuning/frontend/audio.js b/scripts/audio_tuning/frontend/audio.js
index c8f393ae..2476f1a9 100644
--- a/scripts/audio_tuning/frontend/audio.js
+++ b/scripts/audio_tuning/frontend/audio.js
@@ -117,6 +117,58 @@ var analyzer_right; /* The FFT analyzer for right channel */
* The detection result will be stored in this value. When user saves config,
* This value is stored in drc.emphasis_disabled in the config. */
var browser_emphasis_disabled_detection_result;
+/* check_biquad_filter_q detects if the browser implements the lowpass and
+ * highpass biquad filters with the original formula or the new formula from
+ * Audio EQ Cookbook. Chrome changed the filter implementation in R53, see:
+ * https://github.com/GoogleChrome/web-audio-samples/wiki/Detection-of-lowpass-BiquadFilter-implementation
+ * The detection result is saved in this value before the page is initialized.
+ * make_biquad_q() uses this value to compute Q to ensure consistent behavior
+ * on different browser versions.
+ */
+var browser_biquad_filter_uses_audio_cookbook_formula;
+
+/* Check the lowpass implementation and return a promise. */
+function check_biquad_filter_q() {
+ 'use strict';
+ var context = new OfflineAudioContext(1, 128, 48000);
+ var osc = context.createOscillator();
+ var filter1 = context.createBiquadFilter();
+ var filter2 = context.createBiquadFilter();
+ var inverter = context.createGain();
+
+ osc.type = 'sawtooth';
+ osc.frequency.value = 8 * 440;
+ inverter.gain.value = -1;
+ /* each filter should get a different Q value */
+ filter1.Q.value = -1;
+ filter2.Q.value = -20;
+ osc.connect(filter1);
+ osc.connect(filter2);
+ filter1.connect(context.destination);
+ filter2.connect(inverter);
+ inverter.connect(context.destination);
+ osc.start();
+
+ return context.startRendering().then(function (buffer) {
+ return browser_biquad_filter_uses_audio_cookbook_formula =
+ Math.max(...buffer.getChannelData(0)) !== 0;
+ });
+}
+
+/* Return the Q value to be used with the lowpass and highpass biquad filters,
+ * given Q in dB for the original filter formula. If the browser uses the new
+ * formula, conversion is made to simulate the original frequency response
+ * with the new formula.
+ */
+function make_biquad_q(q_db) {
+ if (!browser_biquad_filter_uses_audio_cookbook_formula)
+ return q_db;
+
+ var q_lin = dBToLinear(q_db);
+ var q_new = 1 / Math.sqrt((4 - Math.sqrt(16 - 16 / (q_lin * q_lin))) / 2);
+ q_new = linearToDb(q_new);
+ return q_new;
+}
/* The supported audio element names are different on browsers with different
* versions.*/
@@ -506,7 +558,10 @@ function eq() {
filter.frequency.value = parseFloat(value);
break;
case 'q':
- filter.Q.value = parseFloat(value);
+ value = parseFloat(value);
+ if (filter.type == 'lowpass' || filter.type == 'highpass')
+ value = make_biquad_q(value);
+ filter.Q.value = value;
break;
case 'gain':
filter.gain.value = parseFloat(value);
@@ -837,7 +892,7 @@ function create_lowpass(freq) {
var lp = audioContext.createBiquadFilter();
lp.type = 'lowpass';
lp.frequency.value = freq;
- lp.Q.value = 0;
+ lp.Q.value = make_biquad_q(0);
return lp;
}
@@ -846,7 +901,7 @@ function create_highpass(freq) {
var hp = audioContext.createBiquadFilter();
hp.type = 'highpass';
hp.frequency.value = freq;
- hp.Q.value = 0;
+ hp.Q.value = make_biquad_q(0);
return hp;
}
@@ -1438,12 +1493,17 @@ function global_section(parent) {
window.onload = function() {
fix_audio_elements();
- /* Detects if emphasis is disabled and sets
- * browser_emphasis_disabled_detection_result. */
- get_emphasis_disabled();
- init_config();
- init_audio();
- init_ui();
+ check_biquad_filter_q().then(function (flag) {
+ console.log('Browser biquad filter uses Audio Cookbook formula:', flag);
+ /* Detects if emphasis is disabled and sets
+ * browser_emphasis_disabled_detection_result. */
+ get_emphasis_disabled();
+ init_config();
+ init_audio();
+ init_ui();
+ }).catch(function (reason) {
+ alert('Cannot detect browser biquad filter implementation:', reason);
+ });
};
function init_ui() {
@@ -1760,7 +1820,10 @@ function EqDrawer(canvas, channel) {
}
filter.type = get_config('eq', channel, i, 'type');
filter.frequency.value = centerFreq[i];
- filter.Q.value = q[i];
+ if (filter.type == 'lowpass' || filter.type == 'highpass')
+ filter.Q.value = make_biquad_q(q[i]);
+ else
+ filter.Q.value = q[i];
filter.gain.value = gain[i];
filter.getFrequencyResponse(frequencyHz, magResponse,
phaseResponse);