abcjs-rails 2.3 → 3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/abcjs/api/abc_animation.js +166 -4
  3. data/app/assets/javascripts/abcjs/api/abc_tunebook.js +170 -15
  4. data/app/assets/javascripts/abcjs/data/abc_tune.js +69 -47
  5. data/app/assets/javascripts/abcjs/edit/abc_editor.js +78 -37
  6. data/app/assets/javascripts/abcjs/midi/abc_midi_controls.js +513 -0
  7. data/app/assets/javascripts/abcjs/midi/abc_midi_create.js +29 -7
  8. data/app/assets/javascripts/abcjs/midi/abc_midi_flattener.js +21 -18
  9. data/app/assets/javascripts/abcjs/midi/abc_midi_js_preparer.js +233 -0
  10. data/app/assets/javascripts/abcjs/midi/abc_midi_renderer.js +3 -229
  11. data/app/assets/javascripts/abcjs/midi/abc_midi_sequencer.js +11 -3
  12. data/app/assets/javascripts/abcjs/parse/abc_common.js +24 -0
  13. data/app/assets/javascripts/abcjs/parse/abc_parse.js +58 -16
  14. data/app/assets/javascripts/abcjs/parse/abc_parse_header.js +4 -1
  15. data/app/assets/javascripts/abcjs/parse/abc_parse_key_voice.js +5 -0
  16. data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +9 -2
  17. data/app/assets/javascripts/abcjs/write/abc_abstract_engraver.js +71 -19
  18. data/app/assets/javascripts/abcjs/write/abc_beam_element.js +11 -3
  19. data/app/assets/javascripts/abcjs/write/abc_brace_element.js +51 -0
  20. data/app/assets/javascripts/abcjs/write/abc_create_clef.js +3 -3
  21. data/app/assets/javascripts/abcjs/write/abc_create_key_signature.js +3 -3
  22. data/app/assets/javascripts/abcjs/write/abc_create_time_signature.js +3 -3
  23. data/app/assets/javascripts/abcjs/write/abc_crescendo_element.js +4 -1
  24. data/app/assets/javascripts/abcjs/write/abc_decoration.js +1 -1
  25. data/app/assets/javascripts/abcjs/write/abc_engraver_controller.js +10 -9
  26. data/app/assets/javascripts/abcjs/write/abc_glyphs.js +1 -1
  27. data/app/assets/javascripts/abcjs/write/abc_relative_element.js +1 -1
  28. data/app/assets/javascripts/abcjs/write/abc_renderer.js +85 -13
  29. data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +16 -0
  30. data/app/assets/javascripts/abcjs/write/abc_tempo_element.js +31 -11
  31. data/app/assets/javascripts/abcjs/write/abc_tie_element.js +8 -1
  32. data/lib/abcjs-rails/version.rb +1 -1
  33. metadata +6 -3
@@ -1,5 +1,5 @@
1
1
  // abc_midi_create.js: Turn a linear series of events into a midi file.
2
- // Copyright (C) 2010,2015 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
2
+ // Copyright (C) 2010,2016 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
3
3
  //
4
4
  // This program is free software: you can redistribute it and/or modify
5
5
  // it under the terms of the GNU General Public License as published by
@@ -26,44 +26,66 @@ if (!window.ABCJS.midi)
26
26
  var baseDuration = 480*4; // nice and divisible, equals 1 whole note
27
27
 
