/
octransmid.rb
141 lines (113 loc) · 3.51 KB
/
octransmid.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Fun Fact: Find bus stop numbers here: http://www.octranspo1.com/maps
require './octransposcraper'
require 'midilib/sequence'
require 'midilib/consts'
require 'optparse'
include MIDI
class OCTransmid
@@midi_directory = "midiexports/"
# Start the day at 6AM
@@day_start_time = Time.local(1,1,1,6,0,0)
# Pulses per quarter note. This needs to be at 500 so that
# when you specify a 1 millisecond delay, it actually is 1 millisecond.
@@ppqn = 500
@@seconds_in_a_day = 60 * 60 * 24
def initialize ( stop_number,options )
@scraper = OCTranspoScraper.new
@base_note = 50
@note_length = 1
@stop_number = stop_number
@seq = nil
if options[:multitrack]
return getMultipleTrackMidiSequence
else
return getSingleTrackMidiSequence
end
end
def exportToMidi
filename = "stop" << @stop_number
unless @seq.nil?
if(@seq.tracks.size > 1)
filename << "multi"
end
File.open(@@midi_directory + filename +".mid", 'wb') do | file |
@seq.write(file)
end
end
end
protected
# TODO: Error Checking
def getMultipleTrackMidiSequence
bus_arrivals = @scraper.getBusStopArrivals( @stop_number )
if bus_arrivals.empty?
return
end
@seq = Sequence.new()
@seq.ppqn = @@ppqn
bus_arrivals.each_with_index do |arrivals,index|
bus_number = arrivals[0]
arrival_times = arrivals[1]
# Create a new MIDI track per bus route
track = Track.new(@seq)
@seq.tracks << track
track.events << Controller.new(0, CC_VOLUME, 127)
track.events << ProgramChange.new(0, 1, 0)
delta = arrival_times[0] - @@day_start_time
delta = delta.to_i
new_note_event( @base_note , @note_length, track,127, delta )
0.upto(arrival_times.size-2).each do |i|
#time difference in seconds
delta = arrival_times[i+1] - arrival_times[i]
delta = delta.to_i
if( delta < 0)
delta *= -1
delta = @@seconds_in_a_day - delta
end
new_note_event( @base_note + index, @note_length, track,127, delta - @note_length )
end
end
return @seq
end
def getSingleTrackMidiSequence
# Generate a multi track sequence
multi_track_seq = getMultipleTrackMidiSequence
if multi_track_seq.nil?
return
end
# Take the multitrack sequence, and merge it down.
single_track_seq = Sequence.new()
single_track_seq.ppqn = @@ppqn
track = Track.new( single_track_seq )
multi_track_seq.tracks.each do |other_track|
track.merge other_track.events
end
single_track_seq.tracks << track
@seq = single_track_seq
return @seq
end
def new_note_event(note, note_length, track,velocity, delta)
channel = 0
track.events << NoteOnEvent.new(channel, note, velocity, delta)
track.events << NoteOffEvent.new(channel, note, velocity, @note_length)
end
end
# command line options
options = {}
optparse = OptionParser.new do|opts|
# Set a banner, displayed at the top
# of the help screen.
opts.banner = "Usage: octransmid.rb [options] stopNumber1 stopNumber2 ..."
# Define the options, and what they do
options[:multitrack] = false
opts.on( '-mt', 'Outputs as multitrack' ) do
options[:multitrack] = true
end
end
# parse the options out.
optparse.parse!
# generate a midi file for each stop specified
ARGV.each do|stop_num|
puts "Generating midi file for stop #" << stop_num
transmid = OCTransmid.new( stop_num, options)
transmid.exportToMidi
end