Index: third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js |
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js b/third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js |
index 4cdaeccafba374c566812f8d00b786b83c6a8c2e..61f38c97c27b76b51c200d561e67e247e251f44c 100644 |
--- a/third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js |
+++ b/third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js |
@@ -7,363 +7,370 @@ |
// Lowpass filter. |
function createLowpassFilter(freq, q, gain) { |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- |
- if (freq == 1) { |
- // The formula below works, except for roundoff. When freq = 1, |
- // the filter is just a wire, so hardwire the coefficients. |
- b0 = 1; |
- b1 = 0; |
- b2 = 0; |
- a0 = 1; |
- a1 = 0; |
- a2 = 0; |
- } else { |
- var theta = Math.PI * freq; |
- var alpha = Math.sin(theta) / (2 * Math.pow(10, q / 20)); |
- var cosw = Math.cos(theta); |
- var beta = (1 - cosw) / 2; |
- |
- b0 = beta; |
- b1 = 2 * beta; |
- b2 = beta; |
- a0 = 1 + alpha; |
- a1 = -2 * cosw; |
- a2 = 1 - alpha; |
- } |
- |
- return normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ |
+ if (freq == 1) { |
+ // The formula below works, except for roundoff. When freq = 1, |
+ // the filter is just a wire, so hardwire the coefficients. |
+ b0 = 1; |
+ b1 = 0; |
+ b2 = 0; |
+ a0 = 1; |
+ a1 = 0; |
+ a2 = 0; |
+ } else { |
+ let theta = Math.PI * freq; |
+ let alpha = Math.sin(theta) / (2 * Math.pow(10, q / 20)); |
+ let cosw = Math.cos(theta); |
+ let beta = (1 - cosw) / 2; |
+ |
+ b0 = beta; |
+ b1 = 2 * beta; |
+ b2 = beta; |
+ a0 = 1 + alpha; |
+ a1 = -2 * cosw; |
+ a2 = 1 - alpha; |
+ } |
+ |
+ return normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
} |
function createHighpassFilter(freq, q, gain) { |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- |
- if (freq == 1) { |
- // The filter is 0 |
- b0 = 0; |
- b1 = 0; |
- b2 = 0; |
- a0 = 1; |
- a1 = 0; |
- a2 = 0; |
- } else if (freq == 0) { |
- // The filter is 1. Computation of coefficients below is ok, but |
- // there's a pole at 1 and a zero at 1, so round-off could make |
- // the filter unstable. |
- b0 = 1; |
- b1 = 0; |
- b2 = 0; |
- a0 = 1; |
- a1 = 0; |
- a2 = 0; |
- } else { |
- var theta = Math.PI * freq; |
- var alpha = Math.sin(theta) / (2 * Math.pow(10, q / 20)); |
- var cosw = Math.cos(theta); |
- var beta = (1 + cosw) / 2; |
- |
- b0 = beta; |
- b1 = -2 * beta; |
- b2 = beta; |
- a0 = 1 + alpha; |
- a1 = -2 * cosw; |
- a2 = 1 - alpha; |
- } |
- |
- return normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ |
+ if (freq == 1) { |
+ // The filter is 0 |
+ b0 = 0; |
+ b1 = 0; |
+ b2 = 0; |
+ a0 = 1; |
+ a1 = 0; |
+ a2 = 0; |
+ } else if (freq == 0) { |
+ // The filter is 1. Computation of coefficients below is ok, but |
+ // there's a pole at 1 and a zero at 1, so round-off could make |
+ // the filter unstable. |
+ b0 = 1; |
+ b1 = 0; |
+ b2 = 0; |
+ a0 = 1; |
+ a1 = 0; |
+ a2 = 0; |
+ } else { |
+ let theta = Math.PI * freq; |
+ let alpha = Math.sin(theta) / (2 * Math.pow(10, q / 20)); |
+ let cosw = Math.cos(theta); |
+ let beta = (1 + cosw) / 2; |
+ |
+ b0 = beta; |
+ b1 = -2 * beta; |
+ b2 = beta; |
+ a0 = 1 + alpha; |
+ a1 = -2 * cosw; |
+ a2 = 1 - alpha; |
+ } |
+ |
+ return normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
} |
function normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2) { |
- var scale = 1 / a0; |
- |
- return {b0 : b0 * scale, |
- b1 : b1 * scale, |
- b2 : b2 * scale, |
- a1 : a1 * scale, |
- a2 : a2 * scale}; |
+ let scale = 1 / a0; |
+ |
+ return { |
+ b0: b0 * scale, |
+ b1: b1 * scale, |
+ b2: b2 * scale, |
+ a1: a1 * scale, |
+ a2: a2 * scale |
+ }; |
} |
function createBandpassFilter(freq, q, gain) { |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- var coef; |
- |
- if (freq > 0 && freq < 1) { |
- var w0 = Math.PI * freq; |
- if (q > 0) { |
- var alpha = Math.sin(w0) / (2 * q); |
- var k = Math.cos(w0); |
- |
- b0 = alpha; |
- b1 = 0; |
- b2 = -alpha; |
- a0 = 1 + alpha; |
- a1 = -2 * k; |
- a2 = 1 - alpha; |
- |
- coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
- } else { |
- // q = 0, and frequency is not 0 or 1. The above formula has a |
- // divide by zero problem. The limit of the z-transform as q |
- // approaches 0 is 1, so set the filter that way. |
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ let coef; |
+ |
+ if (freq > 0 && freq < 1) { |
+ let w0 = Math.PI * freq; |
+ if (q > 0) { |
+ let alpha = Math.sin(w0) / (2 * q); |
+ let k = Math.cos(w0); |
+ |
+ b0 = alpha; |
+ b1 = 0; |
+ b2 = -alpha; |
+ a0 = 1 + alpha; |
+ a1 = -2 * k; |
+ a2 = 1 - alpha; |
+ |
+ coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
} else { |
- // When freq = 0 or 1, the z-transform is identically 0, |
- // independent of q. |
- coef = {b0 : 0, b1 : 0, b2 : 0, a1 : 0, a2 : 0} |
+ // q = 0, and frequency is not 0 or 1. The above formula has a |
+ // divide by zero problem. The limit of the z-transform as q |
+ // approaches 0 is 1, so set the filter that way. |
+ coef = {b0: 1, b1: 0, b2: 0, a1: 0, a2: 0}; |
} |
+ } else { |
+ // When freq = 0 or 1, the z-transform is identically 0, |
+ // independent of q. |
+ coef = { b0: 0, b1: 0, b2: 0, a1: 0, a2: 0 } |
+ } |
- return coef; |
+ return coef; |
} |
function createLowShelfFilter(freq, q, gain) { |
- // q not used |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- var coef; |
- |
- var S = 1; |
- var A = Math.pow(10, gain / 40); |
- |
- if (freq == 1) { |
- // The filter is just a constant gain |
- coef = {b0 : A * A, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } else if (freq == 0) { |
- // The filter is 1 |
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } else { |
- var w0 = Math.PI * freq; |
- var alpha = 1 / 2 * Math.sin(w0) * Math.sqrt((A + 1 / A) * (1 / S - 1) + 2); |
- var k = Math.cos(w0); |
- var k2 = 2 * Math.sqrt(A) * alpha; |
- var Ap1 = A + 1; |
- var Am1 = A - 1; |
- |
- b0 = A * (Ap1 - Am1 * k + k2); |
- b1 = 2 * A * (Am1 - Ap1 * k); |
- b2 = A * (Ap1 - Am1 * k - k2); |
- a0 = Ap1 + Am1 * k + k2; |
- a1 = -2 * (Am1 + Ap1 * k); |
- a2 = Ap1 + Am1 * k - k2; |
- coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
- } |
- |
- return coef; |
+ // q not used |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ let coef; |
+ |
+ let S = 1; |
+ let A = Math.pow(10, gain / 40); |
+ |
+ if (freq == 1) { |
+ // The filter is just a constant gain |
+ coef = {b0: A * A, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } else if (freq == 0) { |
+ // The filter is 1 |
+ coef = {b0: 1, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } else { |
+ let w0 = Math.PI * freq; |
+ let alpha = 1 / 2 * Math.sin(w0) * Math.sqrt((A + 1 / A) * (1 / S - 1) + 2); |
+ let k = Math.cos(w0); |
+ let k2 = 2 * Math.sqrt(A) * alpha; |
+ let Ap1 = A + 1; |
+ let Am1 = A - 1; |
+ |
+ b0 = A * (Ap1 - Am1 * k + k2); |
+ b1 = 2 * A * (Am1 - Ap1 * k); |
+ b2 = A * (Ap1 - Am1 * k - k2); |
+ a0 = Ap1 + Am1 * k + k2; |
+ a1 = -2 * (Am1 + Ap1 * k); |
+ a2 = Ap1 + Am1 * k - k2; |
+ coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
+ } |
+ |
+ return coef; |
} |
function createHighShelfFilter(freq, q, gain) { |
- // q not used |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- var coef; |
- |
- var A = Math.pow(10, gain / 40); |
- |
- if (freq == 1) { |
- // When freq = 1, the z-transform is 1 |
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } else if (freq > 0) { |
- var w0 = Math.PI * freq; |
- var S = 1; |
- var alpha = 0.5 * Math.sin(w0) * Math.sqrt((A + 1 / A) * (1 / S - 1) + 2); |
- var k = Math.cos(w0); |
- var k2 = 2 * Math.sqrt(A) * alpha; |
- var Ap1 = A + 1; |
- var Am1 = A - 1; |
- |
- b0 = A * (Ap1 + Am1 * k + k2); |
- b1 = -2 * A * (Am1 + Ap1 * k); |
- b2 = A * (Ap1 + Am1 * k - k2); |
- a0 = Ap1 - Am1 * k + k2; |
- a1 = 2 * (Am1 - Ap1*k); |
- a2 = Ap1 - Am1 * k-k2; |
- |
- coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
- } else { |
- // When freq = 0, the filter is just a gain |
- coef = {b0 : A * A, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } |
- |
- return coef; |
+ // q not used |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ let coef; |
+ |
+ let A = Math.pow(10, gain / 40); |
+ |
+ if (freq == 1) { |
+ // When freq = 1, the z-transform is 1 |
+ coef = {b0: 1, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } else if (freq > 0) { |
+ let w0 = Math.PI * freq; |
+ let S = 1; |
+ let alpha = 0.5 * Math.sin(w0) * Math.sqrt((A + 1 / A) * (1 / S - 1) + 2); |
+ let k = Math.cos(w0); |
+ let k2 = 2 * Math.sqrt(A) * alpha; |
+ let Ap1 = A + 1; |
+ let Am1 = A - 1; |
+ |
+ b0 = A * (Ap1 + Am1 * k + k2); |
+ b1 = -2 * A * (Am1 + Ap1 * k); |
+ b2 = A * (Ap1 + Am1 * k - k2); |
+ a0 = Ap1 - Am1 * k + k2; |
+ a1 = 2 * (Am1 - Ap1 * k); |
+ a2 = Ap1 - Am1 * k - k2; |
+ |
+ coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
+ } else { |
+ // When freq = 0, the filter is just a gain |
+ coef = {b0: A * A, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } |
+ |
+ return coef; |
} |
function createPeakingFilter(freq, q, gain) { |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- var coef; |
- |
- var A = Math.pow(10, gain / 40); |
- |
- if (freq > 0 && freq < 1) { |
- if (q > 0) { |
- var w0 = Math.PI * freq; |
- var alpha = Math.sin(w0) / (2 * q); |
- var k = Math.cos(w0); |
- |
- b0 = 1 + alpha * A; |
- b1 = -2 * k; |
- b2 = 1 - alpha * A; |
- a0 = 1 + alpha / A; |
- a1 = -2 * k; |
- a2 = 1 - alpha / A; |
- |
- coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
- } else { |
- // q = 0, we have a divide by zero problem in the formulas |
- // above. But if we look at the z-transform, we see that the |
- // limit as q approaches 0 is A^2. |
- coef = {b0 : A * A, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ let coef; |
+ |
+ let A = Math.pow(10, gain / 40); |
+ |
+ if (freq > 0 && freq < 1) { |
+ if (q > 0) { |
+ let w0 = Math.PI * freq; |
+ let alpha = Math.sin(w0) / (2 * q); |
+ let k = Math.cos(w0); |
+ |
+ b0 = 1 + alpha * A; |
+ b1 = -2 * k; |
+ b2 = 1 - alpha * A; |
+ a0 = 1 + alpha / A; |
+ a1 = -2 * k; |
+ a2 = 1 - alpha / A; |
+ |
+ coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
} else { |
- // freq = 0 or 1, the z-transform is 1 |
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
+ // q = 0, we have a divide by zero problem in the formulas |
+ // above. But if we look at the z-transform, we see that the |
+ // limit as q approaches 0 is A^2. |
+ coef = {b0: A * A, b1: 0, b2: 0, a1: 0, a2: 0}; |
} |
+ } else { |
+ // freq = 0 or 1, the z-transform is 1 |
+ coef = {b0: 1, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } |
- return coef; |
+ return coef; |
} |
function createNotchFilter(freq, q, gain) { |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- var coef; |
- |
- if (freq > 0 && freq < 1) { |
- if (q > 0) { |
- var w0 = Math.PI * freq; |
- var alpha = Math.sin(w0) / (2 * q); |
- var k = Math.cos(w0); |
- |
- b0 = 1; |
- b1 = -2 * k; |
- b2 = 1; |
- a0 = 1 + alpha; |
- a1 = -2 * k; |
- a2 = 1 - alpha; |
- coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
- } else { |
- // When q = 0, we get a divide by zero above. The limit of the |
- // z-transform as q approaches 0 is 0, so set the coefficients |
- // appropriately. |
- coef = {b0 : 0, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ let coef; |
+ |
+ if (freq > 0 && freq < 1) { |
+ if (q > 0) { |
+ let w0 = Math.PI * freq; |
+ let alpha = Math.sin(w0) / (2 * q); |
+ let k = Math.cos(w0); |
+ |
+ b0 = 1; |
+ b1 = -2 * k; |
+ b2 = 1; |
+ a0 = 1 + alpha; |
+ a1 = -2 * k; |
+ a2 = 1 - alpha; |
+ coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
} else { |
- // When freq = 0 or 1, the z-transform is 1 |
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
+ // When q = 0, we get a divide by zero above. The limit of the |
+ // z-transform as q approaches 0 is 0, so set the coefficients |
+ // appropriately. |
+ coef = {b0: 0, b1: 0, b2: 0, a1: 0, a2: 0}; |
} |
+ } else { |
+ // When freq = 0 or 1, the z-transform is 1 |
+ coef = {b0: 1, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } |
- return coef; |
+ return coef; |
} |
function createAllpassFilter(freq, q, gain) { |
- var b0; |
- var b1; |
- var b2; |
- var a0; |
- var a1; |
- var a2; |
- var coef; |
- |
- if (freq > 0 && freq < 1) { |
- if (q > 0) { |
- var w0 = Math.PI * freq; |
- var alpha = Math.sin(w0) / (2 * q); |
- var k = Math.cos(w0); |
- |
- b0 = 1 - alpha; |
- b1 = -2 * k; |
- b2 = 1 + alpha; |
- a0 = 1 + alpha; |
- a1 = -2 * k; |
- a2 = 1 - alpha; |
- coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
- } else { |
- // q = 0 |
- coef = {b0 : -1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
- } |
+ let b0; |
+ let b1; |
+ let b2; |
+ let a0; |
+ let a1; |
+ let a2; |
+ let coef; |
+ |
+ if (freq > 0 && freq < 1) { |
+ if (q > 0) { |
+ let w0 = Math.PI * freq; |
+ let alpha = Math.sin(w0) / (2 * q); |
+ let k = Math.cos(w0); |
+ |
+ b0 = 1 - alpha; |
+ b1 = -2 * k; |
+ b2 = 1 + alpha; |
+ a0 = 1 + alpha; |
+ a1 = -2 * k; |
+ a2 = 1 - alpha; |
+ coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
} else { |
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0}; |
+ // q = 0 |
+ coef = {b0: -1, b1: 0, b2: 0, a1: 0, a2: 0}; |
} |
+ } else { |
+ coef = {b0: 1, b1: 0, b2: 0, a1: 0, a2: 0}; |
+ } |
- return coef; |
+ return coef; |
} |
function filterData(filterCoef, signal, len) { |
- var y = new Array(len); |
- var b0 = filterCoef.b0; |
- var b1 = filterCoef.b1; |
- var b2 = filterCoef.b2; |
- var a1 = filterCoef.a1; |
- var a2 = filterCoef.a2; |
- |
- // Prime the pump. (Assumes the signal has length >= 2!) |
- y[0] = b0 * signal[0]; |
- y[1] = b0 * signal[1] + b1 * signal[0] - a1 * y[0]; |
- |
- // Filter all of the signal that we have. |
- for (var k = 2; k < Math.min(signal.length, len); ++k) { |
- y[k] = b0 * signal[k] + b1 * signal[k-1] + b2 * signal[k-2] - a1 * y[k-1] - a2 * y[k-2]; |
- } |
- |
- // If we need to filter more, but don't have any signal left, |
- // assume the signal is zero. |
- for (var k = signal.length; k < len; ++k) { |
- y[k] = - a1 * y[k-1] - a2 * y[k-2]; |
- } |
- |
- return y; |
+ let y = new Array(len); |
+ let b0 = filterCoef.b0; |
+ let b1 = filterCoef.b1; |
+ let b2 = filterCoef.b2; |
+ let a1 = filterCoef.a1; |
+ let a2 = filterCoef.a2; |
+ |
+ // Prime the pump. (Assumes the signal has length >= 2!) |
+ y[0] = b0 * signal[0]; |
+ y[1] = b0 * signal[1] + b1 * signal[0] - a1 * y[0]; |
+ |
+ // Filter all of the signal that we have. |
+ for (let k = 2; k < Math.min(signal.length, len); ++k) { |
+ y[k] = b0 * signal[k] + b1 * signal[k - 1] + b2 * signal[k - 2] - |
+ a1 * y[k - 1] - a2 * y[k - 2]; |
+ } |
+ |
+ // If we need to filter more, but don't have any signal left, |
+ // assume the signal is zero. |
+ for (let k = signal.length; k < len; ++k) { |
+ y[k] = -a1 * y[k - 1] - a2 * y[k - 2]; |
+ } |
+ |
+ return y; |
} |
-// Map the filter type name to a function that computes the filter coefficents for the given filter |
-// type. |
-var filterCreatorFunction = {"lowpass": createLowpassFilter, |
- "highpass": createHighpassFilter, |
- "bandpass": createBandpassFilter, |
- "lowshelf": createLowShelfFilter, |
- "highshelf": createHighShelfFilter, |
- "peaking": createPeakingFilter, |
- "notch": createNotchFilter, |
- "allpass": createAllpassFilter}; |
- |
-var filterTypeName = {"lowpass": "Lowpass filter", |
- "highpass": "Highpass filter", |
- "bandpass": "Bandpass filter", |
- "lowshelf": "Lowshelf filter", |
- "highshelf": "Highshelf filter", |
- "peaking": "Peaking filter", |
- "notch": "Notch filter", |
- "allpass": "Allpass filter"}; |
+// Map the filter type name to a function that computes the filter coefficents |
+// for the given filter type. |
+var filterCreatorFunction = { |
+ 'lowpass': createLowpassFilter, |
+ 'highpass': createHighpassFilter, |
+ 'bandpass': createBandpassFilter, |
+ 'lowshelf': createLowShelfFilter, |
+ 'highshelf': createHighShelfFilter, |
+ 'peaking': createPeakingFilter, |
+ 'notch': createNotchFilter, |
+ 'allpass': createAllpassFilter |
+}; |
+ |
+var filterTypeName = { |
+ 'lowpass': 'Lowpass filter', |
+ 'highpass': 'Highpass filter', |
+ 'bandpass': 'Bandpass filter', |
+ 'lowshelf': 'Lowshelf filter', |
+ 'highshelf': 'Highshelf filter', |
+ 'peaking': 'Peaking filter', |
+ 'notch': 'Notch filter', |
+ 'allpass': 'Allpass filter' |
+}; |
function createFilter(filterType, freq, q, gain) { |
- return filterCreatorFunction[filterType](freq, q, gain); |
+ return filterCreatorFunction[filterType](freq, q, gain); |
} |