chart2music
Advanced tools
Comparing version 1.0.6 to 1.1.0
@@ -77,2 +77,3 @@ var c2mChart = (function (exports) { | ||
const HERTZ = [ | ||
16.3516, 17.32391, 18.35405, 19.44544, 20.60172, 21.82676, 23.12465, 24.49971, 25.95654, 27.5, 29.13524, 30.86771, | ||
32.7032, 34.64783, 36.7081, 38.89087, 41.20344, 43.65353, 46.2493, 48.99943, 51.91309, 55, 58.27047, 61.73541, | ||
@@ -85,2 +86,3 @@ 65.40639, 69.29566, 73.41619, 77.78175, 82.40689, 87.30706, 92.49861, 97.99886, 103.8262, 110, 116.5409, 123.4708, | ||
2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, | ||
4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, | ||
]; | ||
@@ -435,2 +437,54 @@ const SPEEDS = [1000, 250, 100, 50, 25]; | ||
}; | ||
const convertDataRow = (row) => { | ||
return row.map((point, index) => { | ||
if (typeof point === "number") { | ||
return { | ||
x: index, | ||
y: point | ||
}; | ||
} | ||
return point; | ||
}); | ||
}; | ||
const formatWrapper = (axis) => { | ||
const format = (num) => { | ||
if (isNaN(num)) { | ||
return "missing"; | ||
} | ||
if (axis.minimum && num < axis.minimum) { | ||
return "too low"; | ||
} | ||
if (axis.maximum && num > axis.maximum) { | ||
return "too high"; | ||
} | ||
return axis.format(num); | ||
}; | ||
return format; | ||
}; | ||
const isUnplayable = (yValue, yAxis) => { | ||
return isNaN(yValue) || yValue < yAxis.minimum || yValue > yAxis.maximum; | ||
}; | ||
const prepChartElement = (elem, title) => { | ||
if (!elem.hasAttribute("alt") && !elem.hasAttribute("aria-label")) { | ||
elem.setAttribute("aria-label", `${title}, Sonified chart`); | ||
} | ||
if (!elem.hasAttribute("role")) { | ||
elem.setAttribute("role", "img"); | ||
} | ||
}; | ||
const checkForNumberInput = (metadataByGroup, data) => { | ||
if (Array.isArray(data) && typeof data[0] === "number") { | ||
metadataByGroup[0].inputType = "number"; | ||
} | ||
else { | ||
let index = 0; | ||
for (const group in data) { | ||
if (detectDataPointType(data[group][0]) === "number") { | ||
metadataByGroup[index].inputType = "number"; | ||
} | ||
index++; | ||
} | ||
} | ||
return metadataByGroup; | ||
}; | ||
@@ -542,40 +596,91 @@ var SUPPORTED_CHART_TYPES; | ||
let context = null; | ||
const convertDataRow = (row) => { | ||
return row.map((point, index) => { | ||
if (typeof point === "number") { | ||
return { | ||
x: index, | ||
y: point | ||
const launchOptionDialog = ({ upper, lower }, cb, playCb) => { | ||
const previousElement = document.activeElement; | ||
const dialog = document.createElement("div"); | ||
dialog.setAttribute("role", "dialog"); | ||
dialog.innerHTML = `<h1>Options</h1> | ||
<p tabIndex="0">While navigating this chart, you may find some sounds too low or too high to hear. Alternatively, you may want to expand the range of the sounds available. Use these sliders to adjust the range of sound:</p> | ||
<form id="optionForm"> | ||
<div> | ||
<label> | ||
Lower hertz: | ||
<input type="range" min="0" max="${upper - 1}" step="1" id="lowerRange" value="${lower}" /> | ||
</label> | ||
</div> | ||
<div> | ||
<label> | ||
Upper hertz: | ||
<input type="range" min="${lower + 1}" max="${HERTZ.length - 1}" step="1" id="upperRange" value="${upper}" /> | ||
</label> | ||
</div> | ||
<div> | ||
<label> | ||
<input type="checkbox" id="global" checked /> | ||
Save my options for other charts on this page | ||
</label> | ||
</div> | ||
<input id="save" type="submit" value="Save" /> | ||
</form> | ||
`; | ||
const lowerRange = dialog.querySelector("#lowerRange"); | ||
const upperRange = dialog.querySelector("#upperRange"); | ||
const global = dialog.querySelector("#global"); | ||
if (!window) { | ||
global.parentElement.parentElement.style.display = " none"; | ||
} | ||
const save = () => { | ||
const lowerValue = Number(lowerRange.value); | ||
const upperValue = Number(upperRange.value); | ||
const saveGlobal = global.checked; | ||
cb(lowerValue, upperValue); | ||
if (window && saveGlobal) { | ||
if (!window.__chart2music_options__) { | ||
window.__chart2music_options__ = {}; | ||
} | ||
window.__chart2music_options__ = { | ||
_hertzClamps: { | ||
lower: lowerValue, | ||
upper: upperValue | ||
} | ||
}; | ||
} | ||
return point; | ||
esc(); | ||
}; | ||
dialog.querySelector("#optionForm").addEventListener("submit", (e) => { | ||
e.preventDefault(); | ||
save(); | ||
}); | ||
}; | ||
const formatWrapper = (axis) => { | ||
const format = (num) => { | ||
if (isNaN(num)) { | ||
return "missing"; | ||
dialog.querySelector("#save").addEventListener("click", (e) => { | ||
e.preventDefault(); | ||
save(); | ||
}); | ||
if (playCb) { | ||
lowerRange.addEventListener("change", () => { | ||
playCb(Number(lowerRange.value)); | ||
upperRange.min = String(Number(lowerRange.value) + 1); | ||
}); | ||
upperRange.addEventListener("change", () => { | ||
playCb(Number(upperRange.value)); | ||
lowerRange.max = String(Number(upperRange.value) - 1); | ||
}); | ||
} | ||
const esc = () => { | ||
previousElement.focus(); | ||
dialog.parentElement.removeChild(dialog); | ||
}; | ||
dialog.addEventListener("keydown", (evt) => { | ||
if (evt.key === "Escape") { | ||
esc(); | ||
} | ||
if (axis.minimum && num < axis.minimum) { | ||
return "too low"; | ||
} | ||
if (axis.maximum && num > axis.maximum) { | ||
return "too high"; | ||
} | ||
return axis.format(num); | ||
}; | ||
return format; | ||
}); | ||
dialog.addEventListener("blur", esc); | ||
document.body.appendChild(dialog); | ||
const p = dialog.querySelector("[tabIndex]"); | ||
p.focus(); | ||
}; | ||
const isUnplayable = (yValue, yAxis) => { | ||
return isNaN(yValue) || yValue < yAxis.minimum || yValue > yAxis.maximum; | ||
}; | ||
const prepChartElement = (elem, title) => { | ||
if (!elem.hasAttribute("alt") && !elem.hasAttribute("aria-label")) { | ||
elem.setAttribute("aria-label", `${title}, Sonified chart`); | ||
} | ||
if (!elem.hasAttribute("role")) { | ||
elem.setAttribute("role", "img"); | ||
} | ||
}; | ||
let context = null; | ||
const c2mChart = (input) => { | ||
@@ -591,17 +696,2 @@ const validationErrorString = validateInput(input); | ||
}; | ||
const checkForNumberInput = (metadataByGroup, data) => { | ||
if (Array.isArray(data) && typeof data[0] === "number") { | ||
metadataByGroup[0].inputType = "number"; | ||
} | ||
else { | ||
let index = 0; | ||
for (const group in data) { | ||
if (detectDataPointType(data[group][0]) === "number") { | ||
metadataByGroup[index].inputType = "number"; | ||
} | ||
index++; | ||
} | ||
} | ||
return metadataByGroup; | ||
}; | ||
class c2m { | ||
@@ -623,2 +713,6 @@ constructor(input) { | ||
this._explicitAxes = {}; | ||
this._hertzClamps = { | ||
upper: HERTZ.length - 12, | ||
lower: 21 | ||
}; | ||
this._type = input.type; | ||
@@ -703,2 +797,3 @@ this._providedAudioEngine = input.audioEngine; | ||
const tmp = this._data[i].shift(); | ||
this._pointIndex--; | ||
if (this._xAxis.minimum === tmp.x || | ||
@@ -731,2 +826,5 @@ this._xAxis.maximum === tmp.x) { | ||
} | ||
if (this._pointIndex < 0) { | ||
this._pointIndex = 0; | ||
} | ||
} | ||
@@ -977,2 +1075,6 @@ appendData(dataPoint, group) { | ||
callback: () => { | ||
if (!this._options.live) { | ||
this._sr.render("Not a live chart"); | ||
return; | ||
} | ||
this._monitorMode = !this._monitorMode; | ||
@@ -989,5 +1091,21 @@ this._sr.render(`Monitoring ${this._monitorMode ? "on" : "off"}`); | ||
} | ||
}, | ||
{ | ||
title: "Open options dialog", | ||
key: "o", | ||
callback: () => { | ||
this._checkAudioEngine(); | ||
launchOptionDialog(this._hertzClamps, (lowerIndex, upperIndex) => { | ||
this._setHertzClamps(lowerIndex, upperIndex); | ||
}, (hertzIndex) => { | ||
this._audioEngine?.playDataPoint(HERTZ[hertzIndex], 0, NOTE_LENGTH); | ||
}); | ||
} | ||
} | ||
]); | ||
} | ||
_setHertzClamps(lowerIndex, upperIndex) { | ||
this._hertzClamps.lower = lowerIndex; | ||
this._hertzClamps.upper = upperIndex; | ||
} | ||
_initializeData(userData) { | ||
@@ -1011,2 +1129,6 @@ if (!Array.isArray(userData)) { | ||
} | ||
if (window.__chart2music_options__?._hertzClamps) { | ||
const { lower, upper } = window.__chart2music_options__._hertzClamps; | ||
this._setHertzClamps(lower, upper); | ||
} | ||
}); | ||
@@ -1114,2 +1236,5 @@ this._chartElement.addEventListener("blur", () => { | ||
} | ||
_getHertzRange() { | ||
return HERTZ.slice(this._hertzClamps.lower, this._hertzClamps.upper); | ||
} | ||
_playCurrent() { | ||
@@ -1125,3 +1250,3 @@ if (!this._options.enableSound) { | ||
} | ||
_playDataPoint(current, statIndex, availableStats) { | ||
_checkAudioEngine() { | ||
if (!context) { | ||
@@ -1134,2 +1259,5 @@ context = new AudioContext(); | ||
} | ||
} | ||
_playDataPoint(current, statIndex, availableStats) { | ||
this._checkAudioEngine(); | ||
if (!this._audioEngine) { | ||
@@ -1141,2 +1269,3 @@ return; | ||
} | ||
const hertzes = this._getHertzRange(); | ||
const xPan = calcPan((current.x - this._xAxis.minimum) / | ||
@@ -1148,4 +1277,4 @@ (this._xAxis.maximum - this._xAxis.minimum)); | ||
} | ||
const yBin = interpolateBin(current.y, this._yAxis.minimum, this._yAxis.maximum, HERTZ.length - 1); | ||
this._audioEngine.playDataPoint(HERTZ[yBin], xPan, NOTE_LENGTH); | ||
const yBin = interpolateBin(current.y, this._yAxis.minimum, this._yAxis.maximum, hertzes.length - 1); | ||
this._audioEngine.playDataPoint(hertzes[yBin], xPan, NOTE_LENGTH); | ||
return; | ||
@@ -1157,4 +1286,4 @@ } | ||
} | ||
const yBin = interpolateBin(current.y2, this._y2Axis.minimum, this._y2Axis.maximum, HERTZ.length - 1); | ||
this._audioEngine.playDataPoint(HERTZ[yBin], xPan, NOTE_LENGTH); | ||
const yBin = interpolateBin(current.y2, this._y2Axis.minimum, this._y2Axis.maximum, hertzes.length - 1); | ||
this._audioEngine.playDataPoint(hertzes[yBin], xPan, NOTE_LENGTH); | ||
return; | ||
@@ -1168,4 +1297,4 @@ } | ||
} | ||
const yBin = interpolateBin(current[stat], this._yAxis.minimum, this._yAxis.maximum, HERTZ.length - 1); | ||
this._audioEngine.playDataPoint(HERTZ[yBin], xPan, NOTE_LENGTH); | ||
const yBin = interpolateBin(current[stat], this._yAxis.minimum, this._yAxis.maximum, hertzes.length - 1); | ||
this._audioEngine.playDataPoint(hertzes[yBin], xPan, NOTE_LENGTH); | ||
return; | ||
@@ -1178,5 +1307,5 @@ } | ||
} | ||
const yBin = interpolateBin(current[stat], this._yAxis.minimum, this._yAxis.maximum, HERTZ.length - 1); | ||
const yBin = interpolateBin(current[stat], this._yAxis.minimum, this._yAxis.maximum, hertzes.length - 1); | ||
setTimeout(() => { | ||
this._audioEngine.playDataPoint(HERTZ[yBin], xPan, NOTE_LENGTH); | ||
this._audioEngine.playDataPoint(hertzes[yBin], xPan, NOTE_LENGTH); | ||
}, SPEEDS[this._speedRateIndex] * interval * index); | ||
@@ -1183,0 +1312,0 @@ }); |
{ | ||
"name": "chart2music", | ||
"version": "1.0.6", | ||
"version": "1.1.0", | ||
"main": "dist/index.js", | ||
@@ -5,0 +5,0 @@ "module": "dist/index.mjs", |
Sorry, the diff of this file is not supported yet
126209
17
3020