Index: third_party/WebKit/LayoutTests/webaudio/biquad-getFrequencyResponse.html |
diff --git a/third_party/WebKit/LayoutTests/webaudio/biquad-getFrequencyResponse.html b/third_party/WebKit/LayoutTests/webaudio/biquad-getFrequencyResponse.html |
deleted file mode 100644 |
index 961c56b99681ad20aef0088c6c8c48e3e1f3e1a7..0000000000000000000000000000000000000000 |
--- a/third_party/WebKit/LayoutTests/webaudio/biquad-getFrequencyResponse.html |
+++ /dev/null |
@@ -1,316 +0,0 @@ |
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
-<html> |
-<head> |
-<script src="../resources/js-test.js"></script> |
-<script src="resources/compatibility.js"></script> |
-<script src="resources/audit-util.js"></script> |
-<script src="resources/audio-testing.js"></script> |
-<script src="resources/biquad-filters.js"></script> |
-<script src="resources/biquad-testing.js"></script> |
-</head> |
- |
-<body> |
-<div id="description"></div> |
-<div id="console"></div> |
- |
-<script> |
-description("Test Biquad getFrequencyResponse() functionality."); |
- |
-// Test the frequency response of a biquad filter. We compute the frequency response for a simple |
-// peaking biquad filter and compare it with the expected frequency response. The actual filter |
-// used doesn't matter since we're testing getFrequencyResponse and not the actual filter output. |
-// The filters are extensively tested in other biquad tests. |
- |
-var context; |
- |
-// The biquad filter node. |
-var filter; |
- |
-// The magnitude response of the biquad filter. |
-var magResponse; |
- |
-// The phase response of the biquad filter. |
-var phaseResponse; |
- |
-// Number of frequency samples to take. |
-var numberOfFrequencies = 1000; |
- |
-// The filter parameters. |
-var filterCutoff = 1000; // Hz. |
-var filterQ = 1; |
-var filterGain = 5; // Decibels. |
- |
-// The maximum allowed error in the magnitude response. |
-var maxAllowedMagError = 5.7e-7; |
- |
-// The maximum allowed error in the phase response. |
-var maxAllowedPhaseError = 4.7e-8; |
- |
-// The magnitudes and phases of the reference frequency response. |
-var magResponse; |
-var phaseResponse; |
- |
-// The magnitudes and phases of the reference frequency response. |
-var expectedMagnitudes; |
-var expectedPhases; |
- |
-// Convert frequency in Hz to a normalized frequency between 0 to 1 with 1 corresponding to the |
-// Nyquist frequency. |
-function normalizedFrequency(freqHz, sampleRate) |
-{ |
- var nyquist = sampleRate / 2; |
- return freqHz / nyquist; |
-} |
- |
-// Get the filter response at a (normalized) frequency |f| for the filter with coefficients |coef|. |
-function getResponseAt(coef, f) |
-{ |
- var b0 = coef.b0; |
- var b1 = coef.b1; |
- var b2 = coef.b2; |
- var a1 = coef.a1; |
- var a2 = coef.a2; |
- |
- // H(z) = (b0 + b1 / z + b2 / z^2) / (1 + a1 / z + a2 / z^2) |
- // |
- // Compute H(exp(i * pi * f)). No native complex numbers in javascript, so break H(exp(i * pi * // f)) |
- // in to the real and imaginary parts of the numerator and denominator. Let omega = pi * f. |
- // Then the numerator is |
- // |
- // b0 + b1 * cos(omega) + b2 * cos(2 * omega) - i * (b1 * sin(omega) + b2 * sin(2 * omega)) |
- // |
- // and the denominator is |
- // |
- // 1 + a1 * cos(omega) + a2 * cos(2 * omega) - i * (a1 * sin(omega) + a2 * sin(2 * omega)) |
- // |
- // Compute the magnitude and phase from the real and imaginary parts. |
- |
- var omega = Math.PI * f; |
- var numeratorReal = b0 + b1 * Math.cos(omega) + b2 * Math.cos(2 * omega); |
- var numeratorImag = -(b1 * Math.sin(omega) + b2 * Math.sin(2 * omega)); |
- var denominatorReal = 1 + a1 * Math.cos(omega) + a2 * Math.cos(2 * omega); |
- var denominatorImag = -(a1 * Math.sin(omega) + a2 * Math.sin(2 * omega)); |
- |
- var magnitude = Math.sqrt((numeratorReal * numeratorReal + numeratorImag * numeratorImag) |
- / (denominatorReal * denominatorReal + denominatorImag * denominatorImag)); |
- var phase = Math.atan2(numeratorImag, numeratorReal) - Math.atan2(denominatorImag, denominatorReal); |
- |
- if (phase >= Math.PI) { |
- phase -= 2 * Math.PI; |
- } else if (phase <= -Math.PI) { |
- phase += 2 * Math.PI; |
- } |
- |
- return {magnitude : magnitude, phase : phase}; |
-} |
- |
-// Compute the reference frequency response for the biquad filter |filter| at the frequency samples |
-// given by |frequencies|. |
-function frequencyResponseReference(filter, frequencies) |
-{ |
- var sampleRate = filter.context.sampleRate; |
- var normalizedFreq = normalizedFrequency(filter.frequency.value, sampleRate); |
- var filterCoefficients = createFilter(filter.type, normalizedFreq, filter.Q.value, filter.gain.value); |
- |
- var magnitudes = []; |
- var phases = []; |
- |
- for (var k = 0; k < frequencies.length; ++k) { |
- var response = getResponseAt(filterCoefficients, normalizedFrequency(frequencies[k], sampleRate)); |
- magnitudes.push(response.magnitude); |
- phases.push(response.phase); |
- } |
- |
- return {magnitudes : magnitudes, phases : phases}; |
-} |
- |
-// Compute a set of linearly spaced frequencies. |
-function createFrequencies(nFrequencies, sampleRate) |
-{ |
- var frequencies = new Float32Array(nFrequencies); |
- var nyquist = sampleRate / 2; |
- var freqDelta = nyquist / nFrequencies; |
- |
- for (var k = 0; k < nFrequencies; ++k) { |
- frequencies[k] = k * freqDelta; |
- } |
- |
- return frequencies; |
-} |
- |
-function linearToDecibels(x) |
-{ |
- if (x) { |
- return 20 * Math.log(x) / Math.LN10; |
- } else { |
- return -1000; |
- } |
-} |
- |
-// Look through the array and find any NaN or infinity. Returns the index of the first occurence or |
-// -1 if none. |
-function findBadNumber(signal) |
-{ |
- for (var k = 0; k < signal.length; ++k) { |
- if (!isValidNumber(signal[k])) { |
- return k; |
- } |
- } |
- return -1; |
-} |
- |
-// Compute absolute value of the difference between phase angles, taking into account the wrapping |
-// of phases. |
-function absolutePhaseDifference(x, y) |
-{ |
- var diff = Math.abs(x - y); |
- |
- if (diff > Math.PI) { |
- diff = 2 * Math.PI - diff; |
- } |
- return diff; |
-} |
- |
-// Compare the frequency response with our expected response. |
-function compareResponses(filter, frequencies, magResponse, phaseResponse) |
-{ |
- var expectedResponse = frequencyResponseReference(filter, frequencies); |
- |
- expectedMagnitudes = expectedResponse.magnitudes; |
- expectedPhases = expectedResponse.phases; |
- |
- var n = magResponse.length; |
- var success = true; |
- var badResponse = false; |
- |
- var maxMagError = -1; |
- var maxMagErrorIndex = -1; |
- |
- var k; |
- var hasBadNumber; |
- |
- hasBadNumber = findBadNumber(magResponse); |
- if (hasBadNumber >= 0) { |
- testFailed("Magnitude response has NaN or infinity at " + hasBadNumber); |
- success = false; |
- badResponse = true; |
- } |
- |
- hasBadNumber = findBadNumber(phaseResponse); |
- if (hasBadNumber >= 0) { |
- testFailed("Phase response has NaN or infinity at " + hasBadNumber); |
- success = false; |
- badResponse = true; |
- } |
- |
- // These aren't testing the implementation itself. Instead, these are sanity checks on the |
- // reference. Failure here does not imply an error in the implementation. |
- hasBadNumber = findBadNumber(expectedMagnitudes); |
- if (hasBadNumber >= 0) { |
- testFailed("Expected magnitude response has NaN or infinity at " + hasBadNumber); |
- success = false; |
- badResponse = true; |
- } |
- |
- hasBadNumber = findBadNumber(expectedPhases); |
- if (hasBadNumber >= 0) { |
- testFailed("Expected phase response has NaN or infinity at " + hasBadNumber); |
- success = false; |
- badResponse = true; |
- } |
- |
- // If we found a NaN or infinity, the following tests aren't very helpful, especially for NaN. |
- // We run them anyway, after printing a warning message. |
- |
- if (badResponse) { |
- testFailed("NaN or infinity in the actual or expected results makes the following test results suspect."); |
- success = false; |
- } |
- |
- for (k = 0; k < n; ++k) { |
- var error = Math.abs(linearToDecibels(magResponse[k]) - linearToDecibels(expectedMagnitudes[k])); |
- if (error > maxMagError) { |
- maxMagError = error; |
- maxMagErrorIndex = k; |
- } |
- } |
- |
- if (maxMagError > maxAllowedMagError) { |
- var message = "Magnitude error (" + maxMagError + " dB)"; |
- message += " exceeded threshold at " + frequencies[maxMagErrorIndex]; |
- message += " Hz. Actual: " + linearToDecibels(magResponse[maxMagErrorIndex]); |
- message += " dB, expected: " + linearToDecibels(expectedMagnitudes[maxMagErrorIndex]) + " dB."; |
- testFailed(message); |
- success = false; |
- } else { |
- testPassed("Magnitude response within acceptable threshold."); |
- } |
- |
- var maxPhaseError = -1; |
- var maxPhaseErrorIndex = -1; |
- |
- for (k = 0; k < n; ++k) { |
- var error = absolutePhaseDifference(phaseResponse[k], expectedPhases[k]); |
- if (error > maxPhaseError) { |
- maxPhaseError = error; |
- maxPhaseErrorIndex = k; |
- } |
- } |
- |
- if (maxPhaseError > maxAllowedPhaseError) { |
- var message = "Phase error (radians) (" + maxPhaseError; |
- message += ") exceeded threshold at " + frequencies[maxPhaseErrorIndex]; |
- message += " Hz. Actual: " + phaseResponse[maxPhaseErrorIndex]; |
- message += " expected: " + expectedPhases[maxPhaseErrorIndex]; |
- testFailed(message); |
- success = false; |
- } else { |
- testPassed("Phase response within acceptable threshold."); |
- } |
- |
- |
- return success; |
-} |
- |
-function runTest() |
-{ |
- if (window.testRunner) { |
- testRunner.dumpAsText(); |
- testRunner.waitUntilDone(); |
- } |
- |
- window.jsTestIsAsync = true; |
- |
- context = new AudioContext(); |
- |
- filter = context.createBiquadFilter(); |
- |
- // Arbitrarily test a peaking filter, but any kind of filter can be tested. |
- filter.type = "peaking"; |
- filter.frequency.value = filterCutoff; |
- filter.Q.value = filterQ; |
- filter.gain.value = filterGain; |
- |
- var frequencies = createFrequencies(numberOfFrequencies, context.sampleRate); |
- magResponse = new Float32Array(numberOfFrequencies); |
- phaseResponse = new Float32Array(numberOfFrequencies); |
- |
- filter.getFrequencyResponse(frequencies, magResponse, phaseResponse); |
- var success = compareResponses(filter, frequencies, magResponse, phaseResponse); |
- |
- if (success) { |
- testPassed("Frequency response was correct."); |
- } else { |
- testFailed("Frequency response was incorrect."); |
- } |
- |
- finishJSTest(); |
-} |
- |
-runTest(); |
-successfullyParsed = true; |
- |
-</script> |
- |
-</body> |
-</html> |