Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/testing/web-platform/tests/webcodecs/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 13 kB image not shown  

Quellcode-Bibliothek audio-data.any.js   Sprache: JAVA

 
// META: global=window,dedicatedworker
// META: script=/common/media.js
// META: script=/webcodecs/utils.js

var defaultInit = {
  timestamp: 1234,
  channels: 2,
  sampleRate: 8000,
  frames: 100,
};

function createDefaultAudioData() {
  return make_audio_data(
    defaultInit.timestamp,
    defaultInit.channels,
    defaultInit.sampleRate,
    defaultInit.frames
  );
}

test(t => {
  let local_data = new Float32Array(defaultInit.channels * defaultInit.frames);

  let audio_data_init = {
    timestamp: defaultInit.timestamp,
    data: local_data,
    numberOfFrames: defaultInit.frames,
    numberOfChannels: defaultInit.channels,
    sampleRate: defaultInit.sampleRate,
    format: 'f32-planar',
  }

  let data = new AudioData(audio_data_init);

  assert_equals(data.timestamp, defaultInit.timestamp, 'timestamp');
  assert_equals(data.numberOfFrames, defaultInit.frames, 'frames');
  assert_equals(data.numberOfChannels, defaultInit.channels, 'channels');
  assert_equals(data.sampleRate, defaultInit.sampleRate, 'sampleRate');
  assert_equals(
      data.duration, defaultInit.frames / defaultInit.sampleRate * 1_000_000,
      'duration');
  assert_equals(data.format, 'f32-planar''format');

  // Create an Int16 array of the right length.
  let small_data = new Int16Array(defaultInit.channels * defaultInit.frames);

  let wrong_format_init = {...audio_data_init};
  wrong_format_init.data = small_data;

  // Creating `f32-planar` AudioData from Int16 from should throw.
  assert_throws_js(TypeError, () => {
    let data = new AudioData(wrong_format_init);
  }, `AudioDataInit.data needs to be big enough`);

  var members = [
    'timestamp',
    'data',
    'numberOfFrames',
    'numberOfChannels',
    'sampleRate',
    'format',
  ];

  for (const member of members) {
    let incomplete_init = {...audio_data_init};
    delete incomplete_init[member];

    assert_throws_js(
        TypeError, () => {let data = new AudioData(incomplete_init)},
        'AudioData requires \'' + member + '\'');
  }

  let invalid_init = {...audio_data_init};
  invalid_init.numberOfFrames = 0

  assert_throws_js(
      TypeError, () => {let data = new AudioData(invalid_init)},
      'AudioData requires numberOfFrames > 0');

  invalid_init = {...audio_data_init};
  invalid_init.numberOfChannels = 0

  assert_throws_js(
      TypeError, () => {let data = new AudioData(invalid_init)},
      'AudioData requires numberOfChannels > 0');

}, 'Verify AudioData constructors');

test(t => {
  let data = createDefaultAudioData();

  let clone = data.clone();

  // Verify the parameters match.
  assert_equals(data.timestamp, clone.timestamp, 'timestamp');
  assert_equals(data.numberOfFrames, clone.numberOfFrames, 'frames');
  assert_equals(data.numberOfChannels, clone.numberOfChannels, 'channels');
  assert_equals(data.sampleRate, clone.sampleRate, 'sampleRate');
  assert_equals(data.format, clone.format, 'format');

  const data_copyDest = new Float32Array(defaultInit.frames);
  const clone_copyDest = new Float32Array(defaultInit.frames);

  // Verify the data matches.
  for (var channel = 0; channel < defaultInit.channels; channel++) {
    data.copyTo(data_copyDest, {planeIndex: channel});
    clone.copyTo(clone_copyDest, {planeIndex: channel});

    assert_array_equals(
        data_copyDest, clone_copyDest, 'Cloned data ch=' + channel);
  }

  // Verify closing the original data doesn't close the clone.
  data.close();
  assert_equals(data.numberOfFrames, 0, 'data.buffer (closed)');
  assert_not_equals(clone.numberOfFrames, 0, 'clone.buffer (not closed)');

  clone.close();
  assert_equals(clone.numberOfFrames, 0, 'clone.buffer (closed)');

  // Verify closing a closed AudioData does not throw.
  data.close();
}, 'Verify closing and cloning AudioData');

test(t => {
  let data = make_audio_data(
      -10, defaultInit.channels, defaultInit.sampleRate, defaultInit.frames);
  assert_equals(data.timestamp, -10, 'timestamp');
  data.close();
}, 'Test we can construct AudioData with a negative timestamp.');

test(t => {
  var data = new Float32Array([0]);
  let audio_data_init = {
    timestamp: 0,
    data: data,
    numberOfFrames: 1,
    numberOfChannels: 1,
    sampleRate: 44100,
    format: 'f32',
  };
  let audioData = new AudioData(audio_data_init);
  assert_not_equals(data.length, 0, "Input data is copied when constructing an AudioData");
}, 'Test input array is copied on construction');

