abcjs-rails 2.3 → 3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  })();