midilib 0.8.4
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.
- data/ChangeLog +87 -0
- data/Credits +8 -0
- data/README +361 -0
- data/Rakefile +68 -0
- data/TODO +25 -0
- data/examples/NoFences.mid +0 -0
- data/examples/from_scratch.mid +0 -0
- data/examples/from_scratch.rb +56 -0
- data/examples/reader2text.rb +220 -0
- data/examples/seq2text.rb +41 -0
- data/examples/strings.rb +34 -0
- data/examples/transpose.rb +75 -0
- data/html/classes/MIDI.html +738 -0
- data/html/classes/MIDI/ActiveSense.html +156 -0
- data/html/classes/MIDI/ActiveSense.src/M000136.html +18 -0
- data/html/classes/MIDI/ActiveSense.src/M000137.html +18 -0
- data/html/classes/MIDI/ChannelEvent.html +179 -0
- data/html/classes/MIDI/ChannelEvent.src/M000124.html +20 -0
- data/html/classes/MIDI/ChannelEvent.src/M000125.html +18 -0
- data/html/classes/MIDI/ChannelPressure.html +184 -0
- data/html/classes/MIDI/ChannelPressure.src/M000088.html +19 -0
- data/html/classes/MIDI/ChannelPressure.src/M000089.html +21 -0
- data/html/classes/MIDI/ChannelPressure.src/M000090.html +18 -0
- data/html/classes/MIDI/Clock.html +156 -0
- data/html/classes/MIDI/Clock.src/M000134.html +18 -0
- data/html/classes/MIDI/Clock.src/M000135.html +18 -0
- data/html/classes/MIDI/Continue.html +156 -0
- data/html/classes/MIDI/Continue.src/M000132.html +18 -0
- data/html/classes/MIDI/Continue.src/M000133.html +18 -0
- data/html/classes/MIDI/Controller.html +189 -0
- data/html/classes/MIDI/Controller.src/M000129.html +21 -0
- data/html/classes/MIDI/Controller.src/M000130.html +22 -0
- data/html/classes/MIDI/Controller.src/M000131.html +18 -0
- data/html/classes/MIDI/Event.html +424 -0
- data/html/classes/MIDI/Event.src/M000145.html +27 -0
- data/html/classes/MIDI/Event.src/M000146.html +18 -0
- data/html/classes/MIDI/Event.src/M000147.html +18 -0
- data/html/classes/MIDI/Event.src/M000148.html +18 -0
- data/html/classes/MIDI/Event.src/M000149.html +18 -0
- data/html/classes/MIDI/Event.src/M000150.html +18 -0
- data/html/classes/MIDI/Event.src/M000151.html +18 -0
- data/html/classes/MIDI/Event.src/M000152.html +18 -0
- data/html/classes/MIDI/Event.src/M000153.html +18 -0
- data/html/classes/MIDI/Event.src/M000154.html +22 -0
- data/html/classes/MIDI/Event.src/M000155.html +18 -0
- data/html/classes/MIDI/Event.src/M000156.html +18 -0
- data/html/classes/MIDI/Event.src/M000157.html +18 -0
- data/html/classes/MIDI/IO.html +121 -0
- data/html/classes/MIDI/IO/MIDIFile.html +925 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000028.html +22 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000029.html +24 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000030.html +19 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000031.html +19 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000032.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000033.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000034.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000035.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000036.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000037.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000038.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000039.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000040.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000041.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000042.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000043.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000044.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000045.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000046.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000047.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000048.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000049.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000050.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000051.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000052.html +17 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000053.html +43 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000054.html +34 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000055.html +96 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000056.html +18 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000057.html +48 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000058.html +42 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000059.html +19 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000060.html +19 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000061.html +20 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000062.html +21 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000063.html +31 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000064.html +20 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000065.html +22 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000066.html +30 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000067.html +18 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000068.html +20 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000069.html +18 -0
- data/html/classes/MIDI/IO/MIDIFile.src/M000070.html +18 -0
- data/html/classes/MIDI/IO/SeqReader.html +460 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000001.html +22 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000002.html +22 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000003.html +21 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000004.html +34 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000005.html +26 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000006.html +28 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000007.html +21 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000008.html +19 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000009.html +19 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000010.html +19 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000011.html +19 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000012.html +19 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000013.html +18 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000014.html +18 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000015.html +27 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000016.html +18 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000017.html +18 -0
- data/html/classes/MIDI/IO/SeqReader.src/M000018.html +18 -0
- data/html/classes/MIDI/IO/SeqWriter.html +267 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000019.html +19 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000020.html +25 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000021.html +22 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000022.html +54 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000023.html +49 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000024.html +21 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000025.html +19 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000026.html +24 -0
- data/html/classes/MIDI/IO/SeqWriter.src/M000027.html +26 -0
- data/html/classes/MIDI/Marker.html +139 -0
- data/html/classes/MIDI/Marker.src/M000107.html +18 -0
- data/html/classes/MIDI/MetaEvent.html +189 -0
- data/html/classes/MIDI/MetaEvent.src/M000167.html +21 -0
- data/html/classes/MIDI/MetaEvent.src/M000168.html +23 -0
- data/html/classes/MIDI/MetaEvent.src/M000169.html +53 -0
- data/html/classes/MIDI/NoteEvent.html +233 -0
- data/html/classes/MIDI/NoteEvent.src/M000091.html +21 -0
- data/html/classes/MIDI/NoteEvent.src/M000092.html +20 -0
- data/html/classes/MIDI/NoteEvent.src/M000093.html +18 -0
- data/html/classes/MIDI/NoteEvent.src/M000094.html +22 -0
- data/html/classes/MIDI/NoteOffEvent.html +169 -0
- data/html/classes/MIDI/NoteOffEvent.src/M000086.html +19 -0
- data/html/classes/MIDI/NoteOffEvent.src/M000087.html +19 -0
- data/html/classes/MIDI/NoteOnEvent.html +169 -0
- data/html/classes/MIDI/NoteOnEvent.src/M000102.html +19 -0
- data/html/classes/MIDI/NoteOnEvent.src/M000103.html +19 -0
- data/html/classes/MIDI/PitchBend.html +184 -0
- data/html/classes/MIDI/PitchBend.src/M000104.html +19 -0
- data/html/classes/MIDI/PitchBend.src/M000105.html +22 -0
- data/html/classes/MIDI/PitchBend.src/M000106.html +18 -0
- data/html/classes/MIDI/PolyPressure.html +186 -0
- data/html/classes/MIDI/PolyPressure.src/M000170.html +18 -0
- data/html/classes/MIDI/PolyPressure.src/M000171.html +18 -0
- data/html/classes/MIDI/PolyPressure.src/M000172.html +18 -0
- data/html/classes/MIDI/PolyPressure.src/M000173.html +19 -0
- data/html/classes/MIDI/ProgramChange.html +184 -0
- data/html/classes/MIDI/ProgramChange.src/M000099.html +19 -0
- data/html/classes/MIDI/ProgramChange.src/M000100.html +21 -0
- data/html/classes/MIDI/ProgramChange.src/M000101.html +18 -0
- data/html/classes/MIDI/Realtime.html +171 -0
- data/html/classes/MIDI/Realtime.src/M000083.html +19 -0
- data/html/classes/MIDI/Realtime.src/M000084.html +20 -0
- data/html/classes/MIDI/Realtime.src/M000085.html +18 -0
- data/html/classes/MIDI/Sequence.html +469 -0
- data/html/classes/MIDI/Sequence.src/M000108.html +28 -0
- data/html/classes/MIDI/Sequence.src/M000109.html +21 -0
- data/html/classes/MIDI/Sequence.src/M000110.html +22 -0
- data/html/classes/MIDI/Sequence.src/M000113.html +18 -0
- data/html/classes/MIDI/Sequence.src/M000114.html +27 -0
- data/html/classes/MIDI/Sequence.src/M000115.html +18 -0
- data/html/classes/MIDI/Sequence.src/M000116.html +19 -0
- data/html/classes/MIDI/Sequence.src/M000117.html +19 -0
- data/html/classes/MIDI/Sequence.src/M000118.html +20 -0
- data/html/classes/MIDI/Sequence.src/M000119.html +19 -0
- data/html/classes/MIDI/Sequence.src/M000120.html +18 -0
- data/html/classes/MIDI/SongPointer.html +184 -0
- data/html/classes/MIDI/SongPointer.src/M000138.html +19 -0
- data/html/classes/MIDI/SongPointer.src/M000139.html +22 -0
- data/html/classes/MIDI/SongPointer.src/M000140.html +18 -0
- data/html/classes/MIDI/SongSelect.html +184 -0
- data/html/classes/MIDI/SongSelect.src/M000126.html +19 -0
- data/html/classes/MIDI/SongSelect.src/M000127.html +21 -0
- data/html/classes/MIDI/SongSelect.src/M000128.html +18 -0
- data/html/classes/MIDI/Start.html +156 -0
- data/html/classes/MIDI/Start.src/M000097.html +18 -0
- data/html/classes/MIDI/Start.src/M000098.html +18 -0
- data/html/classes/MIDI/Stop.html +156 -0
- data/html/classes/MIDI/Stop.src/M000095.html +18 -0
- data/html/classes/MIDI/Stop.src/M000096.html +18 -0
- data/html/classes/MIDI/SystemCommon.html +139 -0
- data/html/classes/MIDI/SystemCommon.src/M000144.html +19 -0
- data/html/classes/MIDI/SystemExclusive.html +184 -0
- data/html/classes/MIDI/SystemExclusive.src/M000141.html +19 -0
- data/html/classes/MIDI/SystemExclusive.src/M000142.html +23 -0
- data/html/classes/MIDI/SystemExclusive.src/M000143.html +18 -0
- data/html/classes/MIDI/SystemReset.html +156 -0
- data/html/classes/MIDI/SystemReset.src/M000081.html +18 -0
- data/html/classes/MIDI/SystemReset.src/M000082.html +18 -0
- data/html/classes/MIDI/Tempo.html +250 -0
- data/html/classes/MIDI/Tempo.src/M000158.html +18 -0
- data/html/classes/MIDI/Tempo.src/M000159.html +18 -0
- data/html/classes/MIDI/Tempo.src/M000160.html +18 -0
- data/html/classes/MIDI/Tempo.src/M000161.html +18 -0
- data/html/classes/MIDI/Tempo.src/M000162.html +18 -0
- data/html/classes/MIDI/Tempo.src/M000163.html +25 -0
- data/html/classes/MIDI/Tempo.src/M000164.html +18 -0
- data/html/classes/MIDI/Track.html +380 -0
- data/html/classes/MIDI/Track.src/M000071.html +23 -0
- data/html/classes/MIDI/Track.src/M000072.html +21 -0
- data/html/classes/MIDI/Track.src/M000073.html +26 -0
- data/html/classes/MIDI/Track.src/M000074.html +18 -0
- data/html/classes/MIDI/Track.src/M000075.html +22 -0
- data/html/classes/MIDI/Track.src/M000076.html +20 -0
- data/html/classes/MIDI/Track.src/M000077.html +22 -0
- data/html/classes/MIDI/Track.src/M000078.html +22 -0
- data/html/classes/MIDI/Track.src/M000079.html +18 -0
- data/html/classes/MIDI/Track.src/M000080.html +19 -0
- data/html/classes/MIDI/TuneRequest.html +171 -0
- data/html/classes/MIDI/TuneRequest.src/M000121.html +18 -0
- data/html/classes/MIDI/TuneRequest.src/M000122.html +20 -0
- data/html/classes/MIDI/TuneRequest.src/M000123.html +18 -0
- data/html/classes/MIDI/Utils.html +190 -0
- data/html/classes/MIDI/Utils.src/M000165.html +20 -0
- data/html/classes/MIDI/Utils.src/M000166.html +25 -0
- data/html/created.rid +1 -0
- data/html/files/README.html +599 -0
- data/html/files/TODO.html +142 -0
- data/html/files/lib/midilib/consts_rb.html +107 -0
- data/html/files/lib/midilib/event_rb.html +109 -0
- data/html/files/lib/midilib/info_rb.html +101 -0
- data/html/files/lib/midilib/io/midifile_rb.html +108 -0
- data/html/files/lib/midilib/io/seqreader_rb.html +110 -0
- data/html/files/lib/midilib/io/seqwriter_rb.html +115 -0
- data/html/files/lib/midilib/sequence_rb.html +109 -0
- data/html/files/lib/midilib/track_rb.html +108 -0
- data/html/files/lib/midilib/utils_rb.html +101 -0
- data/html/files/lib/midilib_rb.html +124 -0
- data/html/fr_class_index.html +59 -0
- data/html/fr_file_index.html +38 -0
- data/html/fr_method_index.html +199 -0
- data/html/index.html +24 -0
- data/html/rdoc-style.css +208 -0
- data/install.rb +57 -0
- data/lib/midilib.rb +16 -0
- data/lib/midilib/consts.rb +422 -0
- data/lib/midilib/event.rb +559 -0
- data/lib/midilib/info.rb +9 -0
- data/lib/midilib/io/midifile.rb +446 -0
- data/lib/midilib/io/seqreader.rb +198 -0
- data/lib/midilib/io/seqwriter.rb +151 -0
- data/lib/midilib/sequence.rb +144 -0
- data/lib/midilib/track.rb +115 -0
- data/lib/midilib/utils.rb +36 -0
- data/test/event_equality.rb +81 -0
- data/test/test_event.rb +116 -0
- data/test/test_io.rb +55 -0
- data/test/test_sequence.rb +68 -0
- data/test/test_track.rb +111 -0
- data/test/test_varlen.rb +40 -0
- metadata +330 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require_gem 'rake'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
require 'rake/gempackagetask'
|
|
5
|
+
require 'rake/contrib/rubyforgepublisher'
|
|
6
|
+
require 'rake/runtest'
|
|
7
|
+
|
|
8
|
+
PROJECT_NAME = 'midilib'
|
|
9
|
+
RUBYFORGE_USER = 'jimm'
|
|
10
|
+
RDOC_DIR = 'html'
|
|
11
|
+
|
|
12
|
+
PKG_FILES = FileList[ 'ChangeLog', 'Credits', 'README', 'Rakefile', 'TODO',
|
|
13
|
+
'examples/**/*',
|
|
14
|
+
'html/**/*',
|
|
15
|
+
'install.rb',
|
|
16
|
+
'lib/**/*.rb',
|
|
17
|
+
'test/**/*.rb']
|
|
18
|
+
|
|
19
|
+
task :default => [:package]
|
|
20
|
+
|
|
21
|
+
spec = Gem::Specification.new do |s|
|
|
22
|
+
s.platform = Gem::Platform::RUBY
|
|
23
|
+
s.name = PROJECT_NAME
|
|
24
|
+
s.version = `ruby -Ilib -e 'require "midilib/info"; puts MIDI::Version'`.strip
|
|
25
|
+
s.requirements << 'none'
|
|
26
|
+
|
|
27
|
+
s.require_path = 'lib'
|
|
28
|
+
s.autorequire = PROJECT_NAME
|
|
29
|
+
|
|
30
|
+
s.files = PKG_FILES.to_a
|
|
31
|
+
|
|
32
|
+
s.has_rdoc = true
|
|
33
|
+
s.rdoc_options << '--main' << 'README'
|
|
34
|
+
s.extra_rdoc_files = ['README', 'TODO']
|
|
35
|
+
|
|
36
|
+
s.author = 'Jim Menard'
|
|
37
|
+
s.email = 'jimm@io.com'
|
|
38
|
+
s.homepage = 'http://midilib.rubyforge.org'
|
|
39
|
+
s.rubyforge_project = PROJECT_NAME
|
|
40
|
+
|
|
41
|
+
s.summary = "MIDI file and event manipulation library"
|
|
42
|
+
s.description = <<EOF
|
|
43
|
+
midilib is a pure Ruby MIDI library useful for reading and
|
|
44
|
+
writing standard MIDI files and manipulating MIDI event data.
|
|
45
|
+
EOF
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Creates a :package task (also named :gem). Also useful are :clobber_package
|
|
49
|
+
# and :repackage.
|
|
50
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
51
|
+
pkg.need_zip = true
|
|
52
|
+
pkg.need_tar = true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# creates an "rdoc" task
|
|
56
|
+
Rake::RDocTask.new do | rd |
|
|
57
|
+
rd.main = 'README'
|
|
58
|
+
rd.title = PROJECT_NAME
|
|
59
|
+
rd.rdoc_files.include('README', 'TODO', 'lib/**/*.rb')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
task :rubyforge => [:rdoc] do
|
|
63
|
+
Rake::RubyForgePublisher.new(PROJECT_NAME, RUBYFORGE_USER).upload
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
task :test do
|
|
67
|
+
Rake::run_tests
|
|
68
|
+
end
|
data/TODO
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
== Bugs
|
|
2
|
+
|
|
3
|
+
* None known.
|
|
4
|
+
|
|
5
|
+
== Features
|
|
6
|
+
|
|
7
|
+
* Method to translate event's time_from_start to number of milliseconds from
|
|
8
|
+
start.
|
|
9
|
+
|
|
10
|
+
* Swing quantizing. (Implied by list email from Carl Youngblood
|
|
11
|
+
<carl.youngblood@gmail.com>)
|
|
12
|
+
|
|
13
|
+
* Implement key signature in SeqReader.
|
|
14
|
+
|
|
15
|
+
* Format 0 files.
|
|
16
|
+
|
|
17
|
+
* Format 2 files(?).
|
|
18
|
+
|
|
19
|
+
== Documentation
|
|
20
|
+
|
|
21
|
+
* Write better docs.
|
|
22
|
+
|
|
23
|
+
== Tests
|
|
24
|
+
|
|
25
|
+
* More needed?
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# usage: from_scratch.rb
|
|
4
|
+
#
|
|
5
|
+
# This script shows you how to create a new sequence from scratch and save it
|
|
6
|
+
# to a MIDI file. It creates a file called 'from_scratch.mid'.
|
|
7
|
+
|
|
8
|
+
# Start looking for MIDI module classes in the directory above this one.
|
|
9
|
+
# This forces us to use the local copy, even if there is a previously
|
|
10
|
+
# installed version out there somewhere.
|
|
11
|
+
$LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
12
|
+
|
|
13
|
+
require 'midilib/sequence'
|
|
14
|
+
require 'midilib/consts'
|
|
15
|
+
include MIDI
|
|
16
|
+
|
|
17
|
+
seq = Sequence.new()
|
|
18
|
+
|
|
19
|
+
# Create a first track for the sequence. This holds tempo events and stuff
|
|
20
|
+
# like that.
|
|
21
|
+
track = Track.new(seq)
|
|
22
|
+
seq.tracks << track
|
|
23
|
+
track.events << Tempo.new(Tempo.bpm_to_mpq(120))
|
|
24
|
+
track.events << MetaEvent.new(META_SEQ_NAME, 'Sequence Name')
|
|
25
|
+
|
|
26
|
+
# Create a track to hold the notes. Add it to the sequence.
|
|
27
|
+
track = Track.new(seq)
|
|
28
|
+
seq.tracks << track
|
|
29
|
+
|
|
30
|
+
# Give the track a name and an instrument name (optional).
|
|
31
|
+
track.name = 'My New Track'
|
|
32
|
+
track.instrument = GM_PATCH_NAMES[0]
|
|
33
|
+
|
|
34
|
+
# Add a volume controller event (optional).
|
|
35
|
+
track.events << Controller.new(0, CC_VOLUME, 127)
|
|
36
|
+
|
|
37
|
+
# Add events to the track: a major scale. Arguments for note on and note off
|
|
38
|
+
# constructors are channel, note, velocity, and delta_time. Channel numbers
|
|
39
|
+
# start at zero. We use the new Sequence#note_to_delta method to get the
|
|
40
|
+
# delta time length of a single quarter note.
|
|
41
|
+
track.events << ProgramChange.new(0, 1, 0)
|
|
42
|
+
quarter_note_length = seq.note_to_delta('quarter')
|
|
43
|
+
[0, 2, 4, 5, 7, 9, 11, 12].each { | offset |
|
|
44
|
+
track.events << NoteOnEvent.new(0, 64 + offset, 127, 0)
|
|
45
|
+
track.events << NoteOffEvent.new(0, 64 + offset, 127, quarter_note_length)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Calling recalc_times is not necessary, because that only sets the events'
|
|
49
|
+
# start times, which are not written out to the MIDI file. The delta times are
|
|
50
|
+
# what get written out.
|
|
51
|
+
|
|
52
|
+
# track.recalc_times
|
|
53
|
+
|
|
54
|
+
File.open('from_scratch.mid', 'wb') { | file |
|
|
55
|
+
seq.write(file)
|
|
56
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# usage: reader2text.rb [midi_file]
|
|
4
|
+
#
|
|
5
|
+
# This script translates a MIDI file into text. It subclasses MIDI::MIDIFile
|
|
6
|
+
# and overrides the methods that are called when various events are seen
|
|
7
|
+
# in the file.
|
|
8
|
+
#
|
|
9
|
+
# For a simpler way to do the same thing, see seq2text.rb.
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
# Start looking for MIDI module classes in the directory above this one.
|
|
13
|
+
# This forces us to use the local copy, even if there is a previously
|
|
14
|
+
# installed version out there somewhere.
|
|
15
|
+
$LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
16
|
+
|
|
17
|
+
require 'midilib/sequence'
|
|
18
|
+
require 'midilib/io/midifile'
|
|
19
|
+
|
|
20
|
+
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
21
|
+
|
|
22
|
+
class TextTranslator < MIDI::IO::MIDIFile
|
|
23
|
+
|
|
24
|
+
def initialize(seq, proc = nil)
|
|
25
|
+
super()
|
|
26
|
+
@seq = seq
|
|
27
|
+
@track = nil
|
|
28
|
+
@update_block = block_given?() ? Proc.new() : proc
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Generate a unique number for a channel/note combination. This is used
|
|
32
|
+
# to remember pending note on events.
|
|
33
|
+
def note_hash(chan, note)
|
|
34
|
+
return (chan << 8) + note
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Print a delta time.
|
|
38
|
+
def pdelta
|
|
39
|
+
print "#{@curr_ticks}: "
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# The remaining methods are overrides of methods in MIDI::IO::MIDIFile.
|
|
43
|
+
|
|
44
|
+
def header(format, ntrks, division)
|
|
45
|
+
puts "header: format = #{format}, ntrks = #{ntrks}," +
|
|
46
|
+
" division = #{division}"
|
|
47
|
+
|
|
48
|
+
@ntrks = ntrks
|
|
49
|
+
@update_block.call(nil, @ntrks, 0) if @update_block
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def start_track()
|
|
53
|
+
pdelta()
|
|
54
|
+
puts "track start"
|
|
55
|
+
|
|
56
|
+
@pending = []
|
|
57
|
+
@chan_mask = 0
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def end_track()
|
|
61
|
+
pdelta()
|
|
62
|
+
puts "track end; chans used bitmask = #{@chan_mask}"
|
|
63
|
+
# Write message for any pending note on messages
|
|
64
|
+
@pending.each_with_index { | num, chan |
|
|
65
|
+
puts "pending note off missing for chan #{num >> 8}," +
|
|
66
|
+
" note #{num & 0xff}" if note_obj
|
|
67
|
+
}
|
|
68
|
+
@pending = nil
|
|
69
|
+
|
|
70
|
+
# call update block
|
|
71
|
+
@update_block.call(@track, @ntrks, @seq.tracks.length) if @update_block
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def note_on(chan, note, vel)
|
|
75
|
+
pdelta()
|
|
76
|
+
if vel == 0
|
|
77
|
+
print "(note on, vel 0) "
|
|
78
|
+
note_off(chan, note, 64)
|
|
79
|
+
return
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
puts "note on chan #{chan}, note #{note}, vel #{vel}"
|
|
83
|
+
@pending << note_hash(chan, note)
|
|
84
|
+
track_uses_channel(chan)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def note_off(chan, note, vel)
|
|
88
|
+
pdelta()
|
|
89
|
+
# Find note on, create note off, connect the two, and remove
|
|
90
|
+
# note on from pending list.
|
|
91
|
+
pnum = note_hash(chan, note)
|
|
92
|
+
@pending.each_with_index { | num, i |
|
|
93
|
+
if pnum == num
|
|
94
|
+
puts "note off chan #{chan}, note #{note}, vel #{vel}"
|
|
95
|
+
@pending.delete_at(i)
|
|
96
|
+
return
|
|
97
|
+
end
|
|
98
|
+
}
|
|
99
|
+
puts "note off with no earlier note on (ch #{chan}, note" +
|
|
100
|
+
" #{note}, vel #{vel})"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def pressure(chan, note, press)
|
|
104
|
+
pdelta()
|
|
105
|
+
puts "pressure chan #{chan}, note #{note}, press #{press}"
|
|
106
|
+
track_uses_channel(chan)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def controller(chan, control, value)
|
|
110
|
+
pdelta()
|
|
111
|
+
puts "controller chan #{chan}, control #{control}, value #{value}"
|
|
112
|
+
track_uses_channel(chan)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def pitch_bend(chan, msb, lsb)
|
|
116
|
+
pdelta()
|
|
117
|
+
puts "pitch bend chan #{chan}, msb #{msb}, lsb #{lsb}"
|
|
118
|
+
track_uses_channel(chan)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def program(chan, program)
|
|
122
|
+
pdelta()
|
|
123
|
+
puts "program chan #{chan}, program #{program}"
|
|
124
|
+
track_uses_channel(chan)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def chan_pressure(chan, press)
|
|
128
|
+
pdelta()
|
|
129
|
+
puts "chan press chan #{chan}, press #{press}"
|
|
130
|
+
track_uses_channel(chan)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def sysex(msg)
|
|
134
|
+
pdelta()
|
|
135
|
+
puts "sysex size #{msg.length}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def meta_misc(type, msg)
|
|
139
|
+
pdelta()
|
|
140
|
+
puts "meta misc type #{type}, length #{msg.length}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def sequencer_specific(type, msg)
|
|
144
|
+
pdelta()
|
|
145
|
+
puts "sequencer specific type #{type}, msg #{msg.length}"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def sequence_number(num)
|
|
149
|
+
pdelta()
|
|
150
|
+
puts "sequence number #{num}"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def text(type, msg)
|
|
154
|
+
pdelta()
|
|
155
|
+
case type
|
|
156
|
+
when MIDI::META_SEQ_NAME
|
|
157
|
+
puts "seq or track name #{msg}"
|
|
158
|
+
when MIDI::META_INSTRUMENT
|
|
159
|
+
puts "instrument name #{msg}"
|
|
160
|
+
when MIDI::META_MARKER
|
|
161
|
+
puts "marker #{msg}"
|
|
162
|
+
else
|
|
163
|
+
puts "text = #{msg}, type = #{type}"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def eot()
|
|
168
|
+
pdelta()
|
|
169
|
+
puts "end of track event"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def time_signature(numer, denom, clocks, qnotes)
|
|
173
|
+
pdelta()
|
|
174
|
+
puts "time sig numer #{numer}, denom #{denom}, clocks #{clocks}," +
|
|
175
|
+
" qnotes #{qnotes}"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def smpte(hour, min, sec, frame, fract)
|
|
179
|
+
pdelta()
|
|
180
|
+
puts "smpte #{hour}:#{min}.#{sec}, frame #{frame}, fract #{fract}"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def tempo(microsecs)
|
|
184
|
+
pdelta()
|
|
185
|
+
bpm = 1.0 / microsecs # quarter notes per microsecond
|
|
186
|
+
bpm *= 1000000.0 # quarter notes per second
|
|
187
|
+
bpm *= 60.0 # quarter notes per minute
|
|
188
|
+
puts "tempo microsecs pqn = #{microsecs} (#{bpm} bpm)"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def key_signature(sharpflat, is_minor)
|
|
192
|
+
pdelta()
|
|
193
|
+
puts "key sig sharpflat #{sharpflat}, is_minor #{is_minor}"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def arbitrary(msg)
|
|
197
|
+
pdelta()
|
|
198
|
+
puts "arbitrary length = #{msg.length}"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def track_uses_channel(chan)
|
|
202
|
+
@chan_mask = @chan_mask | (1 << chan)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# ================================================================
|
|
208
|
+
|
|
209
|
+
seq = MIDI::Sequence.new()
|
|
210
|
+
|
|
211
|
+
# Specify what class to use when reading the MIDI file.
|
|
212
|
+
seq.reader_class = TextTranslator
|
|
213
|
+
|
|
214
|
+
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') { | file |
|
|
215
|
+
# The block we pass in to Sequence.read is called at the end of every
|
|
216
|
+
# track read. It is optional, but is useful for progress reports.
|
|
217
|
+
seq.read(file) { | track, num_tracks, i |
|
|
218
|
+
puts "read track #{track ? track.name : ''} (#{i} of #{num_tracks})"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# usage: seq2text.rb [midi_file]
|
|
4
|
+
#
|
|
5
|
+
# This script translates a MIDI file into text. It reads the file into
|
|
6
|
+
# a MIDI::Sequence and calls to_s for each event.
|
|
7
|
+
#
|
|
8
|
+
# For a different (and more verbose) way to do the same thing, see
|
|
9
|
+
# reader2tex.rb.
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
# Start looking for MIDI module classes in the directory above this one.
|
|
13
|
+
# This forces us to use the local copy, even if there is a previously
|
|
14
|
+
# installed version out there somewhere.
|
|
15
|
+
$LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
16
|
+
|
|
17
|
+
require 'midilib/sequence'
|
|
18
|
+
|
|
19
|
+
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
20
|
+
|
|
21
|
+
# Read from MIDI file
|
|
22
|
+
seq = MIDI::Sequence.new()
|
|
23
|
+
|
|
24
|
+
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') { | file |
|
|
25
|
+
# The block we pass in to Sequence.read is called at the end of every
|
|
26
|
+
# track read. It is optional, but is useful for progress reports.
|
|
27
|
+
seq.read(file) { | track, num_tracks, i |
|
|
28
|
+
puts "read track #{track ? track.name : ''} (#{i} of #{num_tracks})"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
seq.each { | track |
|
|
33
|
+
puts "*** track name \"#{track.name}\""
|
|
34
|
+
puts "instrument name \"#{track.instrument}\""
|
|
35
|
+
puts "#{track.events.length} events"
|
|
36
|
+
track.each { | e |
|
|
37
|
+
e.print_decimal_numbers = true # default = false (print hex)
|
|
38
|
+
e.print_note_names = true # default = false (print note numbers)
|
|
39
|
+
puts e
|
|
40
|
+
}
|
|
41
|
+
}
|
data/examples/strings.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# usage: strings.rb [midi_file]
|
|
4
|
+
#
|
|
5
|
+
# Prints all strings (track names, etc.) found in the MIDI file.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
# Start looking for MIDI module classes in the directory above this one.
|
|
9
|
+
# This forces us to use the local copy, even if there is a previously
|
|
10
|
+
# installed version out there somewhere.
|
|
11
|
+
$LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
12
|
+
|
|
13
|
+
require 'midilib/sequence'
|
|
14
|
+
require 'midilib/consts'
|
|
15
|
+
|
|
16
|
+
DEFAULT_MIDI_TEST_FILE = 'NoFences.mid'
|
|
17
|
+
|
|
18
|
+
seq = MIDI::Sequence.new()
|
|
19
|
+
File.open(ARGV[0] || DEFAULT_MIDI_TEST_FILE, 'rb') { | file |
|
|
20
|
+
# The block we pass in to Sequence.read is called at the end of every
|
|
21
|
+
# track read. It is optional, but is useful for progress reports.
|
|
22
|
+
seq.read(file) { | track, num_tracks, i |
|
|
23
|
+
puts "read track #{track ? track.name : ''} (#{i} of #{num_tracks})"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
include MIDI
|
|
28
|
+
seq.each { | track |
|
|
29
|
+
track.each { | event |
|
|
30
|
+
puts event.data if event.meta? &&
|
|
31
|
+
[META_TEXT, META_COPYRIGHT, META_SEQ_NAME, META_INSTRUMENT,
|
|
32
|
+
META_LYRIC, META_CUE, META_MARKER].include?(event.meta_type)
|
|
33
|
+
}
|
|
34
|
+
}
|