test(t => {
  let audio_data_init = {
    timestamp: 0,
    data: new Float32Array([1,2,3,4,5,6,7,8]),
    numberOfFrames: 4,
    numberOfChannels: 2,
    sampleRate: 44100,
    format: 'f32',
  };
  let audioData = new AudioData(audio_data_init);
  let dest = new Float32Array(8);
  assert_throws_js(
      RangeError, () => audioData.copyTo(dest, {planeIndex: 1}),
      'copyTo from interleaved data with non-zero planeIndex throws');
  audioData.close();
}, 'Test that copyTo throws if copying from interleaved with a non-zero planeIndex');

// Indices to pick a particular specific value in a specific sample-format
const MIN = 0; // Minimum sample value, max amplitude
const MAX = 1; // Maximum sample value, max amplitude
const HALF = 2; // Half the maximum sample value, positive
const NEGATIVE_HALF = 3; // Half the maximum sample value, negative
const BIAS = 4; // Center of the range, silence
const DISCRETE_STEPS = 5; // Number of different value for a type.

function pow2(p) {
  return 2 ** p;
}
// Rounding operations for conversion, currently always floor (round towards
// zero).
let r = Math.floor.bind(this);

const TEST_VALUES = {
  u8: [0, 255, 191, 64, 128, 256],
  s16: [
    -pow2(15),
    pow2(15) - 1,
    r((pow2(15) - 1) / 2),
    r(-pow2(15) / 2),
    0,
    pow2(16),
  ],
  s32: [
    -pow2(31),
    pow2(31) - 1,
    r((pow2(31) - 1) / 2),
    r(-pow2(31) / 2),
    0,
    pow2(32),
  ],
  f32: [-1.0, 1.0, 0.5, -0.5, 0, pow2(24)],
};

const TEST_TEMPLATE = {
  channels: 2,
  frames: 5,
  // Each test is run with an element of the cartesian product of a pair of
  // elements of the set of type in [u8, s16, s32, f32]
  // For each test, this template is copied and the values replaced with the
  // appropriate values for this particular type.
  // For each test, copy this template and replace the number by the appropriate
  // number for this type
  testInput: [MIN, BIAS, MAX, MIN, HALF, NEGATIVE_HALF, BIAS, MAX, BIAS, BIAS],
  testInterleavedResult: [MIN, NEGATIVE_HALF, BIAS, BIAS, MAX, MAX, MIN, BIAS, HALF, BIAS],
  testVectorInterleavedResult: [
    [MIN, MAX, HALF, BIAS, BIAS],
    [BIAS, MIN, NEGATIVE_HALF, MAX, BIAS],
  ],
  testVectorPlanarResult: [
    [MIN, BIAS, MAX, MIN, HALF],
    [NEGATIVE_HALF, BIAS, MAX, BIAS, BIAS],
  ],
};

function isInteger(type) {
  switch (type) {
    case "u8":
    case "s16":
    case "s32":
      return true;
    case "f32":
      return false;
    default:
      throw "invalid type";
  }
}

// This is the complex part: carefully select an acceptable error value
// depending on various factors: expected destination value, source type,
// destination type. This is designed to be strict but reachable with simple
// sample format transformation (no dithering or complex transformation).
function epsilon(expectedDestValue, sourceType, destType) {
  // Strict comparison if not converting
  if (sourceType == destType) {
    return 0.0;
  }
  // There are three cases in which the maximum value cannot be reached, when
  // converting from a smaller integer sample type to a wider integer sample
  // type:
  // - u8 to s16
  // - u8 to s32
  // - s16 to u32
  if (expectedDestValue == TEST_VALUES[destType][MAX]) {
    if (sourceType == "u8" && destType == "s16") {
      return expectedDestValue - 32511; // INT16_MAX - 2 << 7 + 1
    } else if (sourceType == "u8" && destType == "s32") {
      return expectedDestValue - 2130706432; // INT32_MAX - (2 << 23) + 1
    } else if (sourceType == "s16" && destType == "s32") {
      return expectedDestValue - 2147418112; // INT32_MAX - UINT16_MAX
    }
  }
  // Min and bias value are correctly mapped for all integer sample-types
  if (isInteger(sourceType) && isInteger(destType)) {
    if (expectedDestValue == TEST_VALUES[destType][MIN] ||
        expectedDestValue == TEST_VALUES[destType][BIAS]) {
      return 0.0;
    }
  }
  // If converting from float32 to u8 or s16, allow choosing the rounding
  // direction. s32 has higher resolution than f32 in [-1.0,1.0] (24 bits of
  // mantissa)
  if (!isInteger(sourceType) && isInteger(destType) && destType != "s32") {
    return 1.0;
  }
  // In all other cases, expect an accuracy that depends on the source type and
  // the destination type.
  // The resolution of the source type.
  var sourceResolution = TEST_VALUES[sourceType][DISCRETE_STEPS];
  // The resolution of the destination type.
  var destResolution = TEST_VALUES[destType][DISCRETE_STEPS];
  // Computations should be exact if going from high resolution to low resolution.
  if (sourceResolution > destResolution) {
    return 0.0;
  } else {
    // Something that approaches the precision imbalance
    return destResolution / sourceResolution;
  }
}

