Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 205 - (hide annotations) (download)
Sat Jul 23 11:31:56 2022 UTC (20 months, 2 weeks ago) by toshinagata1964
File size: 9646 byte(s)
Create tremolo command is implemented
1 toshinagata1964 73 # Copyright (c) 2010-2017 Toshi Nagata. All rights reserved.
2 toshinagata1964 4 #
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 toshinagata1964 36 hash = Dialog.run {
16 toshinagata1964 4 layout(1,
17     layout(2,
18 toshinagata1964 74 item(:text, :title=>"Old control Number"),
19 toshinagata1964 4 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 toshinagata1964 114 if hash[:status] == 0
26     old = hash["old"].to_i
27     new = hash["new"].to_i
28 toshinagata1964 4 editable_only = hash["editable_only"]
29     selection_only = hash["selection_only"]
30 toshinagata1964 114 puts "old = #{old}, new = #{new}, editable_only = #{editable_only}"
31 toshinagata1964 4 each_track { |tr|
32 toshinagata1964 114 next if editable_only != 0 && !tr.editable?
33     tr.send(selection_only != 0 ? :each_selected : :each) { |p|
34 toshinagata1964 4 if p.kind == :control && p.code == old
35     p.code = new
36     end
37     }
38     }
39     end
40     end
41    
42 toshinagata1964 74 def change_timebase
43     timebase = self.timebase
44 toshinagata1964 80 hash = Dialog.run("Change Timebase") {
45 toshinagata1964 74 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 toshinagata1964 80 # p hash
53 toshinagata1964 74 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 toshinagata1964 4 end
65    
66 toshinagata1964 80 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 toshinagata1964 78 }
78 toshinagata1964 80 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 toshinagata1964 74 end
93    
94 toshinagata1964 82 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 toshinagata1964 78 end
207    
208 toshinagata1964 205 @@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 toshinagata1964 82 end
295    
296 toshinagata1964 205 end
297    
298 toshinagata1964 114 register_menu("Change Timebase...", :change_timebase)
299     register_menu("Randomize Ticks...", :randomize_ticks, 1)
300     register_menu("Thin Selected Events...", :thin_events, 1)
301 toshinagata1964 205 register_menu("Create tremolo...", :create_tremolo, 1)

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