|
1 |
| -/** [p5.sound] Version: 1.0.0 - 2021-02-24 */ |
| 1 | +/** [p5.sound] Version: 1.0.0 - 2021-03-04 */ |
2 | 2 | /**
|
3 | 3 | * <p>p5.sound extends p5 with <a href="http://caniuse.com/audio-api"
|
4 | 4 | * target="_blank">Web Audio</a> functionality including audio input,
|
@@ -1360,153 +1360,7 @@ var _createCounterBuffer = function _createCounterBuffer(buffer) {
|
1360 | 1360 | }
|
1361 | 1361 |
|
1362 | 1362 | return audioBuf;
|
1363 |
| -}; |
1364 |
| - |
1365 |
| - |
1366 |
| -var Peak = function Peak(amp, i) { |
1367 |
| - soundfile_classCallCheck(this, Peak); |
1368 |
| - |
1369 |
| - this.sampleIndex = i; |
1370 |
| - this.amplitude = amp; |
1371 |
| - this.tempos = []; |
1372 |
| - this.intervals = []; |
1373 |
| -}; |
1374 |
| - |
1375 |
| - |
1376 |
| -function getPeaksAtThreshold(data, threshold) { |
1377 |
| - var peaksObj = {}; |
1378 |
| - var length = data.length; |
1379 |
| - |
1380 |
| - for (var i = 0; i < length; i++) { |
1381 |
| - if (data[i] > threshold) { |
1382 |
| - var amp = data[i]; |
1383 |
| - var peak = new Peak(amp, i); |
1384 |
| - peaksObj[i] = peak; |
1385 |
| - |
1386 |
| - i += 6000; |
1387 |
| - } |
1388 |
| - |
1389 |
| - i++; |
1390 |
| - } |
1391 |
| - |
1392 |
| - return peaksObj; |
1393 |
| -} |
1394 |
| - |
1395 |
| - |
1396 |
| -function countIntervalsBetweenNearbyPeaks(peaksObj) { |
1397 |
| - var intervalCounts = []; |
1398 |
| - var peaksArray = Object.keys(peaksObj).sort(); |
1399 |
| - |
1400 |
| - for (var index = 0; index < peaksArray.length; index++) { |
1401 |
| - for (var i = 0; i < 10; i++) { |
1402 |
| - var startPeak = peaksObj[peaksArray[index]]; |
1403 |
| - var endPeak = peaksObj[peaksArray[index + i]]; |
1404 |
| - |
1405 |
| - if (startPeak && endPeak) { |
1406 |
| - var startPos = startPeak.sampleIndex; |
1407 |
| - var endPos = endPeak.sampleIndex; |
1408 |
| - var interval = endPos - startPos; |
1409 |
| - |
1410 |
| - if (interval > 0) { |
1411 |
| - startPeak.intervals.push(interval); |
1412 |
| - } |
1413 |
| - |
1414 |
| - |
1415 |
| - var foundInterval = intervalCounts.some(function (intervalCount) { |
1416 |
| - if (intervalCount.interval === interval) { |
1417 |
| - intervalCount.count++; |
1418 |
| - return intervalCount; |
1419 |
| - } |
1420 |
| - }); |
1421 |
| - |
1422 |
| - if (!foundInterval) { |
1423 |
| - intervalCounts.push({ |
1424 |
| - interval: interval, |
1425 |
| - count: 1 |
1426 |
| - }); |
1427 |
| - } |
1428 |
| - } |
1429 |
| - } |
1430 |
| - } |
1431 |
| - |
1432 |
| - return intervalCounts; |
1433 |
| -} |
1434 |
| - |
1435 |
| - |
1436 |
| -function groupNeighborsByTempo(intervalCounts, sampleRate) { |
1437 |
| - var tempoCounts = []; |
1438 |
| - intervalCounts.forEach(function (intervalCount) { |
1439 |
| - try { |
1440 |
| - var theoreticalTempo = Math.abs(60 / (intervalCount.interval / sampleRate)); |
1441 |
| - theoreticalTempo = mapTempo(theoreticalTempo); |
1442 |
| - var foundTempo = tempoCounts.some(function (tempoCount) { |
1443 |
| - if (tempoCount.tempo === theoreticalTempo) return tempoCount.count += intervalCount.count; |
1444 |
| - }); |
1445 |
| - |
1446 |
| - if (!foundTempo) { |
1447 |
| - if (isNaN(theoreticalTempo)) { |
1448 |
| - return; |
1449 |
| - } |
1450 |
| - |
1451 |
| - tempoCounts.push({ |
1452 |
| - tempo: Math.round(theoreticalTempo), |
1453 |
| - count: intervalCount.count |
1454 |
| - }); |
1455 |
| - } |
1456 |
| - } catch (e) { |
1457 |
| - throw e; |
1458 |
| - } |
1459 |
| - }); |
1460 |
| - return tempoCounts; |
1461 |
| -} |
1462 |
| - |
1463 |
| - |
1464 |
| -function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { |
1465 |
| - var peaksAtTopTempo = []; |
1466 |
| - var peaksArray = Object.keys(peaksObj).sort(); |
1467 |
| - |
1468 |
| - for (var i = 0; i < peaksArray.length; i++) { |
1469 |
| - var key = peaksArray[i]; |
1470 |
| - var peak = peaksObj[key]; |
1471 |
| - |
1472 |
| - for (var j = 0; j < peak.intervals.length; j++) { |
1473 |
| - var intervalBPM = Math.round(Math.abs(60 / (peak.intervals[j] / sampleRate))); |
1474 |
| - intervalBPM = mapTempo(intervalBPM); |
1475 |
| - |
1476 |
| - if (Math.abs(intervalBPM - tempo) < bpmVariance) { |
1477 |
| - peaksAtTopTempo.push(peak.sampleIndex / sampleRate); |
1478 |
| - } |
1479 |
| - } |
1480 |
| - } |
1481 |
| - |
1482 |
| - |
1483 |
| - peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { |
1484 |
| - var dif = arr[index + 1] - peakTime; |
1485 |
| - |
1486 |
| - if (dif > 0.01) { |
1487 |
| - return true; |
1488 |
| - } |
1489 |
| - }); |
1490 |
| - return peaksAtTopTempo; |
1491 |
| -} |
1492 |
| - |
1493 |
| - |
1494 |
| -function mapTempo(theoreticalTempo) { |
1495 |
| - if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { |
1496 |
| - return; |
1497 |
| - } |
1498 |
| - |
1499 |
| - |
1500 |
| - while (theoreticalTempo < 90) { |
1501 |
| - theoreticalTempo *= 2; |
1502 |
| - } |
1503 |
| - |
1504 |
| - while (theoreticalTempo > 180 && theoreticalTempo > 90) { |
1505 |
| - theoreticalTempo /= 2; |
1506 |
| - } |
1507 |
| - |
1508 |
| - return theoreticalTempo; |
1509 |
| -} |
| 1363 | +}; |
1510 | 1364 |
|
1511 | 1365 |
|
1512 | 1366 | var Cue = function Cue(callback, time, id, val) {
|
@@ -2218,8 +2072,6 @@ function () {
|
2218 | 2072 | }
|
2219 | 2073 |
|
2220 | 2074 | this._counterNode.stop(now + time);
|
2221 |
| - |
2222 |
| - this._onended(this); |
2223 | 2075 | }
|
2224 | 2076 | }
|
2225 | 2077 | }, {
|
@@ -2854,75 +2706,10 @@ function () {
|
2854 | 2706 | bufferSourceNode.connect(this.output);
|
2855 | 2707 | return bufferSourceNode;
|
2856 | 2708 | }
|
2857 |
| - /** |
2858 |
| - * processPeaks returns an array of timestamps where it thinks there is a beat. |
2859 |
| - * |
2860 |
| - * This is an asynchronous function that processes the soundfile in an offline audio context, |
2861 |
| - * and sends the results to your callback function. |
2862 |
| - * |
2863 |
| - * The process involves running the soundfile through a lowpass filter, and finding all of the |
2864 |
| - * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, |
2865 |
| - * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. |
2866 |
| - * |
2867 |
| - * @method processPeaks |
2868 |
| - * @for p5.SoundFile |
2869 |
| - * @param {Function} callback a function to call once this data is returned |
2870 |
| - * @param {Number} [initThreshold] initial threshold defaults to 0.9 |
2871 |
| - * @param {Number} [minThreshold] minimum threshold defaults to 0.22 |
2872 |
| - * @param {Number} [minPeaks] minimum number of peaks defaults to 200 |
2873 |
| - * @return {Array} Array of timestamped peaks |
2874 |
| - */ |
2875 |
| - |
2876 | 2709 | }, {
|
2877 | 2710 | key: "processPeaks",
|
2878 | 2711 | value: function processPeaks(callback, _initThreshold, _minThreshold, _minPeaks) {
|
2879 |
| - var bufLen = this.buffer.length; |
2880 |
| - var sampleRate = this.buffer.sampleRate; |
2881 |
| - var buffer = this.buffer; |
2882 |
| - var allPeaks = []; |
2883 |
| - var initialThreshold = _initThreshold || 0.9, |
2884 |
| - threshold = initialThreshold, |
2885 |
| - minThreshold = _minThreshold || 0.22, |
2886 |
| - minPeaks = _minPeaks || 200; |
2887 |
| - |
2888 |
| - var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate); |
2889 |
| - |
2890 |
| - var source = offlineContext.createBufferSource(); |
2891 |
| - source.buffer = buffer; |
2892 |
| - |
2893 |
| - var filter = offlineContext.createBiquadFilter(); |
2894 |
| - filter.type = 'lowpass'; |
2895 |
| - source.connect(filter); |
2896 |
| - filter.connect(offlineContext.destination); |
2897 |
| - |
2898 |
| - source.start(0); |
2899 |
| - offlineContext.startRendering(); |
2900 |
| - |
2901 |
| - offlineContext.oncomplete = function (e) { |
2902 |
| - if (!self.panner) return; |
2903 |
| - var filteredBuffer = e.renderedBuffer; |
2904 |
| - var bufferData = filteredBuffer.getChannelData(0); |
2905 |
| - |
2906 |
| - do { |
2907 |
| - allPeaks = getPeaksAtThreshold(bufferData, threshold); |
2908 |
| - threshold -= 0.005; |
2909 |
| - } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold); |
2910 |
| - |
2911 |
| - |
2912 |
| - var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); |
2913 |
| - |
2914 |
| - var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate); |
2915 |
| - |
2916 |
| - var topTempos = groups.sort(function (intA, intB) { |
2917 |
| - return intB.count - intA.count; |
2918 |
| - }).splice(0, 5); |
2919 |
| - |
2920 |
| - this.tempo = topTempos[0].tempo; |
2921 |
| - |
2922 |
| - var bpmVariance = 5; |
2923 |
| - var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance); |
2924 |
| - callback(tempoPeaks); |
2925 |
| - }; |
| 2712 | + console.warn('processPeaks is deprecated'); |
2926 | 2713 | }
|
2927 | 2714 | /**
|
2928 | 2715 | * Schedule events to trigger every time a MediaElement
|
|
0 commit comments