28
28
  window.ABCJS.midi.create = function(abcTune, options) {
29
+ if (options === undefined) options = {};
29
30
  var sequence = window.ABCJS.midi.sequence(abcTune, options);
30
31
  var commands = window.ABCJS.midi.flatten(sequence);
31
- var midi = window.ABCJS.midi.rendererFactory(false);
32
+ var midi = window.ABCJS.midi.rendererFactory();
33
+ var midiJs = new window.ABCJS.midi.Preparer();
32
34
 
33
- if (commands.instrument !== undefined)
34
- midi.setInstrument(commands.instrument);
35
- if (commands.channel !== undefined)
36
- midi.setChannel(commands.channel);
37
35
  var title = abcTune.metaText ? abcTune.metaText.title : undefined;
38
36
  if (title && title.length > 128)
39
37
  title = title.substring(0,124) + '...';
40
38
  midi.setGlobalInfo(commands.tempo, title);
39
+ midiJs.setGlobalInfo(commands.tempo, title);
41
40
 
41
+ if (commands.instrument !== undefined) {
42
+ midi.setInstrument(commands.instrument);
43
+ midiJs.setInstrument(commands.instrument);
44
+ }
45
+ if (commands.channel !== undefined) {
46
+ midi.setChannel(commands.channel);
47
+ midiJs.setChannel(commands.channel);
48
+ }
42
49
  for (var i = 0; i < commands.tracks.length; i++) {
43
50
  midi.startTrack();
51
+ midiJs.startTrack();
44
52
  for (var j = 0; j < commands.tracks[i].length; j++) {
45
53
  var event = commands.tracks[i][j];
46
54
  switch (event.cmd) {
47
55
  case 'instrument':
48
56
  midi.setInstrument(event.instrument);
57
+ midiJs.setInstrument(event.instrument);
49
58
  break;
50
59
  case 'start':
51
60
  midi.startNote(convertPitch(event.pitch), event.volume);
61
+ midiJs.startNote(convertPitch(event.pitch), event.volume);
52
62
  break;
53
63
  case 'stop':
54
64
  midi.endNote(convertPitch(event.pitch), 0); // TODO-PER: Refactor: the old midi used a duration here.
65
+ midiJs.endNote(convertPitch(event.pitch));
55
66
  break;
56
67
  case 'move':
57
68
  midi.addRest(event.duration * baseDuration);
69
+ midiJs.addRest(event.duration * baseDuration);
58
70
  break;
59
71
  default:
60
72
  console.log("MIDI create Unknown: " + event.cmd);
61
73
  }
62
74
  }
63
75
  midi.endTrack();
76
+ midiJs.endTrack();
64
77
  }
65
78
 
66
- return midi.getData();
79
+ var midiFile = midi.getData();
80
+ var midiInline = midiJs.getData();
81
+ if (options.generateInline === undefined) // default is to generate inline controls.
82
+ options.generateInline = true;
83
+ if (options.generateInline && options.generateDownload)
84
+ return { download: midiFile, inline: midiInline };
85
+ else if (options.generateInline)
86
+ return midiInline;
87
+ else
88
+ return midiFile;
67
89
  };
68
90
 
69
91
  function convertPitch(pitch) {
@@ -1,5 +1,5 @@
1
1
  // abc_midi_create.js: Turn a linear series of events into a series of MIDI commands.
2
- // Copyright (C) 2010,2015 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
2
+ // Copyright (C) 2010,2016 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
3
3
  //
4
4
  // This program is free software: you can redistribute it and/or modify
5
5
  // it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@ if (!window.ABCJS.midi)
34
34
  var multiplier;
35
35
  var tracks;
36
36
  var startingTempo;
37
- var currentTempo;
37
+ var tempoChangeFactor = 1;
38
38
  var instrument;
39
39
  var channel;
40
40
  var currentTrack;
@@ -58,7 +58,7 @@ if (!window.ABCJS.midi)
58
58
  multiplier = 1;
59
59
  tracks = [];
60
60
  startingTempo = undefined;
61
- currentTempo = undefined;
61
+ tempoChangeFactor = 1;
62
62
  instrument = undefined;
63
63
  channel = undefined;
64
64
  currentTrack = undefined;
@@ -93,7 +93,7 @@ if (!window.ABCJS.midi)
93
93
  if (!startingTempo)
94
94
  startingTempo = element.qpm;
95
95
  else
96
- currentTempo = element.qpm;
96
+ tempoChangeFactor = element.qpm ? startingTempo / element.qpm : 1;
97
97
  break;
98
98
  case "transpose":
99
99
  transpose = element.transpose;
@@ -190,7 +190,7 @@ if (!window.ABCJS.midi)
190
190
  // If we ever have a chord in this voice, then we add the chord track.
191
191
  // However, if there are chords on more than one voice, then just use the first voice.
192
192
  if (chordTrack.length === 0) {
193
- chordTrack.push({cmd: 'instrument', instrument: 2});
193
+ chordTrack.push({cmd: 'instrument', instrument: 0});
194
194
  // need to figure out how far in time the chord started: if there are pickup notes before the chords start, we need pauses.
195
195
  var distance = 0;
196
196
  for (var ct = 0; ct < currentTrack.length; ct++) {
@@ -198,7 +198,7 @@ if (!window.ABCJS.midi)
198
198
  distance += currentTrack[ct].duration;
199
199
  }
200
200
  if (distance > 0)
201
- chordTrack.push({cmd: 'move', duration: distance});
201
+ chordTrack.push({cmd: 'move', duration: distance*tempoChangeFactor });
202
202
  }
203
203
 
204
204
  lastChord = c;
@@ -253,16 +253,16 @@ if (!window.ABCJS.midi)
253
253
  else if (note.endTie)
254
254
  pitchesTied[''+actualPitch] = false;
255
255
  }
