midilib 2.0.5 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|