Skip to content

Commit 46d9078

Browse files
committed
Implement sequence renderer
1 parent 9491355 commit 46d9078

15 files changed

+349
-47
lines changed

js/players/mn-sequence-renderer.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
var renderSequenceWithTicks = function(harmonicStructure, baseSequence, ticksPerBeat)
2+
{
3+
var result = new Object;
4+
result.length = createSequencingPosition(harmonicStructure.length, ticksPerBeat);
5+
result.sequence = [];
6+
7+
var harmonyIndex = 0;
8+
// Do all of the harmonic steps
9+
while (harmonyIndex < harmonicStructure.structure.length)
10+
{
11+
var harmonyStep = harmonicStructure.structure[harmonyIndex];
12+
13+
var stepEndPosition =
14+
harmonyIndex < harmonicStructure.structure.length - 1
15+
? harmonicStructure.structure[harmonyIndex + 1].tickCount
16+
: harmonicStructure.length;
17+
18+
// At this point, we'll a new copy the base sequence and loop it until the next or final step
19+
20+
var sequenceIndex = 0;
21+
var render = true;
22+
23+
var notes = harmonyStep.element.notes;
24+
var baseSequenceOffset = 0;
25+
26+
while (render)
27+
{
28+
var sequenceStep = baseSequence.sequence[sequenceIndex];
29+
var currentPosition = harmonyStep.tickCount + sequenceStep.tickCount + baseSequenceOffset;
30+
31+
if (currentPosition < stepEndPosition)
32+
{
33+
var step =
34+
{
35+
position: createSequencingPosition(currentPosition, ticksPerBeat),
36+
notes: []
37+
}
38+
39+
sequenceStep.degrees.forEach(function(degree){
40+
if (degree <= notes.length)
41+
{
42+
step.notes.push(notes[degree-1])
43+
}
44+
})
45+
46+
result.sequence.push(step);
47+
48+
// next one and wrap sequence if needed
49+
sequenceIndex++;
50+
if (sequenceIndex >= baseSequence.sequence.length)
51+
{
52+
sequenceIndex = 0;
53+
baseSequenceOffset += baseSequence.length;
54+
// render = false; // for a single iteration
55+
}
56+
}
57+
else {
58+
render = false;
59+
}
60+
}
61+
62+
harmonyIndex++;
63+
}
64+
return result;
65+
}
66+
67+
// renders a serie of note events to be played from
68+
// a base array sequence in the form:
69+
// { position: "1.1.1", degrees: [1,3] }
70+
// and a harmonic structure
71+
// structure: [{ position: "1.1.1", midiNoteList: [35,67] }]
72+
// length: "4.1.1" // In bars
73+
74+
renderSequence = function(harmonicStructure, baseSequence, signature, ticksPerBeat)
75+
{
76+
// Convert base sequence to use ticks for position
77+
var tickBaseSequence = new Object;
78+
tickBaseSequence.length = stringPositionToTicks(baseSequence.length, signature, ticksPerBeat);
79+
tickBaseSequence.sequence = [];
80+
81+
baseSequence.sequence.forEach(function(element)
82+
{
83+
tickBaseSequence.sequence.push(
84+
{
85+
tickCount: stringPositionToTicks(element.position, signature, ticksPerBeat),
86+
degrees: element.degrees
87+
});
88+
})
89+
90+
// Convert harmonicStructure to use ticks for position
91+
92+
var tickBaseStructure = new Object;
93+
tickBaseStructure.length = stringPositionToTicks(harmonicStructure.length, signature, ticksPerBeat);
94+
tickBaseStructure.structure = [] ;
95+
96+
harmonicStructure.structure.forEach(function(item)
97+
{
98+
tickBaseStructure.structure.push(
99+
{
100+
tickCount: stringPositionToTicks(item.position, signature, ticksPerBeat),
101+
element: item.element
102+
}
103+
)
104+
});
105+
106+
return renderSequenceWithTicks(tickBaseStructure, tickBaseSequence, ticksPerBeat);
107+
}

js/players/mn-sequencer-renderer.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

js/players/players.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require("./mn-sequence-renderer.js")

js/progression/mn-chord-progression.js

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
// Build a chord object to manipulate the content
22

