Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/media/webaudio/test/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 17 kB image not shown  

Quelle  test_mixingRules.html   Sprache: HTML

 
 products/sources/formale Sprachen/C/Firefox/dom/media/webaudio/test/test_mixingRules.html


<!DOCTYPE html>
<html>
<head>
  <title>Testcase for AudioNode channel up-mix/down-mix rules</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="webaudio.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>

<body>

<script>

// This test is based on http://src.chromium.org/viewvc/blink/trunk/LayoutTests/webaudio/audionode-channel-rules.html

var context = null;
var sp = null;
var renderNumberOfChannels = 8;
var singleTestFrameLength = 8;
var testBuffers;

// A list of connections to an AudioNode input, each of which is to be used in one or more specific test cases.
// Each element in the list is a string, with the number of connections corresponding to the length of the string,
// and each character in the string is from '1' to '8' representing a 1 to 8 channel connection (from an AudioNode output).
// For example, the string "128" means 3 connections, having 1, 2, and 8 channels respectively.
var connectionsList = [];
for (var i = 1; i <= 8; ++i) {
  connectionsList.push(i.toString());
  for (var j = 1; j <= 8; ++j) {
    connectionsList.push(i.toString() + j.toString());
  }
}

// A list of mixing rules, each of which will be tested against all of the connections in connectionsList.
var mixingRulesList = [
    {channelCount: 1, channelCountMode: "max", channelInterpretation: "speakers"},
    {channelCount: 2, channelCountMode: "clamped-max", channelInterpretation: "speakers"},
    {channelCount: 3, channelCountMode: "clamped-max", channelInterpretation: "speakers"},
    {channelCount: 4, channelCountMode: "clamped-max", channelInterpretation: "speakers"},
    {channelCount: 5, channelCountMode: "clamped-max", channelInterpretation: "speakers"},
    {channelCount: 6, channelCountMode: "clamped-max", channelInterpretation: "speakers"},
    {channelCount: 7, channelCountMode: "clamped-max", channelInterpretation: "speakers"},
    {channelCount: 2, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 3, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 4, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 5, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 6, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 7, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 8, channelCountMode: "explicit", channelInterpretation: "speakers"},
    {channelCount: 1, channelCountMode: "max", channelInterpretation: "discrete"},
    {channelCount: 2, channelCountMode: "clamped-max", channelInterpretation: "discrete"},
    {channelCount: 3, channelCountMode: "clamped-max", channelInterpretation: "discrete"},
    {channelCount: 4, channelCountMode: "clamped-max", channelInterpretation: "discrete"},
    {channelCount: 5, channelCountMode: "clamped-max", channelInterpretation: "discrete"},
    {channelCount: 6, channelCountMode: "clamped-max", channelInterpretation: "discrete"},
    {channelCount: 3, channelCountMode: "explicit", channelInterpretation: "discrete"},
    {channelCount: 4, channelCountMode: "explicit", channelInterpretation: "discrete"},
    {channelCount: 5, channelCountMode: "explicit", channelInterpretation: "discrete"},
    {channelCount: 6, channelCountMode: "explicit", channelInterpretation: "discrete"},
    {channelCount: 7, channelCountMode: "explicit", channelInterpretation: "discrete"},
    {channelCount: 8, channelCountMode: "explicit", channelInterpretation: "discrete"},
];

var numberOfTests = mixingRulesList.length * connectionsList.length;

// Create an n-channel buffer, with all sample data zero except for a shifted impulse.
// The impulse position depends on the channel index.
// For example, for a 4-channel buffer:
// channel0: 1 0 0 0 0 0 0 0
// channel1: 0 1 0 0 0 0 0 0
// channel2: 0 0 1 0 0 0 0 0
// channel3: 0 0 0 1 0 0 0 0
function createTestBuffer(numberOfChannels) {
    var buffer = context.createBuffer(numberOfChannels, singleTestFrameLength, context.sampleRate);
    for (var i = 0; i < numberOfChannels; ++i) {
        var data = buffer.getChannelData(i);
        data[i] = 1;
    }
    return buffer;
}

