123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- /**
- * Caches the decoded peaks data to improve rendering speed for lage audio
- *
- * Is used if the option parameter `partialRender` is set to `true`
- */
- export default class PeakCache {
- /**
- * Instantiate cache
- */
- constructor() {
- this.clearPeakCache();
- }
- /**
- * Empty the cache
- */
- clearPeakCache() {
- /**
- * Flat array with entries that are always in pairs to mark the
- * beginning and end of each subrange. This is a convenience so we can
- * iterate over the pairs for easy set difference operations.
- * @private
- */
- this.peakCacheRanges = [];
- /**
- * Length of the entire cachable region, used for resetting the cache
- * when this changes (zoom events, for instance).
- * @private
- */
- this.peakCacheLength = -1;
- }
- /**
- * Add a range of peaks to the cache
- *
- * @param {number} length The length of the range
- * @param {number} start The x offset of the start of the range
- * @param {number} end The x offset of the end of the range
- * @return {number[][]}
- */
- addRangeToPeakCache(length, start, end) {
- if (length != this.peakCacheLength) {
- this.clearPeakCache();
- this.peakCacheLength = length;
- }
- // Return ranges that weren't in the cache before the call.
- let uncachedRanges = [];
- let i = 0;
- // Skip ranges before the current start.
- while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] < start) {
- i++;
- }
- // If |i| is even, |start| falls after an existing range. Otherwise,
- // |start| falls between an existing range, and the uncached region
- // starts when we encounter the next node in |peakCacheRanges| or
- // |end|, whichever comes first.
- if (i % 2 == 0) {
- uncachedRanges.push(start);
- }
- while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] <= end) {
- uncachedRanges.push(this.peakCacheRanges[i]);
- i++;
- }
- // If |i| is even, |end| is after all existing ranges.
- if (i % 2 == 0) {
- uncachedRanges.push(end);
- }
- // Filter out the 0-length ranges.
- uncachedRanges = uncachedRanges.filter((item, pos, arr) => {
- if (pos == 0) {
- return item != arr[pos + 1];
- } else if (pos == arr.length - 1) {
- return item != arr[pos - 1];
- }
- return item != arr[pos - 1] && item != arr[pos + 1];
- });
- // Merge the two ranges together, uncachedRanges will either contain
- // wholly new points, or duplicates of points in peakCacheRanges. If
- // duplicates are detected, remove both and extend the range.
- this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);
- this.peakCacheRanges = this.peakCacheRanges.sort((a, b) => a - b).filter((item, pos, arr) => {
- if (pos == 0) {
- return item != arr[pos + 1];
- } else if (pos == arr.length - 1) {
- return item != arr[pos - 1];
- }
- return item != arr[pos - 1] && item != arr[pos + 1];
- });
- // Push the uncached ranges into an array of arrays for ease of
- // iteration in the functions that call this.
- const uncachedRangePairs = [];
- for (i = 0; i < uncachedRanges.length; i += 2) {
- uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i+1]]);
- }
- return uncachedRangePairs;
- }
- /**
- * For testing
- *
- * @return {number[][]}
- */
- getCacheRanges() {
- const peakCacheRangePairs = [];
- let i;
- for (i = 0; i < this.peakCacheRanges.length; i += 2) {
- peakCacheRangePairs.push([this.peakCacheRanges[i], this.peakCacheRanges[i+1]]);
- }
- return peakCacheRangePairs;
- }
- }
|