3-
ProgressionElement = function (notes, bass)
3+
ProgressionElement = function (notes)
44
{
5-
this.notes_ = notes;
6-
this.bass_ = bass;
7-
}
8-
9-
// return the notes
10-
11-
ProgressionElement.prototype.notes = function()
12-
{
13-
return this.notes_;
5+
this.notes = notes;
146
}
157

168
// Chord progression helper object
@@ -31,7 +23,6 @@ ChordProgression.prototype.makeChord = function(degree, alteration)
3123
{
3224
var n = this.scaleNotes_;
3325
var root = n[degree-1];
34-
var bass = root - 24;
3526

3627
// If there's an alteration, force it
3728
if (alteration && alteration.length_ != 0)
@@ -43,10 +34,10 @@ ChordProgression.prototype.makeChord = function(degree, alteration)
4334
current += interval;
4435
notes.push(current);
4536
})
46-
return new ProgressionElement(notes, bass )
37+
return new ProgressionElement(notes)
4738
}
4839
// return the default chord for the scale
49-
return new ProgressionElement([n[degree-1], n[degree+1], n[degree+3]], bass);
40+
return new ProgressionElement([n[degree-1], n[degree+1], n[degree+3]]);
5041
}
5142

5243
// creates a chord progression from a list of scale degree

js/progression/mn-voicing.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ var rectify_progression_sequential = function(sequence)
4242
{
4343
for (var i = 0; i < sequence.length-1; i++)
4444
{
45-
sequence[i+1].notes_ = rectify_closest(sequence[i].notes_,sequence[i+1].notes_);
45+
sequence[i+1].notes = rectify_closest(sequence[i].notes,sequence[i+1].notes);
4646
}
4747
}
4848

4949
var rectify_progression_to_first = function(sequence)
5050
{
5151
for (var i = 0; i < sequence.length-1; i++)
5252
{
53-
sequence[i+1].notes_ = rectify_closest(sequence[0].notes_,sequence[i+1].notes_);
53+
sequence[i+1].notes = rectify_closest(sequence[0].notes,sequence[i+1].notes);
5454
}
5555
}
5656

@@ -59,15 +59,15 @@ var rectify_progression_inwards = function(sequence)
5959
var leftIndex = 1;
6060
var rightIndex = sequence.length -1;
6161

62-
sequence[rightIndex].notes_ = rectify_closest(sequence[0].notes_, sequence[rightIndex].notes_);
62+
sequence[rightIndex].notes = rectify_closest(sequence[0].notes, sequence[rightIndex].notes);
6363
rightIndex--;
6464

6565
while (leftIndex < rightIndex)
6666
{
67-
sequence[leftIndex].notes_ = rectify_closest(sequence[leftIndex -1].notes_, sequence[leftIndex].notes_);
67+
sequence[leftIndex].notes = rectify_closest(sequence[leftIndex -1].notes, sequence[leftIndex].notes);
6868
if (rightIndex > leftIndex)
6969
{
70-
sequence[rightIndex].notes_ = rectify_closest(sequence[rightIndex+1].notes_, sequence[rightIndex].notes_);
70+
sequence[rightIndex].notes = rectify_closest(sequence[rightIndex+1].notes, sequence[rightIndex].notes);
7171
}
7272
rightIndex--;
7373
leftIndex++;

js/sequencing/mn-beat-time-line.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,56 @@ createSequencingPosition = function(tickCount, ticksPerBeat)
3030
return position;
3131
}
3232

33+
ticksFromPosition = function(position)
34+
{
35+
var tickCount = position.beats_;
36+
tickCount = 4 * tickCount + position.sixteenth_;
37+
tickCount = tickCount * (position.ticksPerBeat_ / 4) + position.ticks_;
38+
return tickCount;
39+
}
40+
41+
comparePositions = function(pos1, pos2)
42+
{
43+
var ticks1 = ticksFromPosition(pos1);
44+
var ticks2 = ticksFromPosition(pos2);
45+
if (ticks1 == ticks2) return 0;
46+
return ticks1 < ticks2 ? -1 : 1;
47+
}
48+
49+
addPositions = function(pos1, pos2)
50+
{
51+
var ticks1 = ticksFromPosition(pos1);
52+
var ticks2 = ticksFromPosition(pos2);
53+
return createSequencingPosition(ticks1 + ticks2, pos1.ticksPerBeat_);
54+
}
55+
56+
moduloPosition = function(pos1, pos2)
57+
{
58+
var ticks1 = ticksFromPosition(pos1);
59+
var ticks2 = ticksFromPosition(pos2);
60+
return createSequencingPosition(ticks1 % ticks2, pos1.ticksPerBeat_);
61+
}
62+
63+
subPositions = function(pos1, pos2)
64+
{
65+
var ticks1 = ticksFromPosition(pos1);
66+
var ticks2 = ticksFromPosition(pos2);
67+
return createSequencingPosition(ticks1 - ticks2, pos1.ticksPerBeat_);
68+
}
69+
3370
sixteenthCount = function(position)
3471
{
3572
return position.sixteenth_ + 4 * position.beats_;
3673
}
3774

