Skip to content

Commit

Permalink
Add alternate colour palettes
Browse files Browse the repository at this point in the history
  • Loading branch information
pcprince committed Jul 1, 2024
1 parent 3c55f06 commit b44aaaa
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 19 deletions.
13 changes: 10 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -743,14 +743,21 @@ <h5 class="modal-title" id="settingsModalLabel">Settings</h5>
<input type="checkbox" id="settings-file-time-checkbox" style="vertical-align: middle;">
<label for="settings-file-time-checkbox" id="settings-file-time-label">Display real time on x axis</label>
<br>
<input type="checkbox" id="settings-dynamic-colours-checkbox" style="vertical-align: middle;">
<label for="settings-dynamic-colours-checkbox" id="settings-dynamic-colours-label">Use dynamic spectrogram colouring</label>
<br>
<input type="checkbox" id="settings-video-line-checkbox" style="vertical-align: middle;">
<label for="settings-video-line-checkbox" id="settings-video-line-label">Enable tracking line on exported video</label>
<br>
<input type="checkbox" id="settings-video-fixed-fps-checkbox" style="vertical-align: middle;">
<label for="settings-video-fixed-fps-checkbox" id="settings-video-fixed-fps-label">Favour frame rate over file size when generating videos</label>
<hr>
<label for="settings-monochrome-select" id="settings-monochrome-label" style="margin-right: 5px; margin-top: 3px;">Colour palette:</label>
<select id="settings-monochrome-select">
<option value="0">Default</option>
<option value="1">Monochrome</option>
<option value="2">Inverse monochrome</option>
</select>
<br>
<input type="checkbox" id="settings-dynamic-colours-checkbox" style="vertical-align: middle;">
<label for="settings-dynamic-colours-checkbox" id="settings-dynamic-colours-label">Use dynamic spectrogram colouring</label>
</div>
<div class="modal-footer">
<button id="settings-cancel-button" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
Expand Down
16 changes: 13 additions & 3 deletions scripts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const settingsFileTimeLabel = document.getElementById('settings-file-time-label'
const settingsDynamicColoursCheckbox = document.getElementById('settings-dynamic-colours-checkbox');
const settingsVideoLineCheckbox = document.getElementById('settings-video-line-checkbox');
const settingsVideoFixedFPSCheckbox = document.getElementById('settings-video-fixed-fps-checkbox');
const settingsMonochromeSelect = document.getElementById('settings-monochrome-select');

// Example file variables

Expand Down Expand Up @@ -203,6 +204,13 @@ let xAxisHeading = 'Time (S)';

let useDynamicColours = false;

// Whether or not to use a monochrome colour palette

const COLOUR_MAP_DEFAULT = 0;
const COLOUR_MAP_MONOCHROME = 1;
const COLOUR_MAP_INVERSE_MONOCHROME = 2;
let colourMapIndex = COLOUR_MAP_DEFAULT;

// File variables

let fileHandler;
Expand Down Expand Up @@ -1712,7 +1720,7 @@ function drawWaveformPlot (samples, isInitialRender, spectrogramCompletionTime)

const zoomLevel = (thresholdScaleIndex === THRESHOLD_SCALE_DECIBEL) ? getDecibelZoomY() : getZoomY();

drawWaveform(samples, offset, displayLength, zoomLevel, (waveformCompletionTime) => {
drawWaveform(samples, offset, displayLength, zoomLevel, colourMapIndex, (waveformCompletionTime) => {

if (isInitialRender) {

Expand Down Expand Up @@ -1791,7 +1799,7 @@ function estimateRenderTime () {
*/
function drawPlots (samples, isInitialRender) {

drawSpectrogram(processedSpectrumFrames, useDynamicColours ? spectrumMin : STATIC_COLOUR_MIN, useDynamicColours ? spectrumMax : STATIC_COLOUR_MAX, async (completionTime) => {
drawSpectrogram(processedSpectrumFrames, useDynamicColours ? spectrumMin : STATIC_COLOUR_MIN, useDynamicColours ? spectrumMax : STATIC_COLOUR_MAX, colourMapIndex, async (completionTime) => {

resetCanvas(spectrogramThresholdCanvas);
spectrogramLoadingSVG.style.display = 'none';
Expand Down Expand Up @@ -4931,11 +4939,13 @@ settingsApplyButton.addEventListener('click', () => {

const changedUseFileTime = useFileTime !== settingsFileTimeCheckbox.checked;
const changedUseDynamicColours = useDynamicColours !== settingsDynamicColoursCheckbox.checked;
const changedColourMap = colourMapIndex !== parseInt(settingsMonochromeSelect.value);

useFileTime = settingsFileTimeCheckbox.checked;
useDynamicColours = settingsDynamicColoursCheckbox.checked;
videoLineEnabled = settingsVideoLineCheckbox.checked;
fixedFpsEnabled = settingsVideoFixedFPSCheckbox.checked;
colourMapIndex = parseInt(settingsMonochromeSelect.value);

// If setting has been changed, update the relevant UI

Expand All @@ -4946,7 +4956,7 @@ settingsApplyButton.addEventListener('click', () => {

}

if (changedUseDynamicColours) {
if (changedUseDynamicColours || changedColourMap) {

setTimeout(() => {

Expand Down
13 changes: 10 additions & 3 deletions scripts/spectrogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const spectrogram = new Array(PIXEL_WIDTH * PIXEL_HEIGHT);

// 255 colours from Jet
const rgbColours = [[0, 0, 131], [0, 2, 132], [0, 4, 133], [0, 6, 135], [0, 8, 136], [0, 9, 137], [0, 11, 138], [0, 13, 140], [0, 15, 141], [0, 17, 142], [0, 19, 143], [0, 21, 144], [0, 23, 146], [0, 24, 147], [0, 26, 148], [0, 28, 149], [0, 30, 151], [0, 32, 152], [0, 34, 153], [0, 36, 154], [0, 38, 155], [0, 39, 157], [0, 41, 158], [0, 43, 159], [0, 45, 160], [0, 47, 161], [0, 49, 163], [0, 51, 164], [0, 53, 165], [0, 54, 166], [0, 56, 168], [0, 58, 169], [0, 60, 170], [0, 63, 171], [0, 66, 173], [0, 69, 174], [0, 72, 175], [0, 75, 177], [0, 79, 178], [1, 82, 179], [1, 85, 181], [1, 88, 182], [1, 91, 183], [1, 94, 185], [1, 97, 186], [1, 100, 188], [1, 103, 189], [1, 106, 190], [1, 110, 192], [1, 113, 193], [1, 116, 194], [2, 119, 196], [2, 122, 197], [2, 125, 198], [2, 128, 200], [2, 131, 201], [2, 134, 202], [2, 137, 204], [2, 140, 205], [2, 144, 206], [2, 147, 208], [2, 150, 209], [2, 153, 210], [2, 156, 212], [3, 159, 213], [3, 162, 215], [3, 165, 216], [3, 168, 217], [3, 171, 219], [3, 175, 220], [3, 178, 221], [3, 181, 223], [3, 184, 224], [3, 187, 225], [3, 190, 227], [3, 193, 228], [3, 196, 229], [4, 199, 231], [4, 202, 232], [4, 205, 233], [4, 209, 235], [4, 212, 236], [4, 215, 237], [4, 218, 239], [4, 221, 240], [4, 224, 242], [4, 227, 243], [4, 230, 244], [4, 233, 246], [5, 236, 247], [5, 240, 248], [5, 243, 250], [5, 246, 251], [5, 249, 252], [5, 252, 254], [5, 255, 255], [9, 255, 251], [13, 255, 247], [17, 255, 243], [21, 255, 239], [25, 255, 235], [28, 255, 231], [32, 255, 227], [36, 255, 223], [40, 255, 219], [44, 255, 215], [48, 255, 211], [52, 255, 207], [56, 255, 203], [60, 255, 199], [64, 255, 195], [68, 255, 191], [71, 255, 187], [75, 255, 183], [79, 255, 179], [83, 255, 175], [87, 255, 171], [91, 255, 167], [95, 255, 163], [99, 255, 159], [103, 255, 155], [107, 255, 151], [110, 255, 147], [114, 255, 143], [118, 255, 139], [122, 255, 135], [126, 255, 131], [130, 255, 128], [134, 255, 124], [138, 255, 120], [142, 255, 116], [146, 255, 112], [150, 255, 108], [153, 255, 104], [157, 255, 100], [161, 255, 96], [165, 255, 92], [169, 255, 88], [173, 255, 84], [177, 255, 80], [181, 255, 76], [185, 255, 72], [189, 255, 68], [193, 255, 64], [196, 255, 60], [200, 255, 56], [204, 255, 52], [208, 255, 48], [212, 255, 44], [216, 255, 40], [220, 255, 36], [224, 255, 32], [228, 255, 28], [232, 255, 24], [235, 255, 20], [239, 255, 16], [243, 255, 12], [247, 255, 8], [251, 255, 4], [255, 255, 0], [255, 251, 0], [255, 247, 0], [255, 243, 0], [255, 239, 0], [255, 235, 0], [255, 231, 0], [254, 227, 0], [254, 223, 0], [254, 219, 0], [254, 215, 0], [254, 210, 0], [254, 206, 0], [254, 202, 0], [254, 198, 0], [254, 194, 0], [254, 190, 0], [254, 186, 0], [254, 182, 0], [253, 178, 0], [253, 174, 0], [253, 170, 0], [253, 166, 0], [253, 162, 0], [253, 158, 0], [253, 154, 0], [253, 150, 0], [253, 146, 0], [253, 142, 0], [253, 138, 0], [253, 134, 0], [253, 130, 0], [252, 125, 0], [252, 121, 0], [252, 117, 0], [252, 113, 0], [252, 109, 0], [252, 105, 0], [252, 101, 0], [252, 97, 0], [252, 93, 0], [252, 89, 0], [252, 85, 0], [252, 81, 0], [252, 77, 0], [251, 73, 0], [251, 69, 0], [251, 65, 0], [251, 61, 0], [251, 57, 0], [251, 53, 0], [251, 49, 0], [251, 45, 0], [251, 40, 0], [251, 36, 0], [251, 32, 0], [251, 28, 0], [250, 24, 0], [250, 20, 0], [250, 16, 0], [250, 12, 0], [250, 8, 0], [250, 4, 0], [250, 0, 0], [246, 0, 0], [242, 0, 0], [239, 0, 0], [235, 0, 0], [231, 0, 0], [227, 0, 0], [223, 0, 0], [220, 0, 0], [216, 0, 0], [212, 0, 0], [208, 0, 0], [204, 0, 0], [200, 0, 0], [197, 0, 0], [193, 0, 0], [189, 0, 0], [185, 0, 0], [181, 0, 0], [178, 0, 0], [174, 0, 0], [170, 0, 0], [166, 0, 0], [162, 0, 0], [159, 0, 0], [155, 0, 0], [151, 0, 0], [147, 0, 0], [143, 0, 0], [139, 0, 0], [136, 0, 0], [132, 0, 0], [128, 0, 0], [128, 0, 0]];
const monochromeRgbColours = Array.from({length: 256}, (_, i) => [i, i, i]);
const inverseMonochromeRgbColours = Array.from({length: 256}, (_, i) => [255 - i, 255 - i, 255 - i]);

const colourMaps = [rgbColours, monochromeRgbColours, inverseMonochromeRgbColours];

/**
* Fast approximation of log2()
Expand All @@ -33,7 +37,7 @@ const integerBuffer = new Int32Array(fastLogBuffer);
const floatBuffer = new Float32Array(fastLogBuffer);

function fastLog2 (n) {

floatBuffer[0] = n;
const t = integerBuffer[0] * 1.1920928955078125e-7;
return t - 126.94269504;
Expand Down Expand Up @@ -94,9 +98,10 @@ function calculateSpectrogramFrames (sampleArray, sampleArrayLength, offset, len
* @param {number[][]} spectrogram 2D array created by calculateSpectrogramFrames()
* @param {number} min log2(Minimum value in spectrogram)
* @param {number} max log2(Maximum value in spectrogram)
* @param {number} colourMapIndex Index of colour map
* @param {function} callback Function to be called on completion
*/
function drawSpectrogram (spectrogram, min, max, callback) {
function drawSpectrogram (spectrogram, min, max, colourMapIndex, callback) {

const startTime = new Date();

Expand All @@ -106,6 +111,8 @@ function drawSpectrogram (spectrogram, min, max, callback) {

const pixels = id.data;

const colourMap = colourMaps[colourMapIndex];

for (let i = 0; i < PIXEL_HEIGHT; i += 1) {

for (let j = 0; j < PIXEL_WIDTH; j += 1) {
Expand All @@ -121,7 +128,7 @@ function drawSpectrogram (spectrogram, min, max, callback) {
colourIndex = Math.max(colourIndex, 0);
colourIndex = Math.min(colourIndex, 255);

colour = rgbColours[colourIndex];
colour = colourMap[colourIndex];

}

Expand Down
28 changes: 18 additions & 10 deletions scripts/waveform.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@

const wavCanvas = document.getElementById('waveform-canvas');

const WAVEFORM_COLOURS_AGBR = [[0, 77, 153, 255], [0, 0, 0, 255], [0, 0, 0, 255]];
const WAVEFORM_COLOURS_HEX = ['#004d99', '#000000', '#000000'];

/**
* Draw the waveform plot
* @param {canvas} canvas Canvas to be drawn to
* @param {number[]} data Absolute values of samples to be plotted. Either raw data or grouped into columns.
* @param {number} colourMapIndex Index of colour map
* @param {number} startTime Time when render started
* @param {function} callback Function called on completion
*/
function renderRawWaveform (canvas, pointData, startTime, callback) {
function renderRawWaveform (canvas, pointData, colourMapIndex, startTime, callback) {

const ctx = canvas.getContext('2d');

ctx.strokeStyle = '#004d99';
ctx.strokeStyle = WAVEFORM_COLOURS_HEX[colourMapIndex];
ctx.lineWidth = 1;

ctx.beginPath();
Expand Down Expand Up @@ -59,10 +63,11 @@ function renderRawWaveform (canvas, pointData, startTime, callback) {
* Draw the waveform plot
* @param {canvas} canvas Canvas to be drawn to
* @param {number[]} data Absolute values of samples to be plotted
* @param {number} colourMapIndex Index of colour map
* @param {number} startTime Time when render started
* @param {function} callback Function called on completion
*/
function renderWaveform (canvas, data, startTime, callback) {
function renderWaveform (canvas, data, colourMapIndex, startTime, callback) {

const ctx = canvas.getContext('2d', {willReadFrequently: true});

Expand All @@ -85,10 +90,12 @@ function renderWaveform (canvas, data, startTime, callback) {

const index = j * (WAV_PIXEL_WIDTH * 4) + i * 4;

pixels[index] = 0;
pixels[index + 1] = 77;
pixels[index + 2] = 153;
pixels[index + 3] = 255;
const colour = WAVEFORM_COLOURS_AGBR[colourMapIndex];

pixels[index] = colour[0];
pixels[index + 1] = colour[1];
pixels[index + 2] = colour[2];
pixels[index + 3] = colour[3];

}

Expand All @@ -113,9 +120,10 @@ function renderWaveform (canvas, data, startTime, callback) {
* @param {number} offset Offset from start of sample array to start rendering
* @param {number} length Number of samples to render
* @param {number} yZoom Amount to zoom in plot on y axis
* @param {number} colourMapIndex Index of colour map
* @param {function} callback Function called on completion
*/
function drawWaveform (samples, offset, length, yZoom, callback) {
function drawWaveform (samples, offset, length, yZoom, colourMapIndex, callback) {

const WAV_PIXEL_WIDTH = wavCanvas.width;
const WAV_PIXEL_HEIGHT = wavCanvas.height;
Expand Down Expand Up @@ -177,7 +185,7 @@ function drawWaveform (samples, offset, length, yZoom, callback) {

}

renderRawWaveform(wavCanvas, pointData, startTime, callback);
renderRawWaveform(wavCanvas, pointData, colourMapIndex, startTime, callback);

} else {

Expand Down Expand Up @@ -217,7 +225,7 @@ function drawWaveform (samples, offset, length, yZoom, callback) {

}

renderWaveform(wavCanvas, pointData, startTime, callback);
renderWaveform(wavCanvas, pointData, colourMapIndex, startTime, callback);

}

Expand Down

0 comments on commit b44aaaa

Please sign in to comment.