summaryrefslogtreecommitdiff
path: root/scripts/audio_tuning/frontend/audio.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/audio_tuning/frontend/audio.js')
-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);