256
- currentTrack.push({ cmd: 'move', duration: duration-normalBreakBetweenNotes });
256
+ currentTrack.push({ cmd: 'move', duration: (duration-normalBreakBetweenNotes)*tempoChangeFactor });
257
257
  lastNoteDurationPosition = currentTrack.length-1;
258
258
 
259
259
  for (var ii = 0; ii < pitches.length; ii++) {
260
260
  if (!pitchesTied[''+pitches[ii].pitch])
261
261
  currentTrack.push({ cmd: 'stop', pitch: pitches[ii].pitch });
262
262
  }
263
- currentTrack.push({ cmd: 'move', duration: normalBreakBetweenNotes });
263
+ currentTrack.push({ cmd: 'move', duration: normalBreakBetweenNotes*tempoChangeFactor });
264
264
  } else if (elem.rest) {
265
- currentTrack.push({ cmd: 'move', duration: duration });
265
+ currentTrack.push({ cmd: 'move', duration: duration*tempoChangeFactor });
266
266
  }
267
267
 
268
268
  if (elem.endTriplet) {
@@ -337,7 +337,7 @@ if (!window.ABCJS.midi)
337
337
  var gp = adjustPitch(graces[g]);
338
338
  if (gp !== skipNote)
339
339
  currentTrack.push({cmd: 'start', pitch: gp, volume: 64});
340
- currentTrack.push({cmd: 'move', duration: graces[g].duration});
340
+ currentTrack.push({cmd: 'move', duration: graces[g].duration*tempoChangeFactor });
341
341
  if (gp !== skipNote)
342
342
  currentTrack.push({cmd: 'stop', pitch: gp});
343
343
  if (!stealFromCurrent)
@@ -404,8 +404,11 @@ if (!window.ABCJS.midi)
404
404
  var arr = remaining.split('/');
405
405
  chick = chordNotes(bass, arr[0]);
406
406
  if (arr.length === 2) {
407
- bass = basses[arr[1]] + transpose;
408
- bass2 = bass;
407
+ var explicitBass = basses[arr[1]];
408
+ if (explicitBass) {
409
+ bass = basses[arr[1]] + transpose;
410
+ bass2 = bass;
411
+ }
409
412
  }
410
413
  return { boom: bass, boom2: bass2, chick: chick };
411
414
  }
@@ -458,19 +461,19 @@ if (!window.ABCJS.midi)
458
461
  // undefined means there is a stop time.
459
462
  if (boom !== undefined)
460
463
  chordTrack.push({cmd: 'start', pitch: boom, volume: 64});
461
- chordTrack.push({ cmd: 'move', duration: beatLength/2 });
464
+ chordTrack.push({ cmd: 'move', duration: (beatLength/2)*tempoChangeFactor });
462
465
  if (boom !== undefined)
463
466
  chordTrack.push({ cmd: 'stop', pitch: boom });
464
- chordTrack.push({ cmd: 'move', duration: beatLength/2 });
467
+ chordTrack.push({ cmd: 'move', duration: (beatLength/2)*tempoChangeFactor });
465
468
  }
466
469
 
467
470
  function writeChick(chick, beatLength) {
468
471
  for (var c = 0; c < chick.length; c++)
469
472
  chordTrack.push({cmd: 'start', pitch: chick[c], volume: 48});
470
- chordTrack.push({ cmd: 'move', duration: beatLength/2 });
473
+ chordTrack.push({ cmd: 'move', duration: (beatLength/2)*tempoChangeFactor });
471
474
  for (c = 0; c < chick.length; c++)
472
475
  chordTrack.push({ cmd: 'stop', pitch: chick[c] });
473
- chordTrack.push({ cmd: 'move', duration: beatLength/2 });
476
+ chordTrack.push({ cmd: 'move', duration: (beatLength/2)*tempoChangeFactor });
474
477
  }
475
478
 
