Wordcloud sonification - both

by oysteinmoseng

HTML

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/wordcloud.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<script src="https://code.highcharts.com/modules/sonification.js"></script>

<div id="container"></div>
<div class="controls">
  <button id="play">Play chart</button>
  <div class="grow"></div>
  <label for="speed">Speed</label>
  <input
    id="speed"
    type="range"
    min="0.7"
    step="0.1"
    value="1"
    max="1.3"
    name="Speed"
  />
</div>

<pre id="text" style="display: none">
design concept proposal object process system word design refers something intentionally created thinking agent sometimes used refer inherent nature something design verb design expresses process developing design cases direct construction object without explicit prior plan considered design arts crafts design expected have purpose certain context usually satisfy certain goals constraints take account aesthetic functional economic environmental socio political considerations traditional examples designs include architectural engineering drawings circuit diagrams sewing patterns tangible artefacts business process models designing people produce designs called designers term designer usually refers someone works professionally one various design areas professions word designer generally qualified area practice example fashion designer product designer web designer interior designer designate practitioners architects engineers designer sequence activities produce design called design process
</pre>

CSS

#container {
  min-width: 220px;
  max-width: 400px;
  height: 300px;
}

#play {
  padding: 0.6rem 1.2rem;
  font-size: 1rem;
  line-height: 1rem;
  font-weight: 600;
  color: #fff;
  background-color: #303b4f;
  border: none;
  border-radius: 0.375rem;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  margin-right: 25px;
}

.controls {
  margin-top: 30px;
  max-width: 400px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.controls label {
  font-family: Verdana;
  margin-right: 5px;
}

.controls input {
  accent-color: #303b4f;
  cursor: pointer;
}

.grow {
    flex: 1;
}

JavaScript

const wordsToInclude = 40,
  text = document.getElementById("text").textContent,
  lines = text.replace(/[():'?0-9]+/g, "").split(/[,\. ]+/g),
  data = Object.entries(
    lines.reduce((acc, cur) => {
      acc[cur] = (acc[cur] || 0) + 1
      return acc
    }, {}),
  )
    .sort((a, b) => b[1] - a[1])
    .slice(0, wordsToInclude)

const chart = Highcharts.chart("container", {
  colors: ["#4a5a6a", "#8b6a58", "#3b5c5c", "#7a6b42", "#5e4630", "#2a3b4e"],
  accessibility: {
    keyboardNavigation: {
      focusBorder: {
        style: {
          color: "#f44",
        },
      },
    },
  },
  series: [
    {
      type: "wordcloud",
      name: "Occurrences",
      data,
      rotation: {
        to: 0,
      },
      states: {
        hover: {
          enabled: true,
          color: "#f44",
        },
      },
    },
  ],
  title: {
    text: "Wordcloud of Wikipedia's article on Design",
    align: "left",
  },
  subtitle: {
    text: `An excerpt, top ${wordsToInclude} words included`,
  },
  tooltip: {
    enabled: false,
  },
})

window.speechSynthesis.getVoices()
document.getElementById("play").onclick = () => {
  const instruments = [
      ["piano", "vibraphone", "flute", "plucked"], // small
      ["lead", "saxophone", "trumpet"], // large
    ],
    maxWeight = Math.max(...data.map((d) => d[1])),
    speed = parseFloat(document.getElementById("speed").value)
  let time = 0

  chart.series[0].points
    .sort(() => Math.random() - 0.5) // random order
    .forEach((p, i) => {
      const valFactor = p.weight / maxWeight,
        instrs = instruments[Math.round(valFactor)]
      chart.sonification.speak(
        p.name,
        {
          language: "en-US",
          name: "Samantha",
          volume: valFactor * 0.7 + 0.3,
          rate: 2.5 - valFactor * 2,
          pitch: 1.4 - valFactor * 0.8,
        },
        time + 80,
      )
      chart.sonification.playNote(
        instrs[i % instrs.length],
        {
          volume: valFactor,
        ...