75+
76+
stringPositionToTicks = function(position, signature, ticksPerBeat)
77+
{
78+
var elementPosition = convertToPosition(position, signature, ticksPerBeat);
79+
var elementPositionInTicks = ticksFromPosition(elementPosition);
80+
return elementPositionInTicks;
81+
}
82+
3883
// converts a beat string ("1.1.3.2") to a sequencing position
3984

4085
convertToPosition = function(beatString, signature, ticksPerBeat)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"pegjs":"x.x",
1111
"hapi":"x.x",
1212
"inert":"x.x"
13+
"lodash":"x.x"
1314
}
1415
}

terminal/application.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Application.prototype.updateSequence = function()
7777
// create chord progression
7878
var chordSequence = makeChordProgression(this.rootNote_, this.scale_, this.progression_);
7979
// apply desired inversion to the first chord
80-
chordSequence[0].notes_ = invertChord(chordSequence[0].notes_,this.inversion_);
80+
chordSequence[0].notes = invertChord(chordSequence[0].notes,this.inversion_);
8181
// apply voicing
8282
rectify_progression(chordSequence, this.rectificationMethod_);
8383
console.log("should send chord seaquence")
@@ -91,7 +91,7 @@ Application.prototype.currentSequenceString = function()
9191
var chordSequence = this.chordSequencer_.getContent();
9292
chordSequence.forEach(function (chord)
9393
{
94-
chordnameList += chordname(chord.notes_) + ",";
94+
chordnameList += chordname(chord.notes) + ",";
9595
})
9696
return chordnameList;*/
9797
}
@@ -112,7 +112,10 @@ Application.prototype.exit = function(arguments)
112112
Application.prototype.rebuild = function()
113113
{
114114
var chordSequence = this.harmony_.rebuild();
115-
this.engine_.setChordSequence(chordSequence);
115+
if (chordSequence)
116+
{
117+
this.engine_.setChordSequence(chordSequence);
118+
}
116119
}
117120

118121
Application.prototype.setScale = function(arguments)
@@ -127,7 +130,7 @@ Application.prototype.setScale = function(arguments)
127130
scaleChordsNameList = "";
128131
scaleChords.forEach(function (chord)
129132
{
130-
scaleChordsNameList += chordname(chord.notes_) + ",";
133+
scaleChordsNameList += chordname(chord.notes) + ",";
131134
})
132135

133136
return "Scale chords: " + scaleChordsNameList;

terminal/harmony-engine.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ HarmonyEngine.prototype.rebuild = function()
3636
// create chord progression
3737
var chordSequence = makeChordProgression(this.rootNote_, this.scale_, this.progression_);
3838
// apply desired inversion to the first chord
39-
chordSequence[0].notes_ = invertChord(chordSequence[0].notes_,this.inversion_);
39+
chordSequence[0].notes = invertChord(chordSequence[0].notes,this.inversion_);
4040
// apply voicing
4141
rectify_progression(chordSequence, this.rectificationMethod_);
4242
return chordSequence;

terminal/main.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

3-
//if ( global.v8debug) {
4-
// global.v8debug.Debug.setBreakOnException(); // enable it, global.v8debug is only defined when the --debug or --debug-brk flag is set
5-
//}
3+
if ( global.v8debug) {
4+
global.v8debug.Debug.setBreakOnException(); // enable it, global.v8debug is only defined when the --debug or --debug-brk flag is set
5+
}
66

77
var app = require('./application.js');
88
app.init({

0 commit comments

Comments
 (0)