File size: 2,072 Bytes
4cadbaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

const Node = require("./node.js");
const Navigator = require("./navigator.js");



const HEART_BEAT = 800;	// in ms
const SIMULTANEOUS_INTERVAL = HEART_BEAT * 0.24;


const normalizeInterval = interval => Math.tanh(interval / SIMULTANEOUS_INTERVAL);


// greater softIndexFactor make 'harder' soft index
const makeNoteSoftIndex = function (notes, index, {softIndexFactor = 1} = {}) {
	index = Number(index);

	const note = notes[index];

	// make soft index
	if (index > 0) {
		const lastNote = notes[index - 1];

		console.assert(note.start != null, "note.start is null", note);
		console.assert(lastNote.start != null, "lastNote.start is null", lastNote);

		note.deltaSi = normalizeInterval((note.start - lastNote.start) * softIndexFactor);
		note.softIndex = lastNote.softIndex + note.deltaSi;

		console.assert(!Number.isNaN(note.deltaSi), "note.deltaSi is NaN.", note.start, lastNote.start);
	}
	else {
		note.softIndex = 0;
		note.deltaSi = 0;
	}
};


const makeMatchNodes = function (note, criterion, zeroNode = Node.zero()) {
	note.matches = [];

	const targetList = criterion.pitchMap[note.pitch];
	if (targetList) {
		for (const targetNote of targetList) {
			const node = new Node(note, targetNote);
			if (zeroNode)
				node.evaluatePrev(zeroNode);

			note.matches.push(node);
		}
	}
};


const genNotationContext = function (notation, {softIndexFactor = 1} = {}) {
	for (let i = 0; i < notation.notes.length; ++i)
		makeNoteSoftIndex(notation.notes, i, {softIndexFactor});
};


const runNavigation = async function(criterion, sample, onStep) {
	const navigator = new Navigator(criterion, sample);
	navigator.resetCursor(-1);

	for (let i = 0; i < sample.notes.length; ++i) {
		navigator.step(i);

		const next = await (onStep && onStep(i, navigator));
		if (next === Symbol.for("end")) {
			console.log("Navigation interrupted.");

			return;
		}
	}

	//console.log("Navigation accomplished.");

	return navigator;
};



module.exports = {
	normalizeInterval,
	makeNoteSoftIndex,
	makeMatchNodes,
	genNotationContext,
	runNavigation,
	Navigator,
	Node,
};