UNPKG

@stemplayer-js/stemplayer-js

Version:

A streaming, low latency Stem Player Web-Component

86 lines (71 loc) 2.96 kB
/* * Copyright (c) 2018 Alexufo . Original code 2013 by Sveinn Steinarsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * @see https://github.com/Alexufo/Responsive-waveform/blob/master/largestTriangleThreeBuckets.js */ /* eslint-disable */ export default function largestTriangleThreeBuckets(data, threshold) { // data is linear array [90,87,97...] var data_length = data.length; if (threshold >= data_length || threshold === 0) { return data; // Nothing to do } var sampled = [], sampled_index = 0; // Bucket size. Leave room for start and end data points var every = (data_length - 2) / (threshold - 2); var a = 0, // Initially a is the first point in the triangle max_area_point, max_area, area, next_a; sampled[sampled_index++] = data[a]; // Always add the first point for (var i = 0; i < threshold - 2; i++) { // Calculate point average for next bucket (containing c) var avg_x = 0, avg_y = 0, avg_range_start = Math.floor((i + 1) * every) + 1, avg_range_end = Math.floor((i + 2) * every) + 1; avg_range_end = avg_range_end < data_length ? avg_range_end : data_length; var avg_range_length = avg_range_end - avg_range_start; for (; avg_range_start < avg_range_end; avg_range_start++) { avg_x += avg_range_start; avg_y += data[avg_range_start] * 1; // * 1 enforces Number (value may be Date) } avg_x /= avg_range_length; avg_y /= avg_range_length; // Get the range for this bucket var range_offs = Math.floor((i + 0) * every) + 1, range_to = Math.floor((i + 1) * every) + 1; // Point a var point_a_x = a * 1, // enforce Number (value may be Date) point_a_y = data[a] * 1; max_area = area = -1; for (; range_offs < range_to; range_offs++) { // Calculate triangle area over three buckets area = Math.abs( (point_a_x - avg_x) * (data[range_offs] - point_a_y) - (point_a_x - range_offs) * (avg_y - point_a_y), ) * 0.5; if (area > max_area) { max_area = area; max_area_point = data[range_offs]; next_a = range_offs; // Next a is this b } } sampled[sampled_index++] = max_area_point; // Pick this point from the bucket a = next_a; // This a is the next a (chosen b) } sampled[sampled_index++] = data[data_length - 1]; // Always add last return sampled; }