midilib 2.0.5 → 3.0.1
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.
- checksums.yaml +5 -5
- data/ChangeLog +2 -1
- data/Credits +39 -2
- data/README.rdoc +5 -6
- data/Rakefile +36 -49
- data/TODO.rdoc +13 -2
- data/examples/from_scratch.rb +1 -1
- data/examples/measures_mbt.rb +11 -11
- data/examples/print_program_changes.rb +2 -2
- data/examples/reader2text.rb +47 -47
- data/examples/seq2text.rb +1 -1
- data/examples/split.rb +4 -3
- data/examples/strings.rb +4 -4
- data/examples/transpose.rb +19 -20
- data/install.rb +21 -13
- data/lib/midilib/consts.rb +237 -239
- data/lib/midilib/event.rb +128 -100
- data/lib/midilib/info.rb +3 -5
- data/lib/midilib/io/midifile.rb +155 -182
- data/lib/midilib/io/seqreader.rb +80 -85
- data/lib/midilib/io/seqwriter.rb +93 -88
- data/lib/midilib/measure.rb +78 -80
- data/lib/midilib/mergesort.rb +39 -0
- data/lib/midilib/sequence.rb +40 -32
- data/lib/midilib/track.rb +16 -57
- data/lib/midilib/utils.rb +4 -7
- data/lib/midilib.rb +5 -5
- data/test/event_equality.rb +28 -30
- data/test/test_event.rb +9 -11
- data/test/test_io.rb +83 -3
- data/test/test_mergesort.rb +37 -0
- data/test/test_midifile.rb +6 -19
- data/test/test_sequence.rb +5 -4
- data/test/test_track.rb +9 -38
- data/test/test_varlen.rb +1 -3
- metadata +8 -95
- data/html/IO.html +0 -155
- data/html/MIDI/ActiveSense.html +0 -206
- data/html/MIDI/ChannelEvent.html +0 -231
- data/html/MIDI/ChannelPressure.html +0 -265
- data/html/MIDI/Clock.html +0 -206
- data/html/MIDI/Continue.html +0 -206
- data/html/MIDI/Controller.html +0 -280
- data/html/MIDI/Event.html +0 -489
- data/html/MIDI/IO/MIDIFile.html +0 -2024
- data/html/MIDI/IO/SeqReader.html +0 -904
- data/html/MIDI/IO/SeqWriter.html +0 -572
- data/html/MIDI/IO.html +0 -95
- data/html/MIDI/KeySig.html +0 -353
- data/html/MIDI/MIDI/MIDI/Array.html +0 -255
- data/html/MIDI/MIDI/MIDI.html +0 -95
- data/html/MIDI/MIDI.html +0 -95
- data/html/MIDI/Marker.html +0 -158
- data/html/MIDI/Measure.html +0 -328
- data/html/MIDI/Measures.html +0 -285
- data/html/MIDI/MetaEvent.html +0 -461
- data/html/MIDI/NoteEvent.html +0 -331
- data/html/MIDI/NoteOff.html +0 -228
- data/html/MIDI/NoteOn.html +0 -228
- data/html/MIDI/PitchBend.html +0 -266
- data/html/MIDI/PolyPressure.html +0 -277
- data/html/MIDI/ProgramChange.html +0 -265
- data/html/MIDI/Realtime.html +0 -242
- data/html/MIDI/Sequence.html +0 -896
- data/html/MIDI/SongPointer.html +0 -266
- data/html/MIDI/SongSelect.html +0 -265
- data/html/MIDI/Start.html +0 -206
- data/html/MIDI/Stop.html +0 -206
- data/html/MIDI/SystemCommon.html +0 -158
- data/html/MIDI/SystemExclusive.html +0 -268
- data/html/MIDI/SystemReset.html +0 -206
- data/html/MIDI/Tempo.html +0 -396
- data/html/MIDI/TimeSig.html +0 -388
- data/html/MIDI/Track.html +0 -695
- data/html/MIDI/TuneRequest.html +0 -242
- data/html/MIDI/Utils.html +0 -220
- data/html/MIDI.html +0 -547
- data/html/README_rdoc.html +0 -731
- data/html/TODO_rdoc.html +0 -125
- data/html/created.rid +0 -14
- data/html/css/fonts.css +0 -167
- data/html/css/rdoc.css +0 -590
- data/html/fonts/Lato-Light.ttf +0 -0
- data/html/fonts/Lato-LightItalic.ttf +0 -0
- data/html/fonts/Lato-Regular.ttf +0 -0
- data/html/fonts/Lato-RegularItalic.ttf +0 -0
- data/html/fonts/SourceCodePro-Bold.ttf +0 -0
- data/html/fonts/SourceCodePro-Regular.ttf +0 -0
- data/html/images/add.png +0 -0
- data/html/images/arrow_up.png +0 -0
- data/html/images/brick.png +0 -0
- data/html/images/brick_link.png +0 -0
- data/html/images/bug.png +0 -0
- data/html/images/bullet_black.png +0 -0
- data/html/images/bullet_toggle_minus.png +0 -0
- data/html/images/bullet_toggle_plus.png +0 -0
- data/html/images/date.png +0 -0
- data/html/images/delete.png +0 -0
- data/html/images/find.png +0 -0
- data/html/images/loadingAnimation.gif +0 -0
- data/html/images/macFFBgHack.png +0 -0
- data/html/images/package.png +0 -0
- data/html/images/page_green.png +0 -0
- data/html/images/page_white_text.png +0 -0
- data/html/images/page_white_width.png +0 -0
- data/html/images/plugin.png +0 -0
- data/html/images/ruby.png +0 -0
- data/html/images/tag_blue.png +0 -0
- data/html/images/tag_green.png +0 -0
- data/html/images/transparent.png +0 -0
- data/html/images/wrench.png +0 -0
- data/html/images/wrench_orange.png +0 -0
- data/html/images/zoom.png +0 -0
- data/html/index.html +0 -768
- data/html/js/darkfish.js +0 -161
- data/html/js/jquery.js +0 -4
- data/html/js/navigation.js +0 -142
- data/html/js/navigation.js.gz +0 -0
- data/html/js/search.js +0 -109
- data/html/js/search_index.js +0 -1
- data/html/js/search_index.js.gz +0 -0
- data/html/js/searcher.js +0 -228
- data/html/js/searcher.js.gz +0 -0
- data/html/table_of_contents.html +0 -1265
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c7b4ef36d4f1d38a6f2c2bbf00fc34e7400822ab5f3f05242296bb383bf7cd35
|
|
4
|
+
data.tar.gz: e814f94bccbf648fb8ef7035551996673f6991114000ca7c7199c26cdee0d913
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f9942744aebb170da22efff3c845f9b976f473c6b1584f00abf7da4b680c730eeb597a0aff8fc45b32c965453283a6cb007172183284d9f6116ff89c31dfb57d
|
|
7
|
+
data.tar.gz: 588a781e7776ca3adf309ba1a1eb6b4668c1767927e832c05963c31c85bacd0aee11b68df6e5d930dae7911b5fca663c48806c90ff8e8f53ecd139aa3753db50
|
data/ChangeLog
CHANGED
data/Credits
CHANGED
|
@@ -29,7 +29,7 @@ Jari Williamsson <jari.williamsson@mailbox.swipnet.se>
|
|
|
29
29
|
Noah Thorp
|
|
30
30
|
|
|
31
31
|
Found a bug in the code intended to make midilib work under Ruby 1.9.
|
|
32
|
-
Found another bug in
|
|
32
|
+
Found another bug in KeySig.data_as_bytes.
|
|
33
33
|
|
|
34
34
|
Zach Chadwick (zachad on Github)
|
|
35
35
|
|
|
@@ -48,9 +48,46 @@ Shai Rosenfeld (shaiguitar on Github)
|
|
|
48
48
|
J (dark-panda on Github)
|
|
49
49
|
|
|
50
50
|
Instead of monkeypatching ::Array, put sorting methods into new
|
|
51
|
-
MIDI::Array subclass to avoid clashes with Rails
|
|
51
|
+
MIDI::Array subclass to avoid clashes with Rails apps.
|
|
52
52
|
|
|
53
53
|
Lucas lfzawacki (lfzawacki on Github)
|
|
54
54
|
|
|
55
55
|
Found a bug in the MIDI::IO::SeqReader class: the pitch_bend method's
|
|
56
56
|
msb and lsb parameters were reversed.
|
|
57
|
+
|
|
58
|
+
Parki <parki06780678@gmail.com>
|
|
59
|
+
|
|
60
|
+
Reported failure of install.rb with newer versions of Ruby due to use of
|
|
61
|
+
old 'ftools' standard library component.
|
|
62
|
+
|
|
63
|
+
Adam Murray (adamjmurray on Github)
|
|
64
|
+
|
|
65
|
+
Submitted a patch that avoids writing empty data when writing tracks.
|
|
66
|
+
|
|
67
|
+
@dylee on Github
|
|
68
|
+
|
|
69
|
+
Submitted a patch that improves key signature event code and to_s.
|
|
70
|
+
|
|
71
|
+
@willm on Github
|
|
72
|
+
|
|
73
|
+
Suggested that Sequence.length_to_delta round the result instead of
|
|
74
|
+
truncating it.
|
|
75
|
+
|
|
76
|
+
@kaorukobo on Github
|
|
77
|
+
|
|
78
|
+
Fixed a bug where the delta offset of META_SEQ_NAME and META_COPYRIGHT
|
|
79
|
+
events were incorrectly always set to 0. The delta time may be any
|
|
80
|
+
value (although META_COPYRIGHT should normally be 0).
|
|
81
|
+
|
|
82
|
+
@rhelsing on Github
|
|
83
|
+
|
|
84
|
+
Added the ability to save MIDI format 0 files.
|
|
85
|
+
|
|
86
|
+
Miika Alonen (@amiika on Github)
|
|
87
|
+
|
|
88
|
+
Updated midilib for Ruby 2.7 and 3.0 by using blocks instead of Proc
|
|
89
|
+
objects and changing require to require_relative where appropriate.
|
|
90
|
+
|
|
91
|
+
@johnkolen on Github
|
|
92
|
+
|
|
93
|
+
Pointed out incorrect values for CC_GEN_PURPOSE_{5,6,7,8}.
|
data/README.rdoc
CHANGED
|
@@ -8,7 +8,7 @@ http://github.com/jimm/midilib and the RubyGems.org page is
|
|
|
8
8
|
http://rubygems.org/gems/midilib, where you can also find all the RDoc
|
|
9
9
|
documentation.
|
|
10
10
|
|
|
11
|
-
midilib is compatible with Ruby
|
|
11
|
+
midilib is compatible with Ruby 2.6 and higher.
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
== Dependencies
|
|
@@ -55,10 +55,9 @@ runs all of the tests in the test directory.
|
|
|
55
55
|
|
|
56
56
|
== Overview
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
files in one file).
|
|
58
|
+
midilib can read and write MIDI file formats 0 (one single track) or 1
|
|
59
|
+
multiple tracks. By default, it writes format 1 which is the most common
|
|
60
|
+
format. MIDI file format 2 is not yet supported.
|
|
62
61
|
|
|
63
62
|
=== MIDI::Sequence
|
|
64
63
|
|
|
@@ -290,7 +289,7 @@ information. Though the first edition book is available online, I encourage
|
|
|
290
289
|
you to purchase a copy of the latest edition.
|
|
291
290
|
|
|
292
291
|
A description of the MIDI file format can be found in a few places such as
|
|
293
|
-
|
|
292
|
+
https://www.csie.ntu.edu.tw/~r92092/ref/midi/.
|
|
294
293
|
|
|
295
294
|
The MIDI message reference at http://www.jimmenard.com/midi_ref.html
|
|
296
295
|
describes the format of MIDI commands.
|
data/Rakefile
CHANGED
|
@@ -1,53 +1,46 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'rake'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
require 'rake/testtask'
|
|
7
|
-
else
|
|
8
|
-
require 'rake/rdoctask'
|
|
9
|
-
require 'rake/gempackagetask'
|
|
10
|
-
require 'rake/runtest'
|
|
11
|
-
end
|
|
3
|
+
require 'rdoc/task'
|
|
4
|
+
require 'rubygems/package_task'
|
|
5
|
+
require 'rake/testtask'
|
|
12
6
|
|
|
13
7
|
PROJECT_NAME = 'midilib'
|
|
14
8
|
RDOC_DIR = 'html'
|
|
15
9
|
|
|
16
10
|
PKG_FILES = FileList[ 'ChangeLog', 'Credits', 'Rakefile',
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
'README.rdoc', 'TODO.rdoc',
|
|
12
|
+
'examples/**/*',
|
|
13
|
+
'html/**/*',
|
|
14
|
+
'install.rb',
|
|
15
|
+
'lib/**/*.rb',
|
|
16
|
+
'test/**/*']
|
|
23
17
|
|
|
24
|
-
task :
|
|
18
|
+
task default: [:package]
|
|
25
19
|
|
|
26
20
|
spec = Gem::Specification.new do |s|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
s.platform = Gem::Platform::RUBY
|
|
22
|
+
s.name = PROJECT_NAME
|
|
23
|
+
s.version = `ruby -Ilib -e 'require "midilib/info"; puts MIDI::Version'`.strip
|
|
24
|
+
s.requirements << 'none'
|
|
31
25
|
|
|
32
|
-
|
|
26
|
+
s.require_path = 'lib'
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
s.files = PKG_FILES.to_a
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
s.extra_rdoc_files = ['README.rdoc', 'TODO.rdoc']
|
|
30
|
+
s.rdoc_options << '--main' << 'README.rdoc'
|
|
31
|
+
s.extra_rdoc_files = ['README.rdoc', 'TODO.rdoc']
|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
s.author = 'Jim Menard'
|
|
34
|
+
s.email = 'jim@jimmenard.com'
|
|
35
|
+
s.homepage = 'http://github.com/jimm/midilib'
|
|
36
|
+
s.rubyforge_project = PROJECT_NAME
|
|
37
|
+
s.license = 'Ruby'
|
|
45
38
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
midilib is a pure Ruby MIDI library useful for reading and
|
|
49
|
-
writing standard MIDI files and manipulating MIDI event data.
|
|
50
|
-
EOF
|
|
39
|
+
s.summary = 'MIDI file and event manipulation library'
|
|
40
|
+
s.description = <<~EOF
|
|
41
|
+
midilib is a pure Ruby MIDI library useful for reading and
|
|
42
|
+
writing standard MIDI files and manipulating MIDI event data.
|
|
43
|
+
EOF
|
|
51
44
|
end
|
|
52
45
|
|
|
53
46
|
if RUBY_VERSION >= '1.9'
|
|
@@ -67,24 +60,18 @@ else
|
|
|
67
60
|
end
|
|
68
61
|
|
|
69
62
|
# creates an "rdoc" task
|
|
70
|
-
Rake::RDocTask.new do |
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
Rake::RDocTask.new do |rd|
|
|
64
|
+
rd.main = 'README.rdoc'
|
|
65
|
+
rd.title = PROJECT_NAME
|
|
66
|
+
rd.rdoc_files.include('README.rdoc', 'TODO.rdoc', 'lib/**/*.rb')
|
|
74
67
|
end
|
|
75
68
|
|
|
76
|
-
desc
|
|
77
|
-
task :
|
|
69
|
+
desc 'Publish gem'
|
|
70
|
+
task publish: %i[rdoc package] do
|
|
78
71
|
version = `ruby -Ilib -e 'require "midilib/info"; puts MIDI::Version'`.strip
|
|
79
72
|
system "gem push pkg/midilib-#{version}.gem"
|
|
80
73
|
end
|
|
81
74
|
|
|
82
|
-
|
|
83
|
-
Rake::TestTask.new
|
|
84
|
-
else
|
|
85
|
-
task :test do
|
|
86
|
-
Rake::run_tests
|
|
87
|
-
end
|
|
88
|
-
end
|
|
75
|
+
Rake::TestTask.new
|
|
89
76
|
|
|
90
|
-
task :
|
|
77
|
+
task clean: %i[clobber_rdoc clobber_package]
|
data/TODO.rdoc
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
== Bugs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
midilib does not handle tempo changes when calculating +beats_per_minute+.
|
|
4
|
+
The tempo events are correctly handled when reading/writing/moving them
|
|
5
|
+
around, it's just the functions that answer questions about the current
|
|
6
|
+
tempo that are wrong. See https://github.com/jimm/midilib/issues/8. The
|
|
7
|
+
method +beats_per_minute+ and related methods like +pulses_to_seconds+ will
|
|
8
|
+
have to take into account the possibility of more than one tempo event. They
|
|
9
|
+
will probably have to take new arguments specifying where in the sequence
|
|
10
|
+
the beats or pulses are being requested. For example we could have
|
|
11
|
+
+beats_per_minute(at_seconds: 0.0, at_beat: 0.0)+ (where the two keyword
|
|
12
|
+
args are mutually exclusive). Perhaps there should be separately named
|
|
13
|
+
public methods like +beats_per_minute_at_seconds+ and
|
|
14
|
+
+beats_per_minute_at_beat+ as well.
|
|
4
15
|
|
|
5
16
|
== Features
|
|
6
17
|
|
|
@@ -15,7 +26,7 @@ No known bugs. (If that's not a challenge, I don't know what is.)
|
|
|
15
26
|
|
|
16
27
|
* Implement key signature in SeqReader.
|
|
17
28
|
|
|
18
|
-
*
|
|
29
|
+
* Ignore unknown chunks in MIDI files. See the MIDI file spec.
|
|
19
30
|
|
|
20
31
|
* Format 2 files(?).
|
|
21
32
|
|
data/examples/from_scratch.rb
CHANGED
data/examples/measures_mbt.rb
CHANGED
|
@@ -13,18 +13,18 @@ $LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
|
13
13
|
|
|
14
14
|
require 'midilib/sequence'
|
|
15
15
|
|
|
16
|
-
seq = MIDI::Sequence.new
|
|
17
|
-
File.open(ARGV[0], 'rb') { |
|
|
16
|
+
seq = MIDI::Sequence.new
|
|
17
|
+
File.open(ARGV[0], 'rb') { |file| seq.read(file) }
|
|
18
18
|
|
|
19
19
|
# Get all measures, so events can be mapped to measures:
|
|
20
20
|
measures = seq.get_measures
|
|
21
21
|
|
|
22
|
-
seq.each
|
|
23
|
-
track.each
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
seq.each do |track|
|
|
23
|
+
track.each do |e|
|
|
24
|
+
next unless e.is_a?(MIDI::NoteOn)
|
|
25
|
+
|
|
26
|
+
# Print out start of notes
|
|
27
|
+
e.print_note_names = true
|
|
28
|
+
puts measures.to_mbt(e) + " ch #{e.channel}: #{e.note_to_s}"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -9,7 +9,7 @@ require 'midilib/sequence'
|
|
|
9
9
|
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
10
10
|
|
|
11
11
|
# Read from MIDI file
|
|
12
|
-
seq = MIDI::Sequence.new
|
|
12
|
+
seq = MIDI::Sequence.new
|
|
13
13
|
|
|
14
14
|
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') do |file|
|
|
15
15
|
# The block we pass in to Sequence.read is called at the end of every
|
|
@@ -23,6 +23,6 @@ seq.each do |track|
|
|
|
23
23
|
track.each do |e|
|
|
24
24
|
e.print_decimal_numbers = true
|
|
25
25
|
e.print_channel_numbers_from_one = true
|
|
26
|
-
puts e if e.
|
|
26
|
+
puts e if e.is_a?(MIDI::ProgramChange)
|
|
27
27
|
end
|
|
28
28
|
end
|
data/examples/reader2text.rb
CHANGED
|
@@ -20,18 +20,17 @@ require 'midilib/io/midifile'
|
|
|
20
20
|
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
21
21
|
|
|
22
22
|
class TextTranslator < MIDI::IO::MIDIFile
|
|
23
|
-
|
|
24
|
-
def initialize(seq, proc = nil)
|
|
23
|
+
def initialize(seq, &block)
|
|
25
24
|
super()
|
|
26
25
|
@seq = seq
|
|
27
26
|
@track = nil
|
|
28
|
-
@update_block =
|
|
27
|
+
@update_block = block
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
# Generate a unique number for a channel/note combination. This is used
|
|
32
31
|
# to remember pending note on events.
|
|
33
32
|
def note_hash(chan, note)
|
|
34
|
-
|
|
33
|
+
(chan << 8) + note
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
# Print a delta time.
|
|
@@ -43,27 +42,29 @@ class TextTranslator < MIDI::IO::MIDIFile
|
|
|
43
42
|
|
|
44
43
|
def header(format, ntrks, division)
|
|
45
44
|
puts "header: format = #{format}, ntrks = #{ntrks}," +
|
|
46
|
-
|
|
45
|
+
" division = #{division}"
|
|
47
46
|
|
|
48
47
|
@ntrks = ntrks
|
|
49
48
|
@update_block.call(nil, @ntrks, 0) if @update_block
|
|
50
49
|
end
|
|
51
50
|
|
|
52
|
-
def start_track
|
|
53
|
-
pdelta
|
|
54
|
-
puts
|
|
51
|
+
def start_track
|
|
52
|
+
pdelta
|
|
53
|
+
puts 'track start'
|
|
55
54
|
|
|
56
55
|
@pending = []
|
|
57
56
|
@chan_mask = 0
|
|
58
57
|
end
|
|
59
58
|
|
|
60
|
-
def end_track
|
|
61
|
-
pdelta
|
|
59
|
+
def end_track
|
|
60
|
+
pdelta
|
|
62
61
|
puts "track end; chans used bitmask = #{@chan_mask}"
|
|
63
62
|
# Write message for any pending note on messages
|
|
64
63
|
@pending.each_with_index do |num, chan|
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
if note_obj
|
|
65
|
+
puts "pending note off missing for chan #{num >> 8}," +
|
|
66
|
+
" note #{num & 0xff}"
|
|
67
|
+
end
|
|
67
68
|
end
|
|
68
69
|
@pending = nil
|
|
69
70
|
|
|
@@ -72,9 +73,9 @@ class TextTranslator < MIDI::IO::MIDIFile
|
|
|
72
73
|
end
|
|
73
74
|
|
|
74
75
|
def note_on(chan, note, vel)
|
|
75
|
-
pdelta
|
|
76
|
+
pdelta
|
|
76
77
|
if vel == 0
|
|
77
|
-
print
|
|
78
|
+
print '(note on, vel 0) '
|
|
78
79
|
note_off(chan, note, 64)
|
|
79
80
|
return
|
|
80
81
|
end
|
|
@@ -85,73 +86,73 @@ class TextTranslator < MIDI::IO::MIDIFile
|
|
|
85
86
|
end
|
|
86
87
|
|
|
87
88
|
def note_off(chan, note, vel)
|
|
88
|
-
pdelta
|
|
89
|
+
pdelta
|
|
89
90
|
# Find note on, create note off, connect the two, and remove
|
|
90
91
|
# note on from pending list.
|
|
91
92
|
pnum = note_hash(chan, note)
|
|
92
93
|
@pending.each_with_index do |num, i|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
next unless pnum == num
|
|
95
|
+
|
|
96
|
+
puts "note off chan #{chan}, note #{note}, vel #{vel}"
|
|
97
|
+
@pending.delete_at(i)
|
|
98
|
+
return
|
|
98
99
|
end
|
|
99
100
|
puts "note off with no earlier note on (ch #{chan}, note" +
|
|
100
|
-
|
|
101
|
+
" #{note}, vel #{vel})"
|
|
101
102
|
end
|
|
102
103
|
|
|
103
104
|
def pressure(chan, note, press)
|
|
104
|
-
pdelta
|
|
105
|
+
pdelta
|
|
105
106
|
puts "pressure chan #{chan}, note #{note}, press #{press}"
|
|
106
107
|
track_uses_channel(chan)
|
|
107
108
|
end
|
|
108
109
|
|
|
109
110
|
def controller(chan, control, value)
|
|
110
|
-
pdelta
|
|
111
|
+
pdelta
|
|
111
112
|
puts "controller chan #{chan}, control #{control}, value #{value}"
|
|
112
113
|
track_uses_channel(chan)
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
def pitch_bend(chan, msb, lsb)
|
|
116
|
-
pdelta
|
|
117
|
+
pdelta
|
|
117
118
|
puts "pitch bend chan #{chan}, msb #{msb}, lsb #{lsb}"
|
|
118
119
|
track_uses_channel(chan)
|
|
119
120
|
end
|
|
120
121
|
|
|
121
122
|
def program(chan, program)
|
|
122
|
-
pdelta
|
|
123
|
+
pdelta
|
|
123
124
|
puts "program chan #{chan}, program #{program}"
|
|
124
125
|
track_uses_channel(chan)
|
|
125
126
|
end
|
|
126
127
|
|
|
127
128
|
def chan_pressure(chan, press)
|
|
128
|
-
pdelta
|
|
129
|
+
pdelta
|
|
129
130
|
puts "chan press chan #{chan}, press #{press}"
|
|
130
131
|
track_uses_channel(chan)
|
|
131
132
|
end
|
|
132
133
|
|
|
133
134
|
def sysex(msg)
|
|
134
|
-
pdelta
|
|
135
|
+
pdelta
|
|
135
136
|
puts "sysex size #{msg.length}"
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
def meta_misc(type, msg)
|
|
139
|
-
pdelta
|
|
140
|
+
pdelta
|
|
140
141
|
puts "meta misc type #{type}, length #{msg.length}"
|
|
141
142
|
end
|
|
142
143
|
|
|
143
144
|
def sequencer_specific(type, msg)
|
|
144
|
-
pdelta
|
|
145
|
+
pdelta
|
|
145
146
|
puts "sequencer specific type #{type}, msg #{msg.length}"
|
|
146
147
|
end
|
|
147
148
|
|
|
148
149
|
def sequence_number(num)
|
|
149
|
-
pdelta
|
|
150
|
+
pdelta
|
|
150
151
|
puts "sequence number #{num}"
|
|
151
152
|
end
|
|
152
153
|
|
|
153
154
|
def text(type, msg)
|
|
154
|
-
pdelta
|
|
155
|
+
pdelta
|
|
155
156
|
msg = MIDI::MetaEvent.bytes_as_str(msg)
|
|
156
157
|
case type
|
|
157
158
|
when MIDI::META_SEQ_NAME
|
|
@@ -165,54 +166,53 @@ class TextTranslator < MIDI::IO::MIDIFile
|
|
|
165
166
|
end
|
|
166
167
|
end
|
|
167
168
|
|
|
168
|
-
def eot
|
|
169
|
-
pdelta
|
|
170
|
-
puts
|
|
169
|
+
def eot
|
|
170
|
+
pdelta
|
|
171
|
+
puts 'end of track event'
|
|
171
172
|
end
|
|
172
173
|
|
|
173
174
|
def time_signature(numer, denom, clocks, qnotes)
|
|
174
|
-
pdelta
|
|
175
|
+
pdelta
|
|
175
176
|
puts "time sig numer #{numer}, denom #{denom}, clocks #{clocks}," +
|
|
176
|
-
|
|
177
|
+
" qnotes #{qnotes}"
|
|
177
178
|
end
|
|
178
179
|
|
|
179
180
|
def smpte(hour, min, sec, frame, fract)
|
|
180
|
-
pdelta
|
|
181
|
+
pdelta
|
|
181
182
|
puts "smpte #{hour}:#{min}.#{sec}, frame #{frame}, fract #{fract}"
|
|
182
183
|
end
|
|
183
184
|
|
|
184
185
|
def tempo(microsecs)
|
|
185
|
-
pdelta
|
|
186
|
-
bpm = 1.0 / microsecs
|
|
187
|
-
bpm *=
|
|
188
|
-
bpm *= 60.0
|
|
186
|
+
pdelta
|
|
187
|
+
bpm = 1.0 / microsecs # quarter notes per microsecond
|
|
188
|
+
bpm *= 1_000_000.0 # quarter notes per second
|
|
189
|
+
bpm *= 60.0 # quarter notes per minute
|
|
189
190
|
puts "tempo microsecs pqn = #{microsecs} (#{bpm} bpm)"
|
|
190
191
|
end
|
|
191
192
|
|
|
192
193
|
def key_signature(sharpflat, is_minor)
|
|
193
|
-
pdelta
|
|
194
|
+
pdelta
|
|
194
195
|
puts "key sig sharpflat #{sharpflat}, is_minor #{is_minor}"
|
|
195
196
|
end
|
|
196
197
|
|
|
197
198
|
def arbitrary(msg)
|
|
198
|
-
pdelta
|
|
199
|
+
pdelta
|
|
199
200
|
puts "arbitrary length = #{msg.length}"
|
|
200
201
|
end
|
|
201
202
|
|
|
202
203
|
def track_uses_channel(chan)
|
|
203
|
-
@chan_mask
|
|
204
|
+
@chan_mask |= (1 << chan)
|
|
204
205
|
end
|
|
205
|
-
|
|
206
206
|
end
|
|
207
207
|
|
|
208
208
|
# ================================================================
|
|
209
209
|
|
|
210
|
-
seq = MIDI::Sequence.new
|
|
210
|
+
seq = MIDI::Sequence.new
|
|
211
211
|
|
|
212
212
|
# Specify what class to use when reading the MIDI file.
|
|
213
213
|
seq.reader_class = TextTranslator
|
|
214
214
|
|
|
215
|
-
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') do |
|
|
215
|
+
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') do |file|
|
|
216
216
|
# The block we pass in to Sequence.read is called at the end of every
|
|
217
217
|
# track read. It is optional, but is useful for progress reports.
|
|
218
218
|
seq.read(file) do |track, num_tracks, i|
|
data/examples/seq2text.rb
CHANGED
|
@@ -19,7 +19,7 @@ require 'midilib/sequence'
|
|
|
19
19
|
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
20
20
|
|
|
21
21
|
# Read from MIDI file
|
|
22
|
-
seq = MIDI::Sequence.new
|
|
22
|
+
seq = MIDI::Sequence.new
|
|
23
23
|
|
|
24
24
|
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') do |file|
|
|
25
25
|
# The block we pass in to Sequence.read is called at the end of every
|
data/examples/split.rb
CHANGED
|
@@ -27,7 +27,7 @@ if filename == '-x'
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# Read from MIDI file
|
|
30
|
-
seq = MIDI::Sequence.new
|
|
30
|
+
seq = MIDI::Sequence.new
|
|
31
31
|
|
|
32
32
|
File.open(filename || DEFAULT_MIDI_TEST_FILE, 'rb') do |file|
|
|
33
33
|
# The block we pass in to Sequence.read is called at the end of every
|
|
@@ -41,12 +41,13 @@ t0 = seq.tracks[0]
|
|
|
41
41
|
unless include_tempo_track
|
|
42
42
|
s = MIDI::Sequence.new
|
|
43
43
|
s.tracks << t0
|
|
44
|
-
File.open(
|
|
44
|
+
File.open('tempo_track.mid', 'wb') { |file| s.write(file) }
|
|
45
45
|
end
|
|
46
46
|
seq.each_with_index do |track, i|
|
|
47
47
|
next unless i > 0
|
|
48
|
+
|
|
48
49
|
s = MIDI::Sequence.new
|
|
49
50
|
s.tracks << t0 if include_tempo_track
|
|
50
51
|
s.tracks << track
|
|
51
|
-
File.open("#{track.name}.mid", 'wb') { |
|
|
52
|
+
File.open("#{track.name}.mid", 'wb') { |file| s.write(file) }
|
|
52
53
|
end
|
data/examples/strings.rb
CHANGED
|
@@ -15,7 +15,7 @@ require 'midilib/consts'
|
|
|
15
15
|
|
|
16
16
|
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
17
17
|
|
|
18
|
-
seq = MIDI::Sequence.new
|
|
18
|
+
seq = MIDI::Sequence.new
|
|
19
19
|
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') do |file|
|
|
20
20
|
# The block we pass in to Sequence.read is called at the end of every
|
|
21
21
|
# track read. It is optional, but is useful for progress reports.
|
|
@@ -27,8 +27,8 @@ end
|
|
|
27
27
|
include MIDI
|
|
28
28
|
seq.each do |track|
|
|
29
29
|
track.each do |event|
|
|
30
|
-
puts event.data if event.
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
puts event.data if event.is_a?(MIDI::MetaEvent) &&
|
|
31
|
+
[META_TEXT, META_COPYRIGHT, META_SEQ_NAME, META_INSTRUMENT,
|
|
32
|
+
META_LYRIC, META_CUE, META_MARKER].include?(event.meta_type)
|
|
33
33
|
end
|
|
34
34
|
end
|