smml 0.1.0.1 → 0.1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README_smml.md +13 -4
- data/bin/mmlsmml +4 -2
- data/lib/smml/msm.rb +118 -21
- data/lib/smml/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5502e954b9a84c81d1589125b9c6bff866c7a47c
|
4
|
+
data.tar.gz: 7a54373e442e7d92e5200fd699bd99cbddff5118
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3724df4add3c3d66ac9cc733149a5762bf8e899d0bf28e673d4d01b066b529d72ed612f77cca459612ea5ee06df9bd2d3669f0668fcc2f3320ac318108624117
|
7
|
+
data.tar.gz: f65ca001292854935dfd31c15d73d5556d7e4fee703026a864d62760c4fea85b5746b44434239caa49964f0e189fee9e484ec0f18ba648431615cb620a4cf514
|
data/README_smml.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# smml
|
2
2
|
|
3
3
|
simple Music Macro Language to MIDI
|
4
4
|
|
@@ -28,10 +28,19 @@ in a ruby script,
|
|
28
28
|
m=Smml.new
|
29
29
|
m.compile('infile.mml','outfile.mid')
|
30
30
|
|
31
|
-
Or exec command
|
31
|
+
Or exec command.
|
32
|
+
smml to mid (file to mid, mml data to mid, syntax, help)
|
32
33
|
|
33
|
-
$ smml -i infile.mml -o
|
34
|
-
$ smml -d "cdefgab" -o
|
34
|
+
$ smml -i infile.mml -o out.mid
|
35
|
+
$ smml -d "cdefgab" -o out.mid
|
36
|
+
$ smml -s
|
37
|
+
$ smml -h
|
38
|
+
|
39
|
+
mml2smml (file to smml, mml data to smml, mml data to mid)
|
40
|
+
|
41
|
+
$ mmlsmml -i infile.mml > smmlfile
|
42
|
+
$ mmlsmml -d "cdefgab" > smmlfile
|
43
|
+
$ mmlsmml -d "cdefgab" -o out.mid
|
35
44
|
|
36
45
|
## Contributing
|
37
46
|
|
data/bin/mmlsmml
CHANGED
@@ -28,7 +28,7 @@ def help
|
|
28
28
|
end
|
29
29
|
|
30
30
|
infile="infile.mml"
|
31
|
-
outfile="
|
31
|
+
outfile=""
|
32
32
|
data=""
|
33
33
|
|
34
34
|
opt = OptionParser.new
|
@@ -53,7 +53,9 @@ p data
|
|
53
53
|
data=data.split("\n").map{|i|i.commentoff("\n",'#')}*"\n"
|
54
54
|
p data
|
55
55
|
smml=Mml.tosmml(data)
|
56
|
-
puts smml if $smmlshow || $DEBUG
|
56
|
+
puts smml if $smmlshow || $DEBUG || outfile==""
|
57
|
+
exit if outfile==""
|
58
|
+
|
57
59
|
m.octave=:far
|
58
60
|
m.data=smml
|
59
61
|
m.outfile=outfile
|
data/lib/smml/msm.rb
CHANGED
@@ -92,7 +92,12 @@ syntax: ...( will be changed time after time)
|
|
92
92
|
;;;;;; =start mark of multi-line comment. end mark is same or longer mark of ';;'. these must start from the top of line.
|
93
93
|
|
94
94
|
basicaly, one sound is a tone command followed by length number. now, tone type commands are :
|
95
|
-
'c'
|
95
|
+
'c' => single note
|
96
|
+
'(-)d' => single note with flat/sharp modifier
|
97
|
+
'{64}' => single note by absolute note number
|
98
|
+
'_snare!' => drum note by instrument name
|
99
|
+
'{d,g,-b}' => multi note
|
100
|
+
':cmaj7,' => chord name
|
96
101
|
and other commands are with parentheses.
|
97
102
|
EOF
|
98
103
|
end
|
@@ -193,6 +198,22 @@ class Array
|
|
193
198
|
r
|
194
199
|
end
|
195
200
|
end
|
201
|
+
class ScaleNotes < Array
|
202
|
+
def setSampleRate c
|
203
|
+
@samplerate=c
|
204
|
+
end
|
205
|
+
# todo: use sample rate
|
206
|
+
def sample
|
207
|
+
self[rand(self.size)]
|
208
|
+
end
|
209
|
+
def sampleNote
|
210
|
+
if self.size==0
|
211
|
+
rand(0x7f)
|
212
|
+
else
|
213
|
+
self.sample
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
196
217
|
def unirand n,c,reset=false
|
197
218
|
a=[0,n]
|
198
219
|
while c>a.size
|
@@ -202,39 +223,97 @@ def unirand n,c,reset=false
|
|
202
223
|
a.sort_by{rand}
|
203
224
|
end
|
204
225
|
|
226
|
+
# accumulated time with event
|
227
|
+
class TotalTime
|
228
|
+
def initialize t=0
|
229
|
+
@t=t
|
230
|
+
@series={}
|
231
|
+
end
|
232
|
+
def set num,t
|
233
|
+
add(t)
|
234
|
+
@series[num]=@t
|
235
|
+
end
|
236
|
+
def addtime num,t
|
237
|
+
add(t)
|
238
|
+
@series[num]+=t
|
239
|
+
end
|
240
|
+
def add t
|
241
|
+
@t+=t
|
242
|
+
end
|
243
|
+
def get num
|
244
|
+
@series[num]
|
245
|
+
end
|
246
|
+
def all
|
247
|
+
@series
|
248
|
+
end
|
249
|
+
end
|
250
|
+
# midi event etc.
|
205
251
|
class Event
|
206
|
-
|
207
|
-
|
252
|
+
@@counter=0
|
253
|
+
@@tt=TotalTime.new
|
254
|
+
attr_accessor :type, :value
|
255
|
+
attr_reader :time, :number
|
256
|
+
def initialize ty,*arg
|
257
|
+
@number=@@counter
|
258
|
+
@@counter+=1
|
208
259
|
@type=ty
|
209
260
|
@pos=0
|
210
261
|
@value=""
|
211
262
|
case @type
|
212
|
-
|
213
|
-
|
263
|
+
# event without time; except ':e'
|
264
|
+
when :comment,:raw
|
265
|
+
settime(0)
|
214
266
|
@value=arg[0]
|
215
267
|
when :ahead
|
216
|
-
|
217
|
-
when :
|
268
|
+
settime(arg[0])
|
269
|
+
when :on,:off
|
218
270
|
when :mark
|
219
271
|
@mark,@track,@value=arg
|
220
|
-
|
221
|
-
|
272
|
+
# event with delta time; ':e'
|
273
|
+
when :dummy
|
274
|
+
when :e, :end, :sys
|
275
|
+
settime(arg[0])
|
222
276
|
@value=arg[1]
|
277
|
+
else
|
223
278
|
end
|
224
279
|
end
|
280
|
+
def settime t
|
281
|
+
@time=t
|
282
|
+
@@tt.set(@number,@time)
|
283
|
+
posset
|
284
|
+
end
|
285
|
+
def addtime t
|
286
|
+
@time+=t
|
287
|
+
@@tt.addtime(@number,t)
|
288
|
+
posset
|
289
|
+
end
|
290
|
+
def posset
|
291
|
+
@pos=@@tt.get(@number)
|
292
|
+
end
|
293
|
+
def showTotalTime
|
294
|
+
a=@@tt.all
|
295
|
+
a.keys.sort.map{|k|"#{k}: #{a[k]}"}
|
296
|
+
end
|
297
|
+
def reset
|
298
|
+
@@tt=TotalTime.new
|
299
|
+
end
|
225
300
|
def data
|
226
301
|
case @type
|
227
302
|
when :raw
|
228
303
|
rawdata(@value)
|
229
304
|
when :mark
|
230
305
|
"# marktrack(#{@track}_#{@mark}) [#{@value}]\n"
|
231
|
-
when :
|
306
|
+
when :comment,:on,:off
|
232
307
|
@value
|
233
308
|
else
|
234
309
|
varlenHex(@time)+@value
|
235
310
|
end
|
236
311
|
end
|
312
|
+
def display
|
313
|
+
"#{@pos}(#{@time}) #{@type} => #{@value}"
|
314
|
+
end
|
237
315
|
end
|
316
|
+
|
238
317
|
# arg=[steps],[values]
|
239
318
|
def mymerge span,*arg
|
240
319
|
r=[]
|
@@ -690,7 +769,8 @@ module MidiHex
|
|
690
769
|
@bendrange=2
|
691
770
|
@bendCent=1
|
692
771
|
@pancenter=64
|
693
|
-
@
|
772
|
+
@scalenotes=ScaleNotes.new
|
773
|
+
@prepareSet=[@tbase,@ch,@velocity,@velocityFuzzy,@basekey,@gateRate,@bendrange,@bendCent,@scalenotes]
|
694
774
|
@chmax=15
|
695
775
|
@bendrangemax=127
|
696
776
|
file="midi-programChange-list.txt"
|
@@ -755,7 +835,7 @@ module MidiHex
|
|
755
835
|
@bendCent=8192/@bendrange/100.0 if on
|
756
836
|
end
|
757
837
|
def self.trackPrepare tc=0
|
758
|
-
@tbase,@ch,@velocity,@velocityFuzzy,@basekey,@gateRate,@bendrange,@bendCent=@prepareSet
|
838
|
+
@tbase,@ch,@velocity,@velocityFuzzy,@basekey,@gateRate,@bendrange,@bendCent,@scalenotes=@prepareSet
|
759
839
|
@strokespeed=0
|
760
840
|
@preGate=[]
|
761
841
|
@preVelocity=[]
|
@@ -768,6 +848,7 @@ module MidiHex
|
|
768
848
|
tc=@chmax if tc>@chmax
|
769
849
|
@panoftrack=panbytrack(tc)
|
770
850
|
@ch=tc
|
851
|
+
Event.new(:dummy).reset
|
771
852
|
end
|
772
853
|
def self.header format,track,tbase=@tbase
|
773
854
|
format=[format,0xff].min
|
@@ -808,7 +889,7 @@ module MidiHex
|
|
808
889
|
start=@waitingtime
|
809
890
|
@waitingtime=0
|
810
891
|
@nowtime+=start
|
811
|
-
r=[Event.new(:
|
892
|
+
r=[Event.new(:on)]
|
812
893
|
r<<Event.new(:e,start," 9#{ch} #{key} #{vel} # #{start}後, sound on only , note #{@key} velocity #{velocity}\n")
|
813
894
|
r
|
814
895
|
end
|
@@ -874,6 +955,10 @@ module MidiHex
|
|
874
955
|
def self.dummyNote key,len,accent=false,sharp=0
|
875
956
|
vel=@velocity
|
876
957
|
vel+=@accentPlus
|
958
|
+
if key=="?"
|
959
|
+
key=rand(0x7f)
|
960
|
+
key=self.note2key(@scalenotes.sample) if @scalenotes.size>0
|
961
|
+
end
|
877
962
|
key=@preNote.shift if @preNote.size>0
|
878
963
|
len=@preLength.shift if @preLength.size>0
|
879
964
|
self.oneNote(len,key,vel,sharp)
|
@@ -1299,6 +1384,12 @@ module MidiHex
|
|
1299
1384
|
@chordCenter=[[0,@chordCenter].max,0x7f].min
|
1300
1385
|
@firstchordbase=@chordCenter
|
1301
1386
|
end
|
1387
|
+
def self.scale s
|
1388
|
+
s=s.split(",")
|
1389
|
+
s.each{|i|
|
1390
|
+
@scalenotes<<i
|
1391
|
+
}
|
1392
|
+
end
|
1302
1393
|
def self.preLength v
|
1303
1394
|
@preLength=v.map{|i|
|
1304
1395
|
case i
|
@@ -1391,11 +1482,12 @@ module MidiHex
|
|
1391
1482
|
Event.new(:mark,m,@tracknum,@nowtime)
|
1392
1483
|
end
|
1393
1484
|
def self.eventlist2str elist
|
1394
|
-
|
1485
|
+
@eventlist=[]
|
1486
|
+
r=@eventlist
|
1395
1487
|
# EventList : [func,args] or [callonly, func,args] or others
|
1396
1488
|
elist.each{|h|
|
1397
1489
|
cmd,*arg=h
|
1398
|
-
r<<Event.new(:
|
1490
|
+
r<<Event.new(:comment,"# #{cmd} #{arg}")
|
1399
1491
|
case cmd
|
1400
1492
|
when :basekeyPlus
|
1401
1493
|
@basekey+=arg[0]
|
@@ -1434,6 +1526,7 @@ module MidiHex
|
|
1434
1526
|
if i.class==String
|
1435
1527
|
rr<<i
|
1436
1528
|
else
|
1529
|
+
# Event class
|
1437
1530
|
case i.type
|
1438
1531
|
when :ahead
|
1439
1532
|
ahead=i.time
|
@@ -1442,16 +1535,16 @@ module MidiHex
|
|
1442
1535
|
n-=1 until (rr[n].time>0) || n<-10
|
1443
1536
|
if n>-10
|
1444
1537
|
ahead=[ahead,-rr[n].time].max
|
1445
|
-
rr[n].
|
1538
|
+
rr[n].addtime(ahead)
|
1446
1539
|
after=-ahead
|
1447
1540
|
else
|
1448
1541
|
after=0
|
1449
1542
|
end
|
1450
1543
|
when :end,:e,:sys
|
1451
|
-
(i.
|
1452
|
-
(i.
|
1544
|
+
(i.addtime(after);after=0) if after>0
|
1545
|
+
(i.addtime(after);after=0) if after<0 && i.time+after>=0
|
1453
1546
|
rr<<i
|
1454
|
-
when :
|
1547
|
+
when :comment,:raw,:mark
|
1455
1548
|
rr<<i
|
1456
1549
|
else
|
1457
1550
|
"? #{i}"
|
@@ -1483,7 +1576,7 @@ module MidiHex
|
|
1483
1576
|
@h<<[:controlChange,"10,#{@panoftrack}"] if @autopan
|
1484
1577
|
cmd=rundata.scan(/&\([^)]+\)|\([-+]*[[:digit:]]?\)|:[^\(,]+\([^\)\(]+\),|:[^,]+,|\([^:]*:[^)\(]*\)|_[^!_]+!|_[^_]__[^\?]+\?|v[[:digit:]]+|[<>][[:digit:]]*|\*?[[:digit:]]+\.[[:digit:]]+|\*?[[:digit:]]+|[-+[:alpha:]]|\^|`|'|./)
|
1485
1578
|
cmd<<" " # dummy
|
1486
|
-
p "
|
1579
|
+
p "track hex; start making: ",cmd if $DEBUG
|
1487
1580
|
cmd.each{|i|
|
1488
1581
|
if wait.size>0
|
1489
1582
|
t=@tbase
|
@@ -1657,6 +1750,8 @@ module MidiHex
|
|
1657
1750
|
@h<<[:soundOn,i]
|
1658
1751
|
when /^\(off:(.*)\)/
|
1659
1752
|
@h<<[:soundOff,$1]
|
1753
|
+
when /^\(scale:(.*)\)/
|
1754
|
+
@h<<[:call,:scale,$1]
|
1660
1755
|
when /^\(chordcenter:(.*)\)/
|
1661
1756
|
@h<<[:call,:chordCenter,$1]
|
1662
1757
|
when /^\(stroke:(.*)\)/
|
@@ -1722,7 +1817,7 @@ module MidiHex
|
|
1722
1817
|
wait<<[:dummyNote,i]
|
1723
1818
|
when " "
|
1724
1819
|
when "?"
|
1725
|
-
wait<<[:
|
1820
|
+
wait<<[:dummyNote,"?"]
|
1726
1821
|
else
|
1727
1822
|
if @notes.keys.member?(i)
|
1728
1823
|
wait<<[:sound,i]
|
@@ -1734,6 +1829,7 @@ module MidiHex
|
|
1734
1829
|
p @h if $DEBUG
|
1735
1830
|
puts "float rest add times: #{@frestc}" if $DEBUG
|
1736
1831
|
@h=self.eventlist2str(@h)
|
1832
|
+
p [:number_with_totaltime, Event.new(:dummy).showTotalTime],[:allevent,@eventlist.map{|i|i.display}] if $DEBUG && $debuglevel>2
|
1737
1833
|
@h*"\n# track: #{@tracknum} ==== \n"
|
1738
1834
|
end
|
1739
1835
|
def self.loadMap file, base=0
|
@@ -1840,6 +1936,7 @@ module MidiHex
|
|
1840
1936
|
@snare=self.percussionGet("snare")
|
1841
1937
|
end
|
1842
1938
|
end
|
1939
|
+
# substitute mark comment lines with shift delta time and dummy event hex data to adjust to most preceding track.
|
1843
1940
|
def self.trackMake data
|
1844
1941
|
@marksh||=@marktrack.calc
|
1845
1942
|
data=data.split("\n").map{|i|
|
data/lib/smml/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tabasano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|