// Discrete channel interpretation mixing:
// https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#UpMix
// up-mix by filling channels until they run out then ignore remaining dest channels.
// down-mix by filling as many channels as possible, then dropping remaining source channels.
function discreteSum(sourceBuffer, destBuffer) {
    if (sourceBuffer.length != destBuffer.length) {
        is(sourceBuffer.length, destBuffer.length, "source and destination buffers should have the same length");
    }

    var numberOfChannels = Math.min(sourceBuffer.numberOfChannels, destBuffer.numberOfChannels);
    var length = sourceBuffer.length;

    for (var c = 0; c < numberOfChannels; ++c) {
        var source = sourceBuffer.getChannelData(c);
        var dest = destBuffer.getChannelData(c);
        for (var i = 0; i < length; ++i) {
            dest[i] += source[i];
        }
    }
}

// Speaker channel interpretation mixing:
// https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#UpMix
// eslint-disable-next-line complexity
function speakersSum(sourceBuffer, destBuffer)
{
    var numberOfSourceChannels = sourceBuffer.numberOfChannels;
    var numberOfDestinationChannels = destBuffer.numberOfChannels;
    var length = destBuffer.length;

    if ((numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) ||
        (numberOfDestinationChannels == 4 && numberOfSourceChannels == 1)) {
        // Handle mono -> stereo/Quad case (summing mono channel into both left and right).
        var source = sourceBuffer.getChannelData(0);
        var destL = destBuffer.getChannelData(0);
        var destR = destBuffer.getChannelData(1);

        for (var i = 0; i < length; ++i) {
            destL[i] += source[i];
            destR[i] += source[i];
        }
        } else if ((numberOfDestinationChannels == 4 && numberOfSourceChannels == 2) ||
                   (numberOfDestinationChannels == 6 && numberOfSourceChannels == 2)) {
        // Handle stereo -> Quad/5.1 case (summing left and right channels into the output's left and right).
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var destL = destBuffer.getChannelData(0);
        var destR = destBuffer.getChannelData(1);

        for (var i = 0; i < length; ++i) {
            destL[i] += sourceL[i];
            destR[i] += sourceR[i];
        }
    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) {
        // Handle stereo -> mono case. output += 0.5 * (input.L + input.R).
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var dest = destBuffer.getChannelData(0);

        for (var i = 0; i < length; ++i) {
            dest[i] += 0.5 * (sourceL[i] + sourceR[i]);
        }
    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 4) {
        // Handle Quad -> mono case. output += 0.25 * (input.L + input.R + input.SL + input.SR).
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var sourceSL = sourceBuffer.getChannelData(2);
        var sourceSR = sourceBuffer.getChannelData(3);
        var dest = destBuffer.getChannelData(0);

        for (var i = 0; i < length; ++i) {
            dest[i] += 0.25 * (sourceL[i] + sourceR[i] + sourceSL[i] + sourceSR[i]);
        }
    } else if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 4) {
        // Handle Quad -> stereo case. outputLeft += 0.5 * (input.L + input.SL),
        //                             outputRight += 0.5 * (input.R + input.SR).
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var sourceSL = sourceBuffer.getChannelData(2);
        var sourceSR = sourceBuffer.getChannelData(3);
        var destL = destBuffer.getChannelData(0);
        var destR = destBuffer.getChannelData(1);

        for (var i = 0; i < length; ++i) {
            destL[i] += 0.5 * (sourceL[i] + sourceSL[i]);
            destR[i] += 0.5 * (sourceR[i] + sourceSR[i]);
        }
    } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 4) {
        // Handle Quad -> 5.1 case. outputLeft += (inputL, inputR, 0, 0, inputSL, inputSR)
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var sourceSL = sourceBuffer.getChannelData(2);
        var sourceSR = sourceBuffer.getChannelData(3);
        var destL = destBuffer.getChannelData(0);
        var destR = destBuffer.getChannelData(1);
        var destSL = destBuffer.getChannelData(4);
        var destSR = destBuffer.getChannelData(5);

        for (var i = 0; i < length; ++i) {
            destL[i] += sourceL[i];
            destR[i] += sourceR[i];
            destSL[i] += sourceSL[i];
            destSR[i] += sourceSR[i];
        }
    } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) {
        // Handle mono -> 5.1 case, sum mono channel into center.
        var source = sourceBuffer.getChannelData(0);
        var dest = destBuffer.getChannelData(2);

        for (var i = 0; i < length; ++i) {
            dest[i] += source[i];
        }
    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) {
        // Handle 5.1 -> mono.
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var sourceC = sourceBuffer.getChannelData(2);
        // skip LFE for now, according to current spec.
        var sourceSL = sourceBuffer.getChannelData(4);
        var sourceSR = sourceBuffer.getChannelData(5);
        var dest = destBuffer.getChannelData(0);

        for (var i = 0; i < length; ++i) {
            dest[i] += 0.7071 * (sourceL[i] + sourceR[i]) + sourceC[i] + 0.5 * (sourceSL[i] + sourceSR[i]);
        }
    } else if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 6) {
        // Handle 5.1 -> stereo.
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var sourceC = sourceBuffer.getChannelData(2);
        // skip LFE for now, according to current spec.
        var sourceSL = sourceBuffer.getChannelData(4);
        var sourceSR = sourceBuffer.getChannelData(5);
        var destL = destBuffer.getChannelData(0);
        var destR = destBuffer.getChannelData(1);

        for (var i = 0; i < length; ++i) {
            destL[i] += sourceL[i] + 0.7071 * (sourceC[i] + sourceSL[i]);
            destR[i] += sourceR[i] + 0.7071 * (sourceC[i] + sourceSR[i]);
        }
    } else if (numberOfDestinationChannels == 4 && numberOfSourceChannels == 6) {
        // Handle 5.1 -> Quad.
        var sourceL = sourceBuffer.getChannelData(0);
        var sourceR = sourceBuffer.getChannelData(1);
        var sourceC = sourceBuffer.getChannelData(2);
        // skip LFE for now, according to current spec.
        var sourceSL = sourceBuffer.getChannelData(4);
        var sourceSR = sourceBuffer.getChannelData(5);
        var destL = destBuffer.getChannelData(0);
        var destR = destBuffer.getChannelData(1);
        var destSL = destBuffer.getChannelData(2);
        var destSR = destBuffer.getChannelData(3);

        for (var i = 0; i < length; ++i) {
            destL[i] += sourceL[i] + 0.7071 * sourceC[i];
            destR[i] += sourceR[i] + 0.7071 * sourceC[i];
            destSL[i] += sourceSL[i];
            destSR[i] += sourceSR[i];
        }
    } else {
        // Fallback for unknown combinations.
        discreteSum(sourceBuffer, destBuffer);
    }
}

