Skip to content

Commit

Permalink
UMP text functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jazz-soft committed Sep 17, 2023
1 parent 1b93cb5 commit 45332b8
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 13 deletions.
112 changes: 99 additions & 13 deletions javascript/JZZ.js
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,7 @@
function _bad(x) { throw TypeError('Invalid value: ' + x); }
function _oor(x) { throw RangeError('Out of range: ' + x); }
function _ch(c) { _validateChannel(c); return parseInt(c); }
function _4b(n) { if (n != parseInt(n) || n < 0 || n > 0xf) throw RangeError('Expected a 4-bit value: ' + n); return parseInt(n); }
function _7b(n, m) { if (n != parseInt(n) || n < 0 || n > 0x7f) _throw(typeof m == 'undefined' ? n : m); return parseInt(n); }
function _8b(n) { if (n != parseInt(n) || n < 0 || n > 0xff) _throw(n); return parseInt(n); }
function _14b(n) { if (n != parseInt(n) || n < 0 || n > 0x3fff) _throw(n); return parseInt(n); }
Expand Down Expand Up @@ -2964,7 +2965,7 @@
var m = this[0] >> 4;
if (m == 1 || m == 2 || m == 3 || m == 4 || m == 5 || m == 13) return this[0] & 15;
};

var _zeros = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var _helperNN = {
noop: function() { return [0, 0, 0, 0]; },
umpClock: function(n) { n = _16b(n); return [0, 0x10, n >> 8, n & 0xff]; },
Expand All @@ -2975,7 +2976,7 @@
umpEndClip: function() { return [0xf0, 0x21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; }
};
var _helperGN = {
umpTempo: function(g, n) { return [0xd0 + g, 0x10, 0, 0, n >> 24, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff, 0, 0, 0, 0, 0, 0, 0, 0]; },
umpTempo: function(g, n) { return [0xd0 + _4b(g), 0x10, 0, 0, n >> 24, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff, 0, 0, 0, 0, 0, 0, 0, 0]; },
umpBPM: function(g, n) { return _helperGN.umpTempo(g, Math.round(6000000000 / n)); },
umpTimeSignature: function(g, a, b) {
var nn, cc, dd;
Expand All @@ -2992,7 +2993,7 @@
dd = 0;
for (cc >>= 1; cc; cc >>= 1) dd++;
cc = Math.round(nn * 32 / (1 << dd));
if (cc < 0x100) return [0xd0 + g, 0x10, 0, 1, nn, dd, cc, 0, 0, 0, 0, 0, 0, 0, 0, 0];
if (cc < 0x100) return [0xd0 + _4b(g), 0x10, 0, 1, nn, dd, cc, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
throw RangeError('Wrong time signature ' + a + (typeof b == 'undefined' ? '' : '/' + b));
}
Expand All @@ -3002,14 +3003,63 @@
if (typeof v == 'undefined') v = 0xffff;
t = t || 0; a = a || 0;
v = _16b(v); a = _16b(a);
return [0x40 + g, 0x90 + _ch(c), _7bn(n), _8b(t), v >> 8, v & 255, a >> 8, a & 255];
return [0x40 + _4b(g), 0x90 + _ch(c), _7bn(n), _8b(t), v >> 8, v & 255, a >> 8, a & 255];
},
umpNoteOff: function(g, c, n, v, t, a) {
v = v || 0; t = t || 0; a = a || 0;
v = _16b(v); a = _16b(a);
return [0x40 + g, 0x80 + _ch(c), _7bn(n), _8b(t), v >> 8, v & 255, a >> 8, a & 255];
return [0x40 + _4b(g), 0x80 + _ch(c), _7bn(n), _8b(t), v >> 8, v & 255, a >> 8, a & 255];
}
};
var _helperGCG = {
umpCustomText: function(g, c, d, b, s, t) {
var i;
var a = [];
t = JZZ.lib.toUTF8('' + t);
for (i = 0; i < t.length; i++) a.push(t.charCodeAt(i));
a = _slice(a, 12);
for (i = 0; i < a.length; i++) a[i] = [0xd0 + _4b(g), _umpseqstat(a.length, i) * 64 + (d ? 16 : 0) + _ch(c), b, s].concat(a[i], _zeros).slice(0, 16);
return a;
},
umpCMetadata: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 0, t); },
umpCProjectName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 1, t); },
umpCCompositionName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 2, t); },
umpCClipName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 3, t); },
umpCCopyright: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 4, t); },
umpCComposerName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 5, t); },
umpCLyricistName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 6, t); },
umpCArrangerName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 7, t); },
umpCPublisherName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 8, t); },
umpCPerformerName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 9, t); },
umpCAccPerformerName: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 10, t); },
umpCRecordingDate: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 11, t); },
umpCRecordingLocation: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 1, 12, t); },
umpCText: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 2, 0, t); },
umpCLyrics: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 2, 1, t); },
umpCLyricsLanguage: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 2, 2, t); },
umpCRuby: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 2, 3, t); },
umpCRubyLanguage: function(g, c, t) { return _helperGCG.umpCustomText(g, c, 0, 2, 4, t); }
};
var _helperGNG = {
umpMetadata: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 0, t); },
umpProjectName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 1, t); },
umpCompositionName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 2, t); },
umpClipName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 3, t); },
umpCopyright: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 4, t); },
umpComposerName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 5, t); },
umpLyricistName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 6, t); },
umpArrangerName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 7, t); },
umpPublisherName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 8, t); },
umpPerformerName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 9, t); },
umpAccPerformerName: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 10, t); },
umpRecordingDate: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 11, t); },
umpRecordingLocation: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 1, 12, t); },
umpText: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 2, 0, t); },
umpLyrics: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 2, 1, t); },
umpLyricsLanguage: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 2, 2, t); },
umpRuby: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 2, 3, t); },
umpRubyLanguage: function(g, t) { return _helperGCG.umpCustomText(g, 0, 1, 2, 4, t); }
};

