-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsequence.js
122 lines (98 loc) · 2.45 KB
/
sequence.js
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict';
var Message = require('./message');
var Track = require('./track');
var vlv = require('./vlv');
var constants = {
START_OF_FILE: 0x4d546864 // MThd
};
var fileTypes = {
TYPE_0: 0x0, // single track
TYPE_1: 0x1 // multi track
};
function Sequence(header) {
this.tracks = [];
this.header = header;
}
Sequence.prototype.addTrack = function (track) {
if (this.tracks.length >= this.header.noTracks) {
console.warn('Tracks exceed specified number of tracks in header field.');
}
this.tracks.push(track);
};
Sequence.prototype.getTracks = function () {
return this.tracks;
};
Sequence.prototype.getFileType = function () {
return this.header.fileType;
};
Sequence.prototype.getTicks = function () {
return this.header.ticks;
};
/**
*
* @param buffer
* @returns {Sequence}
*/
Sequence.fromBuffer = function (buffer) {
var offset = 0;
if (buffer.readUInt32BE(offset, false) !== constants.START_OF_FILE) {
throw new Error("Expected start of file marker 'MThd'.");
}
offset += 4;
if (buffer.readUInt32BE(offset) !== 0x6) {
throw new Error('Invalid header size (expected 6 bytes).');
}
offset += 4;
var fileType = buffer.readUInt16BE(offset);
offset += 2;
var noTracks = buffer.readUInt16BE(offset);
offset += 2;
if (fileType === fileTypes.TYPE_0 && noTracks !== 1) {
throw new Error('Number of tracks mismatch file type (expected 1 track).');
}
var ticks = buffer.readUInt16BE(offset);
offset += 2;
var sequence = new Sequence({
fileType: fileType,
ticks: ticks,
noTracks: noTracks
});
for (var i = 0; i < noTracks; i++) {
var track = Track.fromBuffer(buffer.slice(offset));
sequence.addTrack(track);
offset += 8;
var runningStatus = null;
while (buffer.length > 0) {
var delta = vlv.fromBuffer(buffer.slice(offset));
// TODO fix this stuff
if (delta > 0x3FFF) {
offset += 3;
} else if (delta > 0x7F) {
offset += 2;
} else {
offset += 1;
}
var message = Message.fromBuffer(buffer.slice(offset), runningStatus);
if (!message) {
throw new Error("Unexpected end of buffer.");
}
track.addEvent(delta, message);
offset += message.length;
runningStatus = message.statusByte;
if (message.isEndOfTrack()) {
break;
}
}
}
return sequence;
};
Sequence.fromFile = function (filename, cb) {
require('fs').readFile(filename, function (error, data) {
if (error) {
cb(error, null);
return;
}
cb(null, Sequence.fromBuffer(data));
});
};
module.exports = Sequence;