function scheduleTest(testNumber, connections, channelCount, channelCountMode, channelInterpretation) {
    var mixNode = context.createGain();
    mixNode.channelCount = channelCount;
    mixNode.channelCountMode = channelCountMode;
    mixNode.channelInterpretation = channelInterpretation;
    mixNode.connect(sp);

    for (var i = 0; i < connections.length; ++i) {
        var connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCodeAt(0);

        var source = context.createBufferSource();
        // Get a buffer with the right number of channels, converting from 1-based to 0-based index.
        var buffer = testBuffers[connectionNumberOfChannels - 1];
        source.buffer = buffer;
        source.connect(mixNode);

        // Start at the right offset.
        var sampleFrameOffset = testNumber * singleTestFrameLength;
        var time = sampleFrameOffset / context.sampleRate;
        source.start(time);
    }
}

function computeNumberOfChannels(connections, channelCount, channelCountMode) {
    if (channelCountMode == "explicit")
        return channelCount;

    var computedNumberOfChannels = 1; // Must have at least one channel.

    // Compute "computedNumberOfChannels" based on all the connections.
    for (var i = 0; i < connections.length; ++i) {
        var connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCodeAt(0);
        computedNumberOfChannels = Math.max(computedNumberOfChannels, connectionNumberOfChannels);
    }

    if (channelCountMode == "clamped-max")
        computedNumberOfChannels = Math.min(computedNumberOfChannels, channelCount);

    return computedNumberOfChannels;
}

