diff --git a/src/components/DetailElement.jsx b/src/components/DetailElement.jsx index 29a8663..9a5fe52 100644 --- a/src/components/DetailElement.jsx +++ b/src/components/DetailElement.jsx @@ -41,7 +41,8 @@ const calculateDensities = function (el) { var textLength = 0; var linkAmount = 0; var listAmount = 0; - var textDensity = 4; + + var textDensity = 0; var linkDensity = 0; const childElements = getChildElementRoot(el); @@ -90,22 +91,20 @@ const calculateDensities = function (el) { linkAmount = elementAmounts.linkAmount; listAmount = elementAmounts.listAmount; - if (textLength < 900 && textLength > 600) { + if (textLength > 600) { textDensity = 3; - } else if (textLength < 600 && textLength > 300) { + } else if (textLength <= 600 && textLength >= 300) { textDensity = 2; } else if (textLength < 300 && textLength > 0) { textDensity = 1; - } else if (textLength === 0) { - textDensity = 0; } if (linkAmount > 3) { - linkDensity = 4; - } else if (linkAmount === 2 || linkAmount === 3) { linkDensity = 3; - } else if (linkAmount === 1) { + } else if (linkAmount === 2 || linkAmount === 3) { linkDensity = 2; + } else if (linkAmount === 1) { + linkDensity = 1; } return { textDensity: textDensity, linkDensity: linkDensity }; diff --git a/src/components/ScrollableTab.jsx b/src/components/ScrollableTab.jsx index 20ce584..46e90b8 100644 --- a/src/components/ScrollableTab.jsx +++ b/src/components/ScrollableTab.jsx @@ -59,13 +59,13 @@ function ScrollableTab({ onActiveTabChange, sonificationType, children }) { } if (type === "model") { - playTabModelSonification(panVal, frequencyVal, false); + playTabModelSonification(panVal, frequencyVal, !rightSideEnd); } else if (type === "earcon") { - playTabEarconSonification(); + playTabEarconSonification(!rightSideEnd, key, amountTabs); } if (reachedEndValue && endValueVisible) { - playTabModelSonification(panVal, frequencyVal, true); + // Chord End sound play... :) if (rightSideEnd) { endElement = 1; rightSideEnd = false; @@ -103,8 +103,8 @@ function ScrollableTab({ onActiveTabChange, sonificationType, children }) { return ( onHoverTab(tabId)} - onMouseOver={() => onHoverTab(tabId)} + //onTouchMove={() => onHoverTab(tabId)} + //onMouseOver={() => onHoverTab(tabId)} key={tabId} actionType={k.props.actionType} redirectLoc={k.props.redirectLoc} diff --git a/src/core/audio/AudioHandler.jsx b/src/core/audio/AudioHandler.jsx index c1c1bec..3fc403a 100644 --- a/src/core/audio/AudioHandler.jsx +++ b/src/core/audio/AudioHandler.jsx @@ -1,11 +1,46 @@ import * as Tone from "tone"; import { pushToSonificationLog } from "../log/SensorLogger"; import drumSample from "./samples/snare_drum.wav"; +import C2Flute from "./samples/flute_samples/C2.wav"; +import C3Flute from "./samples/flute_samples/C3.wav"; +import C4Flute from "./samples/flute_samples/C4.wav"; +import A2Flute from "./samples/flute_samples/A2.wav"; +import ASharp3Flute from "./samples/flute_samples/A#3.wav"; +import ASharp4Flute from "./samples/flute_samples/A#4.wav"; +import D2Flute from "./samples/flute_samples/D2.wav"; +import D3Flute from "./samples/flute_samples/D3.wav"; +import D4Flute from "./samples/flute_samples/D4.wav"; +import FSharp2Flute from "./samples/flute_samples/F#2.wav"; +import FSharp3Flute from "./samples/flute_samples/F#3.wav"; +import FSharp4Flute from "./samples/flute_samples/F#4.wav"; +import violaSample from "./samples/viola.wav"; + +import { getMotifByVersion } from "./MotifHandler"; +import { generateChord } from "./ChordHelper"; const drumSynth = new Tone.Sampler({ C3: drumSample, }).toDestination(); +const violaSynth = new Tone.Sampler({ + C5: violaSample, +}).toDestination(); + +const fluteSynth = new Tone.Sampler({ + C2: C2Flute, + C3: C3Flute, + C4: C4Flute, + A2: A2Flute, + "A#3": ASharp3Flute, + "A#4": ASharp4Flute, + D2: D2Flute, + D3: D3Flute, + D4: D4Flute, + "F#2": FSharp2Flute, + "F#3": FSharp3Flute, + "F#4": FSharp4Flute, +}).toDestination(); + const setRotation = (angle) => { Tone.Listener.forwardX.value = Math.sin(angle); Tone.Listener.forwardY.value = 0; @@ -18,6 +53,22 @@ const setRotationRamp = (panner, angle, rampTime) => { panner.positionZ.rampTo(-Math.cos(angle), rampTime); }; +// First three are small, then medium, then large and the link chooses the corresponding motif within the category... +const calculateDetailMotifVersion = function (textDensity, linkDensity) { + return 3 * textDensity + linkDensity; +}; + +const tabChordProgression = [ + generateChord(60, "major"), + generateChord(62, "minor"), + generateChord(64, "minor"), + generateChord(65, "major"), + generateChord(67, "major"), + generateChord(69, "minor"), + generateChord(71, "diminished"), + generateChord(72, "major"), +]; + var offCooldown = true; const playChordEndSound = function () { @@ -42,14 +93,30 @@ const playChordEndSound = function () { } }; +const calculatePlayedTabChord = function (endReached, tabIndex, tabAmount) { + const progress = tabIndex / (tabAmount - 1); + const chordListLength = tabChordProgression.length; + + if (!endReached) { + return Math.floor(progress * (chordListLength - 1)); + } + return Math.floor((1 - progress) * (chordListLength - 1)) + 1; +}; + // Maybe also dat... -export function playTabEarconSonification() { +export function playTabEarconSonification(endReached, tabIndex, tabAmount) { if (offCooldown) { - var loop = new Tone.Loop((time) => { - drumSynth.triggerAttackRelease("C3", "4n", time); - }, "4n"); - loop.iterations = 2; - loop.start(); + const now = Tone.now(); + const tabChordIndex = calculatePlayedTabChord( + endReached, + tabIndex, + tabAmount + ); + fluteSynth.triggerAttackRelease( + tabChordProgression[tabChordIndex], + "4n", + now + ); Tone.Transport.start(); pushToSonificationLog("tab_earcon"); offCooldown = false; @@ -60,8 +127,7 @@ export function playTabEarconSonification() { } export function playTabModelSonification(pannerVal, frequencyVal, endReached) { - - if(endReached) { + if (endReached) { playChordEndSound(); return; } @@ -97,12 +163,11 @@ export function playTabModelSonification(pannerVal, frequencyVal, endReached) { // Menu Sonification Paper. :) export function playDetailEarconSonification(textDensity, linkDensity) { if (offCooldown) { - var loop = new Tone.Loop((time) => { - drumSynth.triggerAttackRelease("C3", "4n", time); - }, "4n"); - loop.iterations = 2; - loop.start(); - drumSynth.context.resume(); + const synth = violaSynth.toDestination(); + getMotifByVersion( + calculateDetailMotifVersion(textDensity, linkDensity), + synth + ); Tone.Transport.start(); pushToSonificationLog("detail_earcon"); offCooldown = false; diff --git a/src/core/audio/MotifHandler.jsx b/src/core/audio/MotifHandler.jsx new file mode 100644 index 0000000..bd54398 --- /dev/null +++ b/src/core/audio/MotifHandler.jsx @@ -0,0 +1,112 @@ +import * as Tone from "tone"; + +// List of all Earcon-based Motifs used by the AudioHandler. + +const motifs = [ + getMotif1, + getMotif2, + getMotif3, + getMotif4, + getMotif5, + getMotif6, + getMotif7, + getMotif8, + getMotif9, + getMotif10, + getMotif11, + getMotif12, +]; + +// Small Motifs + +export function getMotif1(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("C#4", "4n", now + 0.16); +} + +export function getMotif2(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("E#4", "4n", now + 0.16); +} + +export function getMotif3(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("G#4", "4n", now + 0.16); +} + +export function getMotif4(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("A4", "4n", now + 0.16); +} + +// Medium Motifs + +export function getMotif5(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("C#4", "4n", now + 0.08); + synth.triggerAttackRelease("E4", "4n", now + 0.24); +} + +export function getMotif6(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("C#4", "4n", now + 0.08); + synth.triggerAttackRelease("G#4", "4n", now + 0.24); +} + +export function getMotif7(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("E4", "4n", now + 0.16); + synth.triggerAttackRelease("A4", "4n", now + 0.32); +} + +export function getMotif8(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("G#4", "4n", now + 0.08); + synth.triggerAttackRelease("C#5", "4n", now + 0.24); +} + +// Large Motifs + +export function getMotif9(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("C#3", "4n", now); + synth.triggerAttackRelease("C#4", "4n", now + 0.16); + synth.triggerAttackRelease("G#3", "4n", now + 0.32); + synth.triggerAttackRelease("G#4", "4n", now + 0.48); +} + +export function getMotif10(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("E3", "4n", now); + synth.triggerAttackRelease("E4", "4n", now + 0.16); + synth.triggerAttackRelease("G#3", "4n", now + 0.32); + synth.triggerAttackRelease("C#4", "4n", now + 0.48); +} + +export function getMotif11(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("E3", "4n", now); + synth.triggerAttackRelease("E4", "4n", now + 0.16); + synth.triggerAttackRelease("A3", "4n", now + 0.32); + synth.triggerAttackRelease("C#4", "4n", now + 0.48); +} + +export function getMotif12(synth) { + const now = Tone.now(); + synth.triggerAttackRelease("A3", "4n", now); + synth.triggerAttackRelease("A4", "4n", now + 0.16); + synth.triggerAttackRelease("C#4", "4n", now + 0.32); + synth.triggerAttackRelease("E4", "4n", now + 0.48); +} + +export function getMotifByVersion(versionNumber, synth) { + return motifs[versionNumber](synth); +} diff --git a/src/core/audio/samples/flute_samples/A#3.wav b/src/core/audio/samples/flute_samples/A#3.wav new file mode 100644 index 0000000..c2ba394 Binary files /dev/null and b/src/core/audio/samples/flute_samples/A#3.wav differ diff --git a/src/core/audio/samples/flute_samples/A#4.wav b/src/core/audio/samples/flute_samples/A#4.wav new file mode 100644 index 0000000..191c023 Binary files /dev/null and b/src/core/audio/samples/flute_samples/A#4.wav differ diff --git a/src/core/audio/samples/flute_samples/A2.wav b/src/core/audio/samples/flute_samples/A2.wav new file mode 100644 index 0000000..93bf62e Binary files /dev/null and b/src/core/audio/samples/flute_samples/A2.wav differ diff --git a/src/core/audio/samples/flute_samples/C2.wav b/src/core/audio/samples/flute_samples/C2.wav new file mode 100644 index 0000000..704e5d2 Binary files /dev/null and b/src/core/audio/samples/flute_samples/C2.wav differ diff --git a/src/core/audio/samples/flute_samples/C3.mp3 b/src/core/audio/samples/flute_samples/C3.mp3 new file mode 100644 index 0000000..81a959f Binary files /dev/null and b/src/core/audio/samples/flute_samples/C3.mp3 differ diff --git a/src/core/audio/samples/flute_samples/C3.wav b/src/core/audio/samples/flute_samples/C3.wav new file mode 100644 index 0000000..4c8a520 Binary files /dev/null and b/src/core/audio/samples/flute_samples/C3.wav differ diff --git a/src/core/audio/samples/flute_samples/C4.wav b/src/core/audio/samples/flute_samples/C4.wav new file mode 100644 index 0000000..de43fb9 Binary files /dev/null and b/src/core/audio/samples/flute_samples/C4.wav differ diff --git a/src/core/audio/samples/flute_samples/D2.wav b/src/core/audio/samples/flute_samples/D2.wav new file mode 100644 index 0000000..550340e Binary files /dev/null and b/src/core/audio/samples/flute_samples/D2.wav differ diff --git a/src/core/audio/samples/flute_samples/D3.wav b/src/core/audio/samples/flute_samples/D3.wav new file mode 100644 index 0000000..9aec8c2 Binary files /dev/null and b/src/core/audio/samples/flute_samples/D3.wav differ diff --git a/src/core/audio/samples/flute_samples/D4.wav b/src/core/audio/samples/flute_samples/D4.wav new file mode 100644 index 0000000..e286e6b Binary files /dev/null and b/src/core/audio/samples/flute_samples/D4.wav differ diff --git a/src/core/audio/samples/flute_samples/F#2.wav b/src/core/audio/samples/flute_samples/F#2.wav new file mode 100644 index 0000000..055c6b6 Binary files /dev/null and b/src/core/audio/samples/flute_samples/F#2.wav differ diff --git a/src/core/audio/samples/flute_samples/F#3.wav b/src/core/audio/samples/flute_samples/F#3.wav new file mode 100644 index 0000000..a4d668c Binary files /dev/null and b/src/core/audio/samples/flute_samples/F#3.wav differ diff --git a/src/core/audio/samples/flute_samples/F#4.wav b/src/core/audio/samples/flute_samples/F#4.wav new file mode 100644 index 0000000..8ed9ede Binary files /dev/null and b/src/core/audio/samples/flute_samples/F#4.wav differ diff --git a/src/core/audio/samples/viola.wav b/src/core/audio/samples/viola.wav new file mode 100644 index 0000000..abc6175 Binary files /dev/null and b/src/core/audio/samples/viola.wav differ diff --git a/src/index.css b/src/index.css index 1094313..75f1073 100644 --- a/src/index.css +++ b/src/index.css @@ -30,7 +30,7 @@ code { } canvas { - opacity: 1; + opacity: 0; z-index: 999; }