Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Ruby_Scripts/200.commands.rb

Parent Directory Parent Directory | Revision Log Revision Log


Revision 205 - (show annotations) (download)
Sat Jul 23 11:31:56 2022 UTC (22 months ago) by toshinagata1964
File size: 9646 byte(s)
Create tremolo command is implemented
1 # Copyright (c) 2010-2017 Toshi Nagata. All rights reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation version 2 of the License.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11
12 class Sequence
13
14 def change_control_number_ext
15 hash = Dialog.run {
16 layout(1,
17 layout(2,
18 item(:text, :title=>"Old control Number"),
19 item(:textfield, :width=>40, :range=>[0, 127], :tag=>"old"),
20 item(:text, :title=>"New control number"),
21 item(:textfield, :width=>40, :range=>[0, 127], :tag=>"new")),
22 item(:checkbox, :title=>"Change only editable tracks", :tag=>"editable_only"),
23 item(:checkbox, :title=>"Change only selected events", :tag=>"selection_only"))
24 }
25 if hash[:status] == 0
26 old = hash["old"].to_i
27 new = hash["new"].to_i
28 editable_only = hash["editable_only"]
29 selection_only = hash["selection_only"]
30 puts "old = #{old}, new = #{new}, editable_only = #{editable_only}"
31 each_track { |tr|
32 next if editable_only != 0 && !tr.editable?
33 tr.send(selection_only != 0 ? :each_selected : :each) { |p|
34 if p.kind == :control && p.code == old
35 p.code = new
36 end
37 }
38 }
39 end
40 end
41
42 def change_timebase
43 timebase = self.timebase
44 hash = Dialog.run("Change Timebase") {
45 layout(1,
46 layout(2,
47 item(:text, :title=>"Current timebase = #{timebase}"),
48 nil,
49 item(:text, :title=>"New timebase"),
50 item(:textfield, :width=>40, :range=>[24, 960], :tag=>"new")))
51 }
52 # p hash
53 if hash[:status] == 0
54 new = hash["new"].to_f
55 mult = new / timebase
56 each_track { |tr|
57 set1 = tr.all_events
58 set2 = tr.eventset { |p| p.kind == :note }
59 set2.modify_duration("*", mult)
60 set1.modify_tick("*", mult)
61 }
62 self.set_timebase(new)
63 end
64 end
65
66 def randomize_ticks
67 wd = (get_global_settings("randomize_tick_width") || "10").to_f
68 if !self.has_selection
69 message_box("No events are selected.", "Error", :ok);
70 return
71 end
72 hash = Dialog.run("Randomize Ticks") {
73 layout(1,
74 layout(1,
75 item(:text, :title=>"Randomize width (in milliseconds, 10-1000)"),
76 item(:textfield, :width=>40, :value=>wd.to_s, :range=>[10, 1000], :tag=>"width")))
77 }
78 if hash[:status] == 0
79 wd = hash["width"].to_f
80 set_global_settings("randomize_tick_width", wd.to_s)
81 each_track { |tr|
82 s = tr.selection
83 t = []
84 s.each { |p|
85 t1 = self.tick_to_time(p.tick)
86 t2 = t1 + (rand() - 0.5) * wd / 1000.0
87 t.push(Integer(self.time_to_tick(t2)))
88 }
89 s.modify_tick(t)
90 }
91 end
92 end
93
94 def thin_events
95 info = []
96 nev = 0
97 interval = (get_global_settings("thin_event_interval") || "10").to_f
98 self.each_editable_track { |tr|
99 sel = tr.selection
100 if sel == nil || sel.count == 0
101 next
102 end
103 pt = tr.pointer(sel[0])
104 info.push([tr, pt, 0, sel, nil])
105 nev += sel.count
106 }
107 if info.count == 0
108 message_box("No events are selected", "Cannot process events", :ok, :error)
109 return
110 end
111 # Check the event kind
112 typ = nil # Control: 0 to 127, Pitch bend: 128
113 info.each { |ip|
114 ip[3].each { |pt|
115 if pt.kind == :control
116 t = pt.code
117 elsif pt.kind == :pitch_bend
118 t = 128
119 else
120 message_box("Only control and pitch bend events can be processed.", "Cannot process events", :ok, :error)
121 return
122 end
123 if typ == nil
124 typ = t
125 elsif typ != t
126 message_box("All events must be the same type", "Cannot process events", :ok, :error)
127 return
128 end
129 }
130 }
131 msg = "#{nev} events (" + (typ == 128 ? "Pitch bend" : "Control #{typ}") + ") found in #{info.count} track#{info.count > 1 ? "s" : ""}."
132 hash = Dialog.run("Thin Events") {
133 layout(1,
134 item(:text, :title=>msg),
135 layout(1,
136 item(:text, :title=>"Minimum event interval (in milliseconds, 10-1000)"),
137 item(:textfield, :width=>40, :value=>interval.to_s, :range=>[10, 1000], :tag=>"interval")))
138 }
139 return if hash[:status] != 0
140 interval = hash["interval"].to_f
141 set_global_settings("thin_event_interval", interval.to_s)
142 next_tick = nil
143 while true
144 # Look for the earliest event
145 ip = info.min_by { |ip0| ip0[1].selected? ? ip0[1].tick : 0x7fffffff }
146 pt = ip[1]
147 break if !pt.selected? # All events are processed
148 next_tick ||= pt.tick
149 if ip[4] == nil || pt.tick >= next_tick
150 ip[4] ||= []
151 new_tick = pt.tick
152 new_data = pt.data
153 pt.next_in_selection
154 else
155 while pt.next_in_selection && pt.tick < next_tick
156 end
157 if pt.selected?
158 if pt.tick == next_tick
159 new_tick = pt.tick
160 new_data = pt.data
161 pt.next_in_selection
162 else
163 # ip[4] is not empty, so we should have ip[4][-2]
164 # Interpolate the data value
165 old_tick = ip[4][-2]
166 old_data = ip[4][-1]
167 val = Float(pt.data - old_data) / (pt.tick - old_tick) * (next_tick - old_tick) + old_data
168 new_tick = next_tick
169 new_data = val # val is left as float
170 end
171 else
172 pt.last_in_selection
173 new_tick = pt.tick
174 new_data = pt.data
175 pt.next_in_selection
176 end
177 end
178 if ip[4].count > 0
179 old_data = ip[4][-1]
180 if old_data.to_i == new_data.to_i
181 new_tick = nil # Skip this event
182 end
183 end
184 if new_tick
185 ip[4].push(new_tick, new_data)
186 end
187 next_tick = self.time_to_tick(self.tick_to_time(next_tick) + interval / 1000.0)
188 end
189 nev_new = 0
190 info.each { |ip|
191 ntr = Track.new
192 (ip[4].count / 2).times { |i|
193 tick = ip[4][i * 2]
194 val = ip[4][i * 2 + 1].to_i
195 if typ == 128
196 ntr.add(tick, :pitch_bend, val)
197 else
198 ntr.add(tick, :control, typ, val)
199 end
200 }
201 ip[0].cut(ip[3])
202 ip[0].merge(ntr)
203 nev_new += ntr.nevents
204 }
205 message_box("#{nev} events were replaced with #{nev_new} events.", "", :ok)
206 end
207
208 @@tremolo_len = "60"
209 @@tremolo_len2 = "90"
210 @@tremolo_accel = "4"
211 @@tremolo_ofs = "1"
212 @@tremolo_fluct = "10"
213
214 def create_tremolo
215 values = [@@tremolo_len, @@tremolo_len2, @@tremolo_accel, @@tremolo_ofs, @@tremolo_fluct]
216 hash = Dialog.run("Create Tremolo") {
217 layout(1,
218 layout(2,
219 item(:text, :title=>"Note length (ms)"),
220 item(:textfield, :width=>40, :tag=>"len", :value=>values[0]),
221 item(:text, :title=>"First note length (ms)"),
222 item(:textfield, :width=>40, :tag=>"len2", :value=>values[1]),
223 item(:text, :title=>"Accelerate count"),
224 item(:textfield, :width=>40, :tag=>"accel", :value=>values[2]),
225 item(:text, :title=>"Note offset"),
226 item(:textfield, :width=>40, :tag=>"ofs", :value=>values[3]),
227 item(:text, :title=>"Length fluctuate (%)"),
228 item(:textfield, :width=>40, :tag=>"fluct", :value=>values[4])))
229 }
230 # p hash
231 if hash[:status] == 0
232 len = hash["len"].to_f / 1000
233 len2 = hash["len2"].to_f / 1000
234 if len2 == 0.0
235 len2 = len
236 end
237 accel = hash["accel"].to_i
238 ofs = hash["ofs"].to_i
239 fluct = hash["fluct"].to_f / 100.0
240 if fluct < 0.0
241 fluct = 0.0
242 elsif fluct >= 1.0
243 fluct = 1.0
244 end
245 @@tremolo_len = hash["len"]
246 @@tremolo_len2 = hash["len2"]
247 @@tremolo_accel = hash["accel"]
248 @@tremolo_ofs = hash["ofs"]
249 @@tremolo_fluct = hash["fluct"]
250 if accel <= 0
251 r = 1.0
252 else
253 r = (len / len2) ** (1.0 / accel)
254 end
255 each_track { |tr|
256 next if tr.selection.length == 0
257 trnew = Track.new
258 tr.each_selected { |p|
259 next if p.kind != :note
260 stick = p.tick
261 etick = p.tick + p.duration
262 vel = p.velocity
263 ctick = stick # Start tick of next note
264 code = p.code # Key number of next note
265 clen = len2 # Length of next note
266 n = 0 # Note count
267 while (ctick < etick)
268 ntick = time_to_tick(tick_to_time(ctick) + clen * (1 + (rand - 0.5) * fluct * 2))
269 if ntick < ctick + 5
270 ntick = ctick + 5
271 end
272 break if ntick >= etick
273 cvel = vel * (1 + (rand - 0.5) * fluct * 2)
274 c = (code < 0 ? 0 : (code > 127 ? 127 : code))
275 trnew.add(ctick, c, ntick - ctick, cvel)
276 ctick = ntick
277 if n < accel
278 clen = clen * r
279 else
280 clen = len
281 end
282 if n % 2 == 0
283 code = code + ofs
284 else
285 code = code - ofs
286 end
287 n = n + 1
288 end
289 }
290 tr.cut(tr.selection)
291 tr.merge(trnew)
292 }
293 end
294 end
295
296 end
297
298 register_menu("Change Timebase...", :change_timebase)
299 register_menu("Randomize Ticks...", :randomize_ticks, 1)
300 register_menu("Thin Selected Events...", :thin_events, 1)
301 register_menu("Create tremolo...", :create_tremolo, 1)

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26