Skip to content

Commit

Permalink
Adds quantize() and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
stephband committed May 17, 2024
1 parent 5fd183a commit a8e3249
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
84 changes: 84 additions & 0 deletions modules/quantize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@

const assign = Object.assign;

/**
quantize()
Quantize events into triplets and duplets.
**/

function collect(split, events, i) {
let n = i - 1;
while(events[++n] && events[n][0] < split);
return n > i ?
events.slice(i, n) :
undefined ;
}

function toBeat0(output, event) {
const e = Array.from(event);
e[0] = 0;
output.push(e);
return output;
}

function quantizeScale(events, scale = 1, output) {
let i = 0;

const events00 = collect(scale * 0.0972222222, events, i);
if (events00) {
i += events00.length;
events00.reduce(toBeat0, output);
}

const events25 = collect(scale * 0.2916666667, events, i);
if (events25) i += events25.length;
const events33 = collect(scale * 0.4305555556, events, i);
if (events33) i += events33.length;
const events50 = collect(scale * 0.5694444444, events, i);
if (events50) i += events50.length;
const events67 = collect(scale * 0.7083333333, events, i);
if (events67) i += events67.length;
const events75 = collect(scale * 0.9027777778, events, i);

// Quadruplets
if (events25 && events50
|| events25 && events75
|| events50 && events75
|| events25 && events33
|| events33 && events50
|| events50 && events67
|| events67 && events75
) {
console.log('Quadruplets');
return;
}

if (events33) {
console.log('Triplets');
return events33.map((event) => assign([], event, { 0: 0.333333333 }));
}

// We already checked (events50 && events67) so this is exclusive OR. In
// english, that means there is only one event beat at 50% or 67% in this
// beat, and we want to fall through to looking at these events at 2x zoom
if (events50 || events67) {
console.log('Recurse at 2x');
return;
}

// Quadruplets
if (events25) {
return events25.map((event) => assign([], event, { 0: 0.25 }));
}

if (events75) {
return events75.map((event) => assign([], event, { 0: 0.75 }));
}

return output;
}

export default function quantize(events) {
const output = [];
return quantizeScale(events, 1, output);
}
46 changes: 46 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>&lt;scribe-music&gt;</title>

<meta charset="utf-8" />
<meta name="author" content="@stephband" />
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />

<script title="debug">window.DEBUG = true;</script>
</head>
<body>
<script type="module">
import quantize from '../modules/quantize.js';
import test from '../lib/fn/modules/test.js';

const assign = Object.assign;

test('Quantize', [
[],
[[0, 'note', 'C4', 1, 1]],
[[0.25, 'note', 'C4', 1, 1]],
[[0.25, 'note', 'C4', 1, 1]],
[[0.333333333, 'note', 'C4', 1, 1]],
[[0.333333333, 'note', 'C4', 1, 1]],

[[0.75, 'note', 'C4', 1, 1]],
[[0.75, 'note', 'C4', 1, 1]]
], (expect, done) => {
expect(quantize([]));
expect(quantize([[0.0, 'note', 'C4', 1, 1]]));
expect(quantize([[0.1, 'note', 'C4', 1, 1]]));
expect(quantize([[0.2, 'note', 'C4', 1, 1]]));
expect(quantize([[0.3, 'note', 'C4', 1, 1]]));
expect(quantize([[0.4, 'note', 'C4', 1, 1]]));
quantize([[0.5, 'note', 'C4', 1, 1]]);
quantize([[0.6, 'note', 'C4', 1, 1]]);
quantize([[0.7, 'note', 'C4', 1, 1]]);
expect(quantize([[0.8, 'note', 'C4', 1, 1]]));
expect(quantize([[0.9, 'note', 'C4', 1, 1]]));
done();
});
</script>
</body>
</html>

0 comments on commit a8e3249

Please sign in to comment.