Highcharts test tool

by oysteinmoseng

HTML

<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>

<div id="columnChart" class="container"></div>
<div id="scatterChart" class="container"></div>
<div id="lineChart" class="container"></div>

CSS

.container {
    min-width: 300px;
    max-width: 800px;
    height: 300px;
    margin: 1em auto;
}

JavaScript

// Plugin to visualize the chart using basic sonification

var each = Highcharts.each,
	merge = Highcharts.merge,
    audio = new (window.AudioContext || window.webkitAudioContext)();

Highcharts.Series.prototype.sonify = function (options, callback) {
    var gainNode = audio.createGain(),
        panNode = audio.createStereoPanner(), // Note: Panning might not be accessible to mono users
		oscillator = audio.createOscillator(), // Initial oscillator. Updated or replaced depending on smooth setting
    	series = this,
        numPoints = series.points.length,
        valueToFreq = function (val) {
        	var valMin = options.rangeMin || series.dataMin,
            	valMax = options.rangeMax || series.dataMax,
                freqStep = (options.maxFrequency - options.minFrequency) / (valMax - valMin);
            return options.minFrequency + (val - valMin) * freqStep;
        },
        timePerPoint = Math.min(options.maxDuration / numPoints, options.maxPointDuration),
        maxPointsNum = options.maxDuration / options.maxPointDuration,
        pointSkip = 1;

	// Skip over points if we have too many
    // We might want to use data grouping here
	if (timePerPoint < options.minPointDuration) {
    	pointSkip = numPoints / maxPointsNum;
    }

    // Init audio nodes
	panNode.pan.value = 0; // TODO
	gainNode.gain.value = options.volume;
	oscillator.type = options.waveType;
    oscillator.frequency.value = 0;	
	oscillator.connect(gainNode);
	gainNode.connect(panNode);
    panNode.connect(audio.destination);

    if (options.smooth) {
    	oscillator.start(audio.currentTime);
        for (var i = 0, point; i < numPoints; i += pointSkip) {
        	point = this.points[i];
    		oscillator.frequency.linearRampToValueAtTime(
            	valueToFreq(point.y),
                audio.currentTime + i * timePerPoint / 1000
            );
        }
        gainNode.gain.setTargetAtTime(0, audio.currentTime + i * timePerPoint / 1000, 0.1); // Fade
       ...