// Fill the template above with the values for a particular type
function get_type_values(type) {
  let cloned = structuredClone(TEST_TEMPLATE);
  cloned.testInput = Array.from(
    cloned.testInput,
    idx => TEST_VALUES[type][idx]
  );
  cloned.testInterleavedResult = Array.from(
    cloned.testInterleavedResult,
    idx => TEST_VALUES[type][idx]
  );
  cloned.testVectorInterleavedResult = Array.from(
    cloned.testVectorInterleavedResult,
    c => {
      return Array.from(c, idx => {
        return TEST_VALUES[type][idx];
      });
    }
  );
  cloned.testVectorPlanarResult = Array.from(
    cloned.testVectorPlanarResult,
    c => {
      return Array.from(c, idx => {
        return TEST_VALUES[type][idx];
      });
    }
  );
  return cloned;
}

function typeToArrayType(type) {
  switch (type) {
    case "u8":
      return Uint8Array;
    case "s16":
      return Int16Array;
    case "s32":
      return Int32Array;
    case "f32":
      return Float32Array;
    default:
      throw "Unexpected";
  }
}

function arrayTypeToType(array) {
  switch (array.constructor) {
    case Uint8Array:
      return "u8";
    case Int16Array:
      return "s16";
    case Int32Array:
      return "s32";
    case Float32Array:
      return "f32";
    default:
      throw "Unexpected";
  }
}

function check_array_equality(values, expected, sourceType, message, assert_func) {
  if (values.length != expected.length) {
    throw "Array not of the same length";
  }
  for (var i = 0; i < values.length; i++) {
    var eps = epsilon(expected[i], sourceType, arrayTypeToType(values));
    assert_func(
      Math.abs(expected[i] - values[i]) <= eps,
      `Got ${values[i]} but expected result ${
        expected[i]
      } at index ${i} when converting from ${sourceType} to ${arrayTypeToType(
        values
      )}, epsilon ${eps}`
    );
  }
  assert_func(
    true,
    `${values} is equal to ${expected} when converting from ${sourceType} to ${arrayTypeToType(
      values
    )}`
  );
}

function conversionTest(sourceType, destinationType) {
  test(function (t) {
    var test = get_type_values(sourceType);
    var result = get_type_values(destinationType);

    var sourceArrayCtor = typeToArrayType(sourceType);
    var destArrayCtor = typeToArrayType(destinationType);

    let data = new AudioData({
      timestamp: defaultInit.timestamp,
      data: new sourceArrayCtor(test.testInput),
      numberOfFrames: test.frames,
      numberOfChannels: test.channels,
      sampleRate: defaultInit.sampleRate,
      format: sourceType,
    });

    // All conversions can be supported, but conversion of any type to f32-planar
    // MUST be supported.
    var assert_func = destinationType == "f32" ? assert_true : assert_implements_optional;
    let dest = new destArrayCtor(data.numberOfFrames);
    data.copyTo(dest, { planeIndex: 0, format: destinationType + "-planar" });
    check_array_equality(
      dest,
      result.testVectorInterleavedResult[0],
      sourceType,
      "interleaved channel 0",
      assert_func
    );
    data.copyTo(dest, { planeIndex: 1, format: destinationType + "-planar" });
    check_array_equality(
      dest,
      result.testVectorInterleavedResult[1],
      sourceType,
      "interleaved channel 0",
      assert_func
    );
    let destInterleaved = new destArrayCtor(data.numberOfFrames * data.numberOfChannels);
    data.copyTo(destInterleaved, { planeIndex: 0, format: destinationType });
    check_array_equality(
      destInterleaved,
      result.testInput,
      sourceType,
      "copyTo from interleaved to interleaved (conversion only)",
      assert_implements_optional
    );

    data = new AudioData({
      timestamp: defaultInit.timestamp,
      data: new sourceArrayCtor(test.testInput),
      numberOfFrames: test.frames,
      numberOfChannels: test.channels,
      sampleRate: defaultInit.sampleRate,
      format: sourceType + "-planar",
    });

    data.copyTo(dest, { planeIndex: 0, format: destinationType + "-planar" });
    check_array_equality(
      dest,
      result.testVectorPlanarResult[0],
      sourceType,
      "planar channel 0",
      assert_func,
    );
    data.copyTo(dest, { planeIndex: 1, format: destinationType + "-planar" });
    check_array_equality(
      dest,
      result.testVectorPlanarResult[1],
      sourceType,
      "planar channel 1",
      assert_func
    );
    // Copy to interleaved from planar: all channels are copied
    data.copyTo(destInterleaved, {planeIndex: 0, format: destinationType});
    check_array_equality(
      destInterleaved,
      result.testInterleavedResult,
      sourceType,
      "planar to interleaved",
      assert_func
    );
  }, `Test conversion of ${sourceType} to ${destinationType}`);
}

const TYPES = ["u8""s16""s32""f32"];
 TYPES.forEach(sourceType => {
   TYPES.forEach(destinationType => {
    conversionTest(sourceType, destinationType);
  });
});

95%


¤ 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.0.8Bemerkung:  ¤

*Bot Zugriff






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 ist noch experimentell.