PageSourceSearch

https://pure80spop.co.uk/wp-content/plugins/qt-kenthaplayer/assets/js/kenthaplayer-waveform.js?ver=3.3.0

js pure80spop.co.uk collected 2026-10-02 13:19:59 UTC 6,696 bytes, 207 lines download raw bytes

1/**
2* Copyright 2020 QantumThemes by Igor Nardo - All Rights Reserved
3*/
4jQuery.storedPeaks = [];
5
6function qtWaveformDebug(m){
7	if( jQuery('#qtmusicplayer').data('debug') ){
8		// console.log(infor);
9		var c = jQuery("#qtmPlayerDebugger");
10		if(c.length > 0){
11			c.append(m+'<br>');
12		}
13	}
14}
15
16/**
17 * Retrieves audio from an external source, the initializes the drawing function
18 * @param {String} url the url of the audio we'd like to fetch
19 */
20const drawAudio = url => {
21
22	if(0 === jQuery('#qtKenthaPlayerWaveform').length ) return; // do nothing if 
23
24	jQuery('#qtKenthaPlayerWaveform canvas').remove();
25	jQuery('#qtKenthaPlayerWaveform').append('<canvas id="qtwaveformOriginal"></canvas><canvas id="qtwaveformClone"></canvas>');
26	jQuery.qtmplayerCanvas = jQuery('#qtKenthaPlayerWaveform #qtwaveformOriginal');
27	jQuery.qtmplayerCanvasClone = jQuery('#qtKenthaPlayerWaveform #qtwaveformClone');
28	jQuery.qtmplayerCanvasCloneColor = jQuery('#qtKenthaPlayerWaveform').data('color'); // not in use
29	if( undefined === jQuery.storedPeaks[url] ){
30		var storedSongPeaks = false;
31		var ajaxPeaksUrl = jQuery('#qtmusicplayer').data('siteurl'); // ajax_var.url;
32		jQuery.ajax({
33			type: "get",
34			url: ajaxPeaksUrl,
35			data: {
36				'kentha_spectrum_url' : url,
37			},
38			success: function( response ){
39				qtWaveformDebug('Waveform cache response success');
40				var valid = 0;
41				if(  'undefined' !== typeof(response) ){
42					if(response !== 'error'){
43						try{
44							peaks = jQuery.parseJSON(response);
45							if(typeof(peaks) == 'object') {
46								valid = 1;
47							}
48						} catch(e){
49							console.log(e);
50						}
51					}
52				}
53				if( 1 === valid ){
54					qtWaveformDebug('Use DB peaks');
55					var peaks = jQuery.parseJSON(response );
56					jQuery.storedPeaks[url] = peaks;
57					draw(url, peaks, false);
58				} else {
59					qtWaveformDebug('Calculate peaks new');
60					window.AudioContext = window.AudioContext || window.webkitAudioContext;
61					const audioContext = new AudioContext();
62					fetch(url)
63					.then(response => response.arrayBuffer())
64					.then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer))
65					.then(audioBuffer => draw(url,normalizeData(filterData(audioBuffer)),true)); // third parameter: store the data?
66				}
67				return true;
68			}, fail: function(e){
69				qtWaveformDebug( e );
70				qtWaveformDebug('Ajax FAIL');
71			}
72		});
73	} else {
74		draw(url, jQuery.storedPeaks[url], false);
75		return true;
76	}
77};
78
79/**
80 * Filters the AudioBuffer retrieved from an external source
81 * @param {AudioBuffer} audioBuffer the AudioBuffer from drawAudio()
82 * @returns {Array} an array of floating point numbers
83 */
84const filterData = audioBuffer => {
85	const rawData = audioBuffer.getChannelData(0); // We only need to work with one channel of data
86	const samples = 500; // Number of samples we want to have in our final data set
87	const blockSize = Math.floor(rawData.length / samples); // the number of samples in each subdivision
88	const filteredData = [];
89	for (let i = 0; i < samples; i++) {
90		let blockStart = blockSize * i; // the location of the first sample in the block
91		let sum = 0;
92		for (let j = 0; j < blockSize; j++) {
93			sum = sum + Math.abs(rawData[blockStart + j]); // find the sum of all the samples in the block
94		}
95		filteredData.push(sum / blockSize); // divide the sum by the block size to get the average
96	}
97	return filteredData;
98};
99
100/**
101 * Normalizes the audio data to make a cleaner illustration 
102 * @param {Array} filteredData the data from filterData()
103 * @returns {Array} an normalized array of floating point numbers
104 */
105const normalizeData = filteredData => {
106	const multiplier = Math.pow(Math.max(...filteredData), -1);
107	let normalized = filteredData.map(n => n * multiplier);
108	return normalized;
109}
110
111
112
113/**
114 * Draws the audio file into a canvas element.
115 * @param {Array} normalizedData The filtered array returned from filterData()
116 * @returns {Array} a normalized array of data 
117 */
118const draw = ( url, normalizedData, storeData) => {
119	const canvas = jQuery.qtmplayerCanvas[0];//document.querySelector("canvas");
120	
121	const dpr = window.devicePixelRatio || 1;
122	const gap = 1;
123	const padding = 2;
124	canvas.width = canvas.offsetWidth * dpr;
125	canvas.height = (canvas.offsetHeight + padding * 2) * dpr;
126	const ctx = canvas.getContext("2d");
127	ctx.scale(dpr, -dpr);
128	ctx.translate(0, - canvas.offsetHeight - padding- padding  ); // set Y = 0 to be in the middle of the canvas
129
130	// draw the line segments
131	const width = Math.round( canvas.offsetWidth / normalizedData.length );
132	jQuery.storedPeaks[url] = normalizedData;// Save the peaks associated with the URL to avoid reloading the same file again
133
134	qtWaveformDebug('Store data:'+storeData)
135	if(true == storeData){
136
137		jQuery.ajax({
138			type: "post",
139			url: ajax_var.url,
140			data: {
141				'action': 'qtmplayer-store-peaks',
142				'nonce': ajax_var.nonce,
143				'url': url,
144				'peaks': normalizedData
145			},
146			success: function( response ){
147				qtWaveformDebug('Data stored: '+response);
148				return true;
149			},
150			fail: function(e){
151				qtWaveformDebug('Data not stored: '+response);
152				return false;
153			}
154		});
155	}
156
157	const peakSpacing = 4;
158	ctx.beginPath();
159	ctx.moveTo( 0, 0 );
160	let x;
161	// Draw the upper path.
162	for ( let i = 0; i < normalizedData.length; i++ ) {
163		let x = Math.round(width * i);
164		let height = normalizedData[i] * canvas.offsetHeight - padding;
165		ctx.moveTo( x, 0 );
166		ctx.lineTo( x, height );
167		ctx.lineTo( Math.round(width - gap + x)  , height);
168		ctx.lineTo( Math.round(width - gap + x), 0);
169		ctx.lineTo( width + x , 0);
170	}
171
172	// Original full
173	ctx.moveTo( 0, 0 );
174	ctx.strokeStyle = '#FFFFFF';
175	ctx.fillStyle="#FFFFFF";
176	ctx.fill();
177
178
179	// ===============
180	// The clone
181	// ===============
182	const canvasClone = jQuery.qtmplayerCanvasClone[0];//document.querySelector("canvas");
183	canvasClone.width = canvasClone.offsetWidth * dpr;
184	canvasClone.height = (canvasClone.offsetHeight + padding * 2) * dpr;
185	const ctxClone = canvasClone.getContext("2d");
186	ctxClone.scale(dpr, -dpr);
187	ctxClone.translate(0, - canvasClone.offsetHeight - padding - padding  ); // set Y = 0 to be in the middle of the canvas
188	ctxClone.beginPath();
189	ctxClone.moveTo( 0, 0 );
190	// Draw the upper path.
191	for ( let i = 0; i < normalizedData.length; i++ ) {
192		let x = width * i;
193		let height = normalizedData[i] * canvas.offsetHeight - padding;
194		ctxClone.moveTo( x, 0 );
195		ctxClone.lineTo( x, height );
196		ctxClone.lineTo( Math.round(width - gap + x)  , height);
197		ctxClone.lineTo( Math.round(width - gap + x), 0);
198		ctxClone.lineTo( width + x , 0);
199	}
200	// Clone for tracking
201	ctxClone.moveTo( 0, 0 );
202	ctxClone.strokeStyle = jQuery.qtmplayerCanvasCloneColor;
203	ctxClone.fillStyle=jQuery.qtmplayerCanvasCloneColor;
204	ctxClone.fill();
205
206
207};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.