function checkTestResult(renderedBuffer, testNumber, connections, channelCount, channelCountMode, channelInterpretation) {
    var computedNumberOfChannels = computeNumberOfChannels(connections, channelCount, channelCountMode);

    // Create a zero-initialized silent AudioBuffer with computedNumberOfChannels.
    var destBuffer = context.createBuffer(computedNumberOfChannels, singleTestFrameLength, context.sampleRate);

    // Mix all of the connections into the destination buffer.
    for (var i = 0; i < connections.length; ++i) {
        var connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCodeAt(0);
        var sourceBuffer = testBuffers[connectionNumberOfChannels - 1]; // convert from 1-based to 0-based index

        if (channelInterpretation == "speakers") {
            speakersSum(sourceBuffer, destBuffer);
        } else if (channelInterpretation == "discrete") {
            discreteSum(sourceBuffer, destBuffer);
        } else {
            ok(false, "Invalid channel interpretation!");
        }
    }

    // Validate that destBuffer matches the rendered output.
    // We need to check the rendered output at a specific sample-frame-offset corresponding
    // to the specific test case we're checking for based on testNumber.

    var sampleFrameOffset = testNumber * singleTestFrameLength;
    for (var c = 0; c < renderNumberOfChannels; ++c) {
        var renderedData = renderedBuffer.getChannelData(c);
        for (var frame = 0; frame < singleTestFrameLength; ++frame) {
            var renderedValue = renderedData[frame + sampleFrameOffset];

            var expectedValue = 0;
            if (c < destBuffer.numberOfChannels) {
                var expectedData = destBuffer.getChannelData(c);
                expectedValue = expectedData[frame];
            }

            if (Math.abs(renderedValue - expectedValue) > 1e-4) {
                var s = "connections: " + connections + ", " + channelCountMode;

                // channelCount is ignored in "max" mode.
                if (channelCountMode == "clamped-max" || channelCountMode == "explicit") {
                    s += "(" + channelCount + ")";
                }

                s += ", " + channelInterpretation + ". ";

                var message = s + "rendered: " + renderedValue + " expected: " + expectedValue + " channel: " + c + " frame: " + frame;
                is(renderedValue, expectedValue, message);
            }
        }
    }
}

function checkResult(event) {
    var buffer = event.inputBuffer;

    // Sanity check result.
    ok(buffer.length != numberOfTests * singleTestFrameLength ||
       buffer.numberOfChannels != renderNumberOfChannels, "Sanity check");

    // Check all the tests.
    var testNumber = 0;
    for (var m = 0; m < mixingRulesList.length; ++m) {
        var mixingRules = mixingRulesList[m];
        for (var i = 0; i < connectionsList.length; ++i, ++testNumber) {
            checkTestResult(buffer, testNumber, connectionsList[i], mixingRules.channelCount, mixingRules.channelCountMode, mixingRules.channelInterpretation);
        }
    }

    sp.onaudioprocess = null;
    SimpleTest.finish();
}

SimpleTest.waitForExplicitFinish();
function runTest() {
    // Create 8-channel offline audio context.
    // Each test will render 8 sample-frames starting at sample-frame position testNumber * 8.
    var totalFrameLength = numberOfTests * singleTestFrameLength;
    context = new AudioContext();
    var nextPowerOfTwo = 256;
    while (nextPowerOfTwo < totalFrameLength) {
        nextPowerOfTwo *= 2;
    }
    sp = context.createScriptProcessor(nextPowerOfTwo, renderNumberOfChannels);

    // Set destination to discrete mixing.
    sp.channelCount = renderNumberOfChannels;
    sp.channelCountMode = "explicit";
    sp.channelInterpretation = "discrete";

    // Create test buffers from 1 to 8 channels.
    testBuffers = new Array();
    for (var i = 0; i < renderNumberOfChannels; ++i) {
        testBuffers[i] = createTestBuffer(i + 1);
    }

    // Schedule all the tests.
    var testNumber = 0;
    for (var m = 0; m < mixingRulesList.length; ++m) {
        var mixingRules = mixingRulesList[m];
        for (var i = 0; i < connectionsList.length; ++i, ++testNumber) {
            scheduleTest(testNumber, connectionsList[i], mixingRules.channelCount, mixingRules.channelCountMode, mixingRules.channelInterpretation);
        }
    }

    // Render then check results.
    sp.onaudioprocess = checkResult;
}

runTest();

</script>

</body>
</html>

Messung V0.5
C=93 H=94 G=93

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.