476
479
  var rhythmPatterns = { "2/2": [ 'boom', 'chick' ],
@@ -514,7 +517,7 @@ if (!window.ABCJS.midi)
514
517
  writeChick(currentChords[0].chord.chick, beatLength);
515
518
  break;
516
519
  case '':
517
- chordTrack.push({ cmd: 'move', duration: beatLength });
520
+ chordTrack.push({ cmd: 'move', duration: beatLength*tempoChangeFactor });
518
521
  break;
519
522
  }
520
523
  }
@@ -557,7 +560,7 @@ if (!window.ABCJS.midi)
557
560
  if (beats[''+m2]) // If there is an explicit chord on this beat, play it.
558
561
  writeChick(thisChord.chord.chick, beatLength);
559
562
  else
560
- chordTrack.push({cmd: 'move', duration: beatLength});
563
+ chordTrack.push({cmd: 'move', duration: beatLength*tempoChangeFactor });
561
564
  break;
562
565
  }
563
566
  }
@@ -0,0 +1,233 @@
1
+ // abc_midi_js_preparer.js: Create the structure that MIDI.js expects.
2
+ // Copyright (C) 2010,2016 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
3
+ //
4
+ // This program is free software: you can redistribute it and/or modify
5
+ // it under the terms of the GNU General Public License as published by
6
+ // the Free Software Foundation, either version 3 of the License, or
7
+ // (at your option) any later version.
8
+ //
9
+ // This program is distributed in the hope that it will be useful,
10
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ // GNU General Public License for more details.
13
+ //
14
+ // You should have received a copy of the GNU General Public License
15
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ if (!window.ABCJS)
18
+ window.ABCJS = {};
19
+
20
+ if (!window.ABCJS.midi)
21
+ window.ABCJS.midi = {};
22
+
23
+ (function() {
24
+ "use strict";
25
+
26
+ window.ABCJS.midi.Preparer = function() {
27
+ this.tempo = 0;
28
+ this.timeFactor = 0;
29
+ this.output = [];
30
+ this.currentChannel = 0;
31
+ this.currentInstrument = 0;
32
+ this.track = 0;
33
+ this.nextDuration = 0;
34
+ this.tracks = [ [] ];
35
+ };
36
+
37
+ var Preparer = window.ABCJS.midi.Preparer;
38
+
39
+ Preparer.prototype.setInstrument = function(instrument) {
40
+ // TODO-PER: for the first version, there are no channel or instrument changes.
41
+ //this.currentInstrument = instrument;
42
+
43
+ var ev = [
44
+ {
45
+ ticksToEvent: 0,
46
+ track: this.track,
47
+ event: {
48
+ channel: this.currentChannel,
49
+ deltaTime: 0,
50
+ programNumber: this.currentInstrument,
51
+ subtype: 'programChange',
52
+ type: 'channel'
53
+ }
54
+ },
55
+ this.nextDuration * this.timeFactor
56
+ ];
57
+ this.tracks[this.track].push(ev);
58
+ };
59
+
60
+ Preparer.prototype.setChannel = function(channel) {
61
+ // TODO-PER: for the first version, there are no channel or instrument changes.
62
+ //this.currentChannel = channel;
63
+ };
64
+
65
+ Preparer.prototype.startTrack = function() {
66
+ this.track++;
67
+ this.tracks[this.track] = [];
68
+ this.nextDuration = 0;
69
+ };
70
+
71
+ Preparer.prototype.setGlobalInfo = function(tempo, title) {
72
+ this.tempo = tempo;
73
+ var mspb = Math.round((1.0/tempo)*60000000);
74
+ this.timeFactor = mspb / 480000;
75
+ var ev = [
76
+ {
77
+ ticksToEvent: 0,
78
+ track: this.track,
79
+ event: {
80
+ deltaTime: 0,
81
+ microsecondsPerBeat: mspb,
82
+ subtype: 'setTempo',
83
+ type: 'meta'
84
+ }
85
+ },
86
+ this.nextDuration * this.timeFactor
87
+ ];
88
+ // this.tracks[this.track].push(ev);
89
+
90
+ ev = [
91
+ {
92
+ ticksToEvent: 0,
93
+ track: this.track,
94
+ event: {
95
+ deltaTime: 0,
96
+ subtype: 'trackName',
97
+ text: title,
98
+ type: 'meta'
99
+ }
100
+ },
101
+ this.nextDuration * this.timeFactor
102
+ ];
103
+ // this.tracks[this.track].push(ev);
104
+
105
+ ev = [
106
+ {
107
+ ticksToEvent: 0,
108
+ track: this.track,
109
+ event: {
110
+ deltaTime: 0,
111
+ subtype: 'endOfTrack',
112
+ type: 'meta'
113
+ }
114
+ },
115
+ this.nextDuration * this.timeFactor
116
+ ];
117
+ // this.tracks[this.track].push(ev);
118
+ };
119
+
120
+ Preparer.prototype.startNote = function(pitch, volume) {
121
+ var deltaTime = Math.floor(this.nextDuration / 5) * 5;
122
+ var ev = [
123
+ {
124
+ ticksToEvent: deltaTime,
125
+ track: this.track,
126
+ event: {
127
+ deltaTime: deltaTime,
128
+ channel: this.currentChannel,
129
+ type: "channel",
130
+ noteNumber: pitch,
131
+ velocity: volume,
132
+ subtype: "noteOn"
133
+ }
134
+ },
135
+ this.nextDuration * this.timeFactor
136
+ ];
137
+ this.tracks[this.track].push(ev);
138
+ this.nextDuration = 0;
139
+ };
140
+
141
+ Preparer.prototype.endNote = function(pitch) {
142
+ var deltaTime = Math.floor(this.nextDuration / 5) * 5;
143
+ var ev = [
144
+ {
145
+ ticksToEvent: deltaTime,
146
+ track: this.track,
147
+ event: {
148
+ deltaTime: deltaTime,
149
+ channel: this.currentChannel,
150
+ type: "channel",
151
+ noteNumber: pitch,
152
+ velocity: 0,
153
+ subtype: "noteOff"
154
+ }
155
+ },
156
+ this.nextDuration * this.timeFactor
157
+ ];
158
+ this.tracks[this.track].push(ev);
159
+ this.nextDuration = 0;
160
+ };
161
+
162
+ Preparer.prototype.addRest = function(duration) {
163
+ this.nextDuration += duration;
164
+ };
165
+
166
+ Preparer.prototype.endTrack = function() {
167
+ var ev = [
168
+ {
169
+ ticksToEvent: 0,
170
+ track: this.track,
171
+ event: {
172
+ deltaTime: 0,
173
+ type: "meta",
174
+ subtype: "endOfTrack"
175
+ }
176
+ },
177
+ 0
178
+ ];
179
+ // this.tracks[this.track].push(ev);
180
+ };
181
+
182
+ function addAbsoluteTime(tracks) {
183
+ for (var i = 0; i < tracks.length; i++) {
184
+ var absTime = 0;
185
+ for (var j = 0; j < tracks[i].length; j++) {
186
+ absTime += tracks[i][j][1];
187
+ tracks[i][j].absTime = absTime;
188
+ }
189
+ }
190
+ }
191
+
192
+ function combineTracks(tracks) {
193
+ var output = [];
194
+ for (var i = 0; i < tracks.length; i++) {
195
+ for (var j = 0; j < tracks[i].length; j++) {
196
+ output.push(tracks[i][j]);
197
+ }
198
+ }
199
+ return output;
200
+ }
201
+
202
+ function sortTracks(output) {
203
+ return output.sort(function(a,b) {
204
+ if (a.absTime > b.absTime) return 1;
205
+ return -1;
206
+ });
207
+ }
208
+
209
+ function adjustTime(output) {
210
+ var lastTime = 0;
211
+ for (var i = 0; i < output.length; i++) {
212
+ var thisTime = output[i].absTime;
213
+ output[i][1] = thisTime - lastTime;
214
+ lastTime = thisTime;
215
+ }
216
+ }
217
+
218
+ function weaveTracks(tracks) {
219
+ // Each track has a progression of delta times. To combine them, first assign an absolute time to each event,
220
+ // then make one large track of all the tracks, sort it by absolute time, then adjust the amount of time each
221
+ // event causes time to move. That is, the movement was figured out as the distance from the last note in the track,
222
+ // but now we want the distance from the last note on ANY track.
223
+ addAbsoluteTime(tracks);
224
+ var output = combineTracks(tracks);
225
+ output = sortTracks(output);
226
+ adjustTime(output);
227
+ return output;
228
+ }
229
+
230
+ Preparer.prototype.getData = function() {
231
+ return weaveTracks(this.tracks);
232
+ };
233
+ })();
@@ -1,5 +1,5 @@
1
1
  // abc_midi_renderer.js: Create the actual format for the midi.