var _helpersUmp = {};
function _copyHelperNN(name, func) {
Expand All @@ -3030,6 +3080,40 @@
return this.send(func.apply(this, args));
};
}
function _copyHelperGCG(name, func) {
UMP[name] = function() {
var args = Array.prototype.slice.call(arguments);
if (typeof this._gr != 'undefined') args = [this._gr].concat(args);
if (typeof this._ch != 'undefined') args = [args[0]].concat([this._ch]).concat(args.slice(1));
var a = func.apply(this, args);
for (var i = 0; i < a.length; i++) a[i] = new UMP(a[i]);
return a;
};
_helpersUmp[name] = function() {
var args = Array.prototype.slice.call(arguments);
if (typeof this._gr != 'undefined') args = [this._gr].concat(args);
if (typeof this._ch != 'undefined') args = [args[0]].concat([this._ch]).concat(args.slice(1));
var a = func.apply(this, args);
for (var i = 0; i < a.length; i++) this.send(a[i]);
return this;
};
}
function _copyHelperGNG(name, func) {
UMP[name] = function() {
var args = Array.prototype.slice.call(arguments);
if (typeof this._gr != 'undefined') args = [this._gr].concat(args);
var a = func.apply(this, args);
for (var i = 0; i < a.length; i++) a[i] = new UMP(a[i]);
return a;
};
_helpersUmp[name] = function() {
var args = Array.prototype.slice.call(arguments);
if (typeof this._gr != 'undefined') args = [this._gr].concat(args);
var a = func.apply(this, args);
for (var i = 0; i < a.length; i++) this.send(a[i]);
return this;
};
}
function _copyHelperGN(name, func) {
UMP[name] = function() {
var args = Array.prototype.slice.call(arguments);
Expand All @@ -3046,11 +3130,11 @@
function _slice(m, n) {
var a = [];
for (var x = m; x.length; x = x.slice(n)) a.push(x.slice(0, n));
return a;
return a.length ? a : [[]];
}
function _sliceSX(gr, m) {
var a = _slice(m.slice(1, m.length - 1), 6);
for (var i = 0; i < a.length; i++) a[i] = new UMP([0x30 + gr, _umpseqstat(a.length, i) * 16 + a[i].length].concat(a[i], [0, 0, 0, 0, 0, 0]).slice(0, 8));
for (var i = 0; i < a.length; i++) a[i] = new UMP([0x30 + gr, _umpseqstat(a.length, i) * 16 + a[i].length].concat(a[i], _zeros).slice(0, 8));
return a;
}
function _copyHelperSX(name, func) {
Expand Down Expand Up @@ -3096,6 +3180,8 @@
}
_for(_helperNN, function(n) { _copyHelperNN(n, _helperNN[n]); });
_for(_helperGC, function(n) { _copyHelperGC(n, _helperGC[n]); });
_for(_helperGCG, function(n) { _copyHelperGCG(n, _helperGCG[n]); });
_for(_helperGNG, function(n) { _copyHelperGNG(n, _helperGNG[n]); });
_for(_helperMPE, function(n) { _copyHelperM1(n, _helperMPE[n]); });
_for(_helperCH, function(n) { _copyHelperM1(n, _helperCH[n]); });
_for(_helperNC, function(n) { _copyHelperM1N(n, _helperNC[n]); });
Expand Down Expand Up @@ -3134,14 +3220,14 @@
var c = (this[0] || 0) >> 4;
var d = (this[1] || 0) >> 4;
if (c == 4) return d == 9;
else if (c == 2) return d == 9 && !!this[3];
else if (c == 2) return d == 9 && !!this[3];
return false;
};
UMP.prototype.isNoteOff = function() {
var c = (this[0] || 0) >> 4;
var d = (this[1] || 0) >> 4;
if (c == 4) return d == 8;
else if (c == 2) return d == 8 || (d == 9 && !this[3]);
else if (c == 2) return d == 8 || (d == 9 && !this[3]);
return false;
};
UMP.prototype.toString = MIDI.prototype.toString;
Expand Down Expand Up @@ -3200,7 +3286,7 @@
else if (n == 1) {
n = this[3];
s = {
0: 'Metadata Text',
0: 'Metadata',
1: 'Project Name',
2: 'Composition Name',
3: 'Clip Name',
Expand All @@ -3213,17 +3299,17 @@
10: 'Accompanying Performer Name',
11: 'Recording Date',
12: 'Recording Location'
}[n];
}[n] || 'Unknown Text';
}
else if (n == 2) {
n = this[3];
s = {
0: 'Performance Text',
0: 'Text',
1: 'Lyrics',
2: 'Lyrics Language',
3: 'Ruby',
4: 'Ruby Language',
}[n];
}[n] || 'Unknown Text';
}
}
if (t == 15) {
Expand Down
88 changes: 88 additions & 0 deletions test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,89 @@ describe('UMP messages', function() {
var s = 'd0100005 00000000 00000000 00000000 -- Key Signature';
assert.equal(JZZ.UMP([0xd0, 0x10, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).toString(), s);
});
it('umpCustomText', function() {
var m = JZZ.UMP.umpCustomText(5, 5, 1, 1, 15, 'This is a long text that spans over 4 messages!');
console.log(m);
assert.equal(m[0].toString(), 'd555010f 54686973 20697320 61206c6f -- Unknown Text');
assert.equal(m[1].toString(), 'd595010f 6e672074 65787420 74686174 -- Unknown Text');
assert.equal(m[2].toString(), 'd595010f 20737061 6e73206f 76657220 -- Unknown Text');
assert.equal(m[3].toString(), 'd5d5010f 34206d65 73736167 65732100 -- Unknown Text');
assert.equal(JZZ.UMP.umpCustomText(5, 5, 0, 2, 15, '')[0].toString(), 'd505020f 00000000 00000000 00000000 -- Unknown Text');
});
it('umpMetadata', function() {
var s = 'd2100100 00000000 00000000 00000000 -- Metadata';
assert.equal(JZZ.UMP.umpMetadata(2, '')[0].toString(), s);
assert.equal(JZZ.UMP.gr(2).umpMetadata('')[0].toString(), s);
s = 'd2050100 54455854 00000000 00000000 -- Metadata';
assert.equal(JZZ.UMP.umpCMetadata(2, 5, 'TEXT')[0].toString(), s);
assert.equal(JZZ.UMP.gr(2).umpCMetadata(5, 'TEXT')[0].toString(), s);
assert.equal(JZZ.UMP.gr(2).ch(5).umpCMetadata('TEXT')[0].toString(), s);
assert.equal(JZZ.UMP.ch(5).umpCMetadata(2, 'TEXT')[0].toString(), s);
});
it('umpProjectName', function() {
assert.equal(JZZ.UMP.umpProjectName(0, 'JZZ')[0].toString(), 'd0100101 4a5a5a00 00000000 00000000 -- Project Name');
assert.equal(JZZ.UMP.umpCProjectName(0, 0, 'JZZ')[0].toString(), 'd0000101 4a5a5a00 00000000 00000000 -- Project Name');
});
it('umpCompositionName', function() {
assert.equal(JZZ.UMP.umpCompositionName(0, '...')[0].toString(), 'd0100102 2e2e2e00 00000000 00000000 -- Composition Name');
assert.equal(JZZ.UMP.umpCCompositionName(0, 0, '...')[0].toString(), 'd0000102 2e2e2e00 00000000 00000000 -- Composition Name');
});
it('umpClipName', function() {
assert.equal(JZZ.UMP.umpClipName(0, '...')[0].toString(), 'd0100103 2e2e2e00 00000000 00000000 -- Clip Name');
assert.equal(JZZ.UMP.umpCClipName(0, 0, '...')[0].toString(), 'd0000103 2e2e2e00 00000000 00000000 -- Clip Name');
});
it('umpCopyright', function() {
assert.equal(JZZ.UMP.umpCopyright(0, '...')[0].toString(), 'd0100104 2e2e2e00 00000000 00000000 -- Copyright');
assert.equal(JZZ.UMP.umpCCopyright(0, 0, '...')[0].toString(), 'd0000104 2e2e2e00 00000000 00000000 -- Copyright');
});
it('umpComposerName', function() {
assert.equal(JZZ.UMP.umpComposerName(0, '...')[0].toString(), 'd0100105 2e2e2e00 00000000 00000000 -- Composer Name');
assert.equal(JZZ.UMP.umpCComposerName(0, 0, '...')[0].toString(), 'd0000105 2e2e2e00 00000000 00000000 -- Composer Name');
});
it('umpLyricistName', function() {
assert.equal(JZZ.UMP.umpLyricistName(0, '...')[0].toString(), 'd0100106 2e2e2e00 00000000 00000000 -- Lyricist Name');
assert.equal(JZZ.UMP.umpCLyricistName(0, 0, '...')[0].toString(), 'd0000106 2e2e2e00 00000000 00000000 -- Lyricist Name');
});
it('umpArrangerName', function() {
assert.equal(JZZ.UMP.umpArrangerName(0, '...')[0].toString(), 'd0100107 2e2e2e00 00000000 00000000 -- Arranger Name');
assert.equal(JZZ.UMP.umpCArrangerName(0, 0, '...')[0].toString(), 'd0000107 2e2e2e00 00000000 00000000 -- Arranger Name');
});
it('umpPublisherName', function() {
assert.equal(JZZ.UMP.umpPublisherName(0, '...')[0].toString(), 'd0100108 2e2e2e00 00000000 00000000 -- Publisher Name');
assert.equal(JZZ.UMP.umpCPublisherName(0, 0, '...')[0].toString(), 'd0000108 2e2e2e00 00000000 00000000 -- Publisher Name');
});
it('umpPerformerName', function() {
assert.equal(JZZ.UMP.umpPerformerName(0, '...')[0].toString(), 'd0100109 2e2e2e00 00000000 00000000 -- Primary Performer Name');
assert.equal(JZZ.UMP.umpCPerformerName(0, 0, '...')[0].toString(), 'd0000109 2e2e2e00 00000000 00000000 -- Primary Performer Name');
});
it('umpAccPerformerName', function() {
assert.equal(JZZ.UMP.umpAccPerformerName(0, '...')[0].toString(), 'd010010a 2e2e2e00 00000000 00000000 -- Accompanying Performer Name');
assert.equal(JZZ.UMP.umpCAccPerformerName(0, 0, '...')[0].toString(), 'd000010a 2e2e2e00 00000000 00000000 -- Accompanying Performer Name');
});
it('umpRecordingDate', function() {
assert.equal(JZZ.UMP.umpRecordingDate(0, '...')[0].toString(), 'd010010b 2e2e2e00 00000000 00000000 -- Recording Date');
assert.equal(JZZ.UMP.umpCRecordingDate(0, 0, '...')[0].toString(), 'd000010b 2e2e2e00 00000000 00000000 -- Recording Date');
});
it('umpRecordingLocation', function() {
assert.equal(JZZ.UMP.umpRecordingLocation(0, '...')[0].toString(), 'd010010c 2e2e2e00 00000000 00000000 -- Recording Location');
assert.equal(JZZ.UMP.umpCRecordingLocation(0, 0, '...')[0].toString(), 'd000010c 2e2e2e00 00000000 00000000 -- Recording Location');
});
it('umpText', function() {
assert.equal(JZZ.UMP.umpText(0, '音樂')[0].toString(), 'd0100200 e99fb3e6 a8820000 00000000 -- Text');
assert.equal(JZZ.UMP.umpCText(0, 0, '音樂')[0].toString(), 'd0000200 e99fb3e6 a8820000 00000000 -- Text');
});
it('umpLyrics', function() {
assert.equal(JZZ.UMP.umpLyrics(0, '...')[0].toString(), 'd0100201 2e2e2e00 00000000 00000000 -- Lyrics');
assert.equal(JZZ.UMP.umpCLyrics(0, 0, '...')[0].toString(), 'd0000201 2e2e2e00 00000000 00000000 -- Lyrics');
assert.equal(JZZ.UMP.umpLyricsLanguage(0, '...')[0].toString(), 'd0100202 2e2e2e00 00000000 00000000 -- Lyrics Language');
assert.equal(JZZ.UMP.umpCLyricsLanguage(0, 0, '...')[0].toString(), 'd0000202 2e2e2e00 00000000 00000000 -- Lyrics Language');
});
it('umpRuby', function() {
assert.equal(JZZ.UMP.umpRuby(0, '...')[0].toString(), 'd0100203 2e2e2e00 00000000 00000000 -- Ruby');
assert.equal(JZZ.UMP.umpCRuby(0, 0, '...')[0].toString(), 'd0000203 2e2e2e00 00000000 00000000 -- Ruby');
assert.equal(JZZ.UMP.umpRubyLanguage(0, '...')[0].toString(), 'd0100204 2e2e2e00 00000000 00000000 -- Ruby Language');
assert.equal(JZZ.UMP.umpCRubyLanguage(0, 0, '...')[0].toString(), 'd0000204 2e2e2e00 00000000 00000000 -- Ruby Language');
});
it('umpNoteOn', function() {
var s = '41923d00 ffff0000 -- Note On';
var msg = JZZ.UMP.umpNoteOn(1, 2, 'C#5');
Expand Down Expand Up @@ -1365,6 +1448,11 @@ describe('JZZ.Widget2', function() {
port.connect(function(msg) { sample.compare(msg); });
port.umpBPM(1, 120).gr(2).umpBPM(120);
});
it('umpText', function() {
var port = JZZ.Widget2();
port.umpText(1, '').gr(2).umpText('');
port.umpCText(1, 2, '').gr(2).umpText(2, '').ch(3).umpText('');
});
});

describe('JZZ.Context', function() {
Expand Down

0 comments on commit 45332b8

Please sign in to comment.