2
- // Copyright (C) 2010,2015 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
2
+ // Copyright (C) 2010,2016 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
3
3
  //
4
4
  // This program is free software: you can redistribute it and/or modify
5
5
  // it under the terms of the GNU General Public License as published by
@@ -29,215 +29,6 @@ if (!window.ABCJS.midi)
29
29
  return elm;
30
30
  }
31
31
 
32
- var MIDIPlugin;
33
- //TODO-PER: put this back in when the MIDIPlugin works again.
34
- //window.oldunload = window.onbeforeunload;
35
- //window.onbeforeunload = function() {
36
- // if (window.oldunload)
37
- // window.oldunload();
38
- // if (typeof(MIDIPlugin) !== "undefined" && MIDIPlugin) { // PER: take care of crash in IE 8
39
- // MIDIPlugin.closePlugin();
40
- // }
41
- //};
42
-
43
-
44
- function MidiProxy(javamidi, qtmidi) {
45
- this.javamidi = javamidi;
46
- this.qtmidi = qtmidi;
47
- }
48
-
49
- MidiProxy.prototype.setTempo = function(qpm) {
50
- this.javamidi.setTempo(qpm);
51
- this.qtmidi.setTempo(qpm);
52
- };
53
-
54
- MidiProxy.prototype.startTrack = function() {
55
- this.javamidi.startTrack();
56
- this.qtmidi.startTrack();
57
- };
58
-
59
- MidiProxy.prototype.endTrack = function() {
60
- this.javamidi.endTrack();
61
- this.qtmidi.endTrack();
62
- };
63
-
64
- MidiProxy.prototype.setInstrument = function(number) {
65
- this.javamidi.setInstrument(number);
66
- this.qtmidi.setInstrument(number);
67
- };
68
-
69
- MidiProxy.prototype.startNote = function(pitch, loudness, abcelem) {
70
- this.javamidi.startNote(pitch, loudness, abcelem);
71
- this.qtmidi.startNote(pitch, loudness, abcelem);
72
- };
73
-
74
- MidiProxy.prototype.endNote = function(pitch, length) {
75
- this.javamidi.endNote(pitch, length);
76
- this.qtmidi.endNote(pitch, length);
77
- };
78
-
79
- MidiProxy.prototype.addRest = function(length) {
80
- this.javamidi.addRest(length);
81
- this.qtmidi.addRest(length);
82
- };
83
-
84
- MidiProxy.prototype.embed = function(parent) {
85
- this.javamidi.embed(parent);
86
- this.qtmidi.embed(parent, true);
87
- };
88
-
89
- function JavaMidi(midiwriter) {
90
- this.playlist = []; // contains {time:t,funct:f} pairs
91
- this.trackcount = 0;
92
- this.timecount = 0;
93
- this.tempo = 60;
94
- this.midiapi = MIDIPlugin;
95
- this.midiwriter = midiwriter;
96
- this.noteOnAndChannel = "%90";
97
- }
98
-
99
- JavaMidi.prototype.setTempo = function(qpm) {
100
- this.tempo = qpm;
101
- };
102
-
103
- JavaMidi.prototype.startTrack = function() {
104
- this.silencelength = 0;
105
- this.trackcount++;
106
- this.timecount = 0;
107
- this.playlistpos = 0;
108
- this.first = true;
109
- if (this.instrument) {
110
- this.setInstrument(this.instrument);
111
- }
112
- if (this.channel) {
113
- this.setChannel(this.channel);
114
- }
115
- };
116
-
117
- JavaMidi.prototype.endTrack = function() {
118
- // need to do anything?
119
- };
120
-
121
- JavaMidi.prototype.setInstrument = function(number) {
122
- this.instrument = number;
123
- this.midiapi.setInstrument(number);
124
- //TODO push this into the playlist?
125
- };
126
-
127
- JavaMidi.prototype.setChannel = function(number) {
128
- this.channel = number;
129
- this.midiapi.setChannel(number);
130
- };
131
-
132
- JavaMidi.prototype.updatePos = function() {
133
- while (this.playlist[this.playlistpos] &&
134
- this.playlist[this.playlistpos].time < this.timecount) {
135
- this.playlistpos++;
136
- }
137
- };
138
-
139
- JavaMidi.prototype.startNote = function(pitch, loudness, abcelem) {
140
- this.timecount += this.silencelength;
141
- this.silencelength = 0;
142
- if (this.first) {
143
- //nothing special if first?
144
- }
145
- this.updatePos();
146
- var self = this;
147
- this.playlist.splice(this.playlistpos, 0, {
148
- time: this.timecount,
149
- funct: function() {
150
- self.midiapi.playNote(pitch);
151
- self.midiwriter.notifySelect(abcelem);
152
- }
153
- });
154
- };
155
-
156
- JavaMidi.prototype.endNote = function(pitch, length) {
157
- this.timecount += length;
158
- this.updatePos();
159
- var self = this;
160
- this.playlist.splice(this.playlistpos, 0, {
161
- time: this.timecount,
162
- funct: function() {
163
- self.midiapi.stopNote(pitch);
164
- }
165
- });
166
- };
167
-
168
- JavaMidi.prototype.addRest = function(length) {
169
- this.silencelength += length;
170
- };
171
-
172
- JavaMidi.prototype.embed = function(parent) {
173
-
174
-
175
- this.playlink = setAttributes(document.createElement('a'), {
176
- style: "border:1px solid black; margin:3px;"
177
- });
178
- this.playlink.innerHTML = "play";
179
- var self = this;
180
- this.playlink.onmousedown = function() {
181
- if (self.playing) {
182
- this.innerHTML = "play";
183
- self.pausePlay();
184
- } else {
185
- this.innerHTML = "pause";
186
- self.startPlay();
187
- }
188
- };
189
- parent.appendChild(this.playlink);
190
-
191
- var stoplink = setAttributes(document.createElement('a'), {
192
- style: "border:1px solid black; margin:3px;"
193
- });
194
- stoplink.innerHTML = "stop";
195
- //var self = this;
196
- stoplink.onmousedown = function() {
197
- self.stopPlay();
198
- };
199
- parent.appendChild(stoplink);
200
- this.i = 0;
201
- this.currenttime = 0;
202
- this.playing = false;
203
- };
204
-
205
- JavaMidi.prototype.stopPlay = function() {
206
- this.i = 0;
207
- this.currenttime = 0;
208
- this.pausePlay();
209
- this.playlink.innerHTML = "play";
210
- };
211
-
212
- JavaMidi.prototype.startPlay = function() {
213
- this.playing = true;
214
- var self = this;
215
- // repeat every 16th note TODO see the min in the piece
216
- this.ticksperinterval = 480 / 4;
217
- this.doPlay();
218
- this.playinterval = window.setInterval(function() {self.doPlay(); },
219
- (60000 / (this.tempo * 4)));
220
- };
221
-
222
- JavaMidi.prototype.pausePlay = function() {
223
- this.playing = false;
224
- window.clearInterval(this.playinterval);
225
- this.midiapi.stopAllNotes();
226
- };
227
-
228
- JavaMidi.prototype.doPlay = function() {
229
- while (this.playlist[this.i] &&
230
- this.playlist[this.i].time <= this.currenttime) {
231
- this.playlist[this.i].funct();
232
- this.i++;
233
- }
234
- if (this.playlist[this.i]) {
235
- this.currenttime += this.ticksperinterval;
236
- } else {
237
- this.stopPlay();
238
- }
239
- };
240
-
241
32
  function Midi() {
242
33
  this.trackstrings = "";
243
34
  this.trackcount = 0;
@@ -403,24 +194,7 @@ if (!window.ABCJS.midi)
403
194
  return toHex(res, padding);
404
195
  }
405
196
 
406
- window.ABCJS.midi.rendererFactory = function(isJava) {
407
- return (isJava) ? new MidiProxy(new JavaMidi(this), new Midi()) : new Midi();
197
+ window.ABCJS.midi.rendererFactory = function() {
198
+ return new Midi();
408
199
  };
409
-
410
- window.ABCJS.midi.initializeJava = function() {
411
- MIDIPlugin = document.MIDIPlugin;
412
- setTimeout(function() { // run on next event loop (once MIDIPlugin is loaded)
413
- try { // activate MIDIPlugin
414
- MIDIPlugin.openPlugin();
415
-
416
- } catch(e) { // plugin not supported (download externals)
417
- var a = document.createElement("a");
418
- a.href = "http://java.sun.com/products/java-media/sound/soundbanks.html";
419
- a.target = "_blank";
420
- a.appendChild(document.createTextNode("Download Soundbank"));
421
- parent.appendChild(a);
422
- }
423
- }, 0);
424
- };
425
-
426
200
  })();