smml 0.1.6 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/smml/msm.rb +207 -66
- data/lib/smml/version.rb +1 -1
- data/sample/midi-preModifier.txt +1 -1
- data/{bin/ssmml → sample/ssmml.rb} +0 -0
- data/smml.gemspec +1 -1
- data/tutorial_smml.md +61 -16
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2a5f8a92f538689c4376fde815e064a7d4887ec
|
4
|
+
data.tar.gz: cb84d1b91997d306b5de5bbdb4033c3a01e0a1ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d31c883cdba860e6dc39175eccad5d8ce55cfe95c31fba806042473ae9e5dff29bf3506f8b6c762c62d75fba36b6cfa20b56c257700e03b11fe4fe36d711fd95
|
7
|
+
data.tar.gz: 14dff95b8b0cdf6c81eedb3fa284cb16c9e0d9ed7250022b0eb0928e4c626f68849e1c6614c27896197e4a5825ce6856e8806b87adbe4b2f3e66df2d578ad589
|
data/lib/smml/msm.rb
CHANGED
@@ -7,7 +7,7 @@ $debuglevel=0
|
|
7
7
|
|
8
8
|
# as gem or this file only
|
9
9
|
def version
|
10
|
-
if defined?(Smml) && ( Smml.constants.member?("VERSION") || Smml.constants.member?(
|
10
|
+
if defined?(Smml) && ( Smml.constants.member?("VERSION") || Smml.constants.member?(:VERSION) )
|
11
11
|
Smml::VERSION
|
12
12
|
else
|
13
13
|
File.mtime(__FILE__).strftime("%Y-%m-%d")
|
@@ -170,14 +170,14 @@ end
|
|
170
170
|
|
171
171
|
#===========================================================
|
172
172
|
module MmlReg
|
173
|
-
def self.r key, sort=true
|
173
|
+
def self.r key, sort=true, pre=""
|
174
174
|
raise if sort.class==Symbol
|
175
175
|
case key
|
176
176
|
when Array
|
177
177
|
raise if (key-@@keys).size>0
|
178
178
|
ks=key
|
179
179
|
ks=(@@keys-(@@keys-ks)) if sort
|
180
|
-
ks.map{|i
|
180
|
+
ks.map{|i|"#{pre}#{@@h[i]}"}*"|"
|
181
181
|
else
|
182
182
|
@@h[key]
|
183
183
|
end
|
@@ -185,13 +185,24 @@ module MmlReg
|
|
185
185
|
puts "Regex part,arg bug",[key-@@keys]
|
186
186
|
raise
|
187
187
|
end
|
188
|
+
def self.rPlusPre key, pre, sort=true
|
189
|
+
self.r(key,sort,pre)
|
190
|
+
end
|
188
191
|
def self.trackr
|
189
|
-
self.r([:hexraw,:
|
192
|
+
self.r([:hexraw,:sharp,:chord,:word,:sound,:modifier,:velocity,:tempo,:num,:octave,:note,:mod,:note?,:sound?])
|
193
|
+
end
|
194
|
+
def self.multipletr
|
195
|
+
self.r([:word,:note,:sound,:chord,:num,:sharp,:octave,:mod])
|
196
|
+
end
|
197
|
+
def self.macroDefr
|
198
|
+
self::MacroDef
|
199
|
+
end
|
200
|
+
def self.repeatr
|
201
|
+
self.r([:repStart,:repEnd,:repmark])
|
190
202
|
end
|
191
203
|
@@h={} # mml regex key hash. order is in @@keys
|
192
204
|
@@keys=[
|
193
205
|
:comment,
|
194
|
-
:keyword,
|
195
206
|
:macrodefAStart,
|
196
207
|
:macrodefA,
|
197
208
|
:macrodefStart,
|
@@ -208,13 +219,12 @@ module MmlReg
|
|
208
219
|
:repEnd,
|
209
220
|
:word,
|
210
221
|
:modifier,
|
211
|
-
:
|
222
|
+
:sharp,
|
212
223
|
:wordStart,
|
213
224
|
:word?,
|
214
225
|
:chord,
|
215
226
|
:velocity,
|
216
227
|
:sound,
|
217
|
-
:DCmark,
|
218
228
|
:tempo,
|
219
229
|
:mod,
|
220
230
|
:octave,
|
@@ -233,12 +243,15 @@ module MmlReg
|
|
233
243
|
:sound?,
|
234
244
|
:plusMinus,
|
235
245
|
:lineSep,
|
246
|
+
:repmark,
|
247
|
+
:DCmark?,
|
236
248
|
:chord?,
|
237
249
|
]
|
250
|
+
@@h[:repmark]="\\.FINE|\\.DS|\\.DC|\\.\\$|\\.toCODA|\\.CODA|\\.SKIP"
|
238
251
|
@@h[:comment]="\\( *comment[^\(\)]*\\)"
|
239
252
|
@@h[:word]="\\([^\(\):]*:[^\(\)]*\\)"
|
240
253
|
@@h[:wordStart]="\\([^\(\):]*:"
|
241
|
-
@@h[:
|
254
|
+
@@h[:sharp]="\\([+-]*[[:digit:]\\.]*\\)"
|
242
255
|
@@h[:word?]="\\([^\(\)]*\\)"
|
243
256
|
@@h[:chord]="\\{[^\{\}]+,[^\{\},]+\\}|:[[:alpha:]][[:alnum:]]*,"
|
244
257
|
@@h[:velocity]="v[[:digit:]]+"
|
@@ -248,7 +261,7 @@ module MmlReg
|
|
248
261
|
@@h[:randNote]="\\?"
|
249
262
|
@@h[:sound]="_[^!]+!|=|~"
|
250
263
|
@@h[:sound?]="[[:alpha:]]"
|
251
|
-
@@h[:DCmark]="
|
264
|
+
@@h[:DCmark?]="\\.[[:alpha:]]+"
|
252
265
|
@@h[:tempo]="[><][[:digit:]]*"
|
253
266
|
@@h[:mod]="[`'^]"
|
254
267
|
@@h[:octave]= "[+-][[:digit:]]*"
|
@@ -262,13 +275,12 @@ module MmlReg
|
|
262
275
|
@@h[:num]="[-+*]?[[:digit:]]+\\.[[:digit:]]+|[-+*]?[[:digit:]]+"
|
263
276
|
@@h[:hexraw]="&\\([^()]*\\)"
|
264
277
|
@@h[:hexrawStart]="&\\("
|
265
|
-
@@h[:keyword]="macro +"
|
266
278
|
@@h[:macroA]="\\$\\{[^}]+\\}\\[[^\\]]+\\]|\\$[^}\\$\\{\\(\\)]+\\[[^\\]]+\\]"
|
267
279
|
@@h[:macro]="\\$[[:alnum:]]+\\([^)]*\\)|\\$[[:alnum:]]+|\\$\\{[^}]+\\}"
|
268
|
-
@@h[:macrodefAStart]="[[:alnum:]]+\\([,[:alpha:]]+\\):= *\\(
|
269
|
-
@@h[:macrodefA]= "[[:alnum:]]+\\([,[:alpha:]]+\\):= *[^\\n]
|
270
|
-
@@h[:macrodefStart]="[[:alnum:]]+:= *\\(
|
271
|
-
@@h[:macrodef]= "[[:alnum:]]+:= *[^\\n]+"
|
280
|
+
@@h[:macrodefAStart]="[[:alnum:]]+\\([,[:alpha:]]+\\):= *\\( *[;\\z]"
|
281
|
+
@@h[:macrodefA]= "[[:alnum:]]+\\([,[:alpha:]]+\\):= *[^\\(;\\n][^;\\n]*"
|
282
|
+
@@h[:macrodefStart]="[[:alnum:]]+:= *\\( *[;\\z]"
|
283
|
+
@@h[:macrodef]= "[[:alnum:]]+:= *[^\\(;\\n][^;\\n]+"
|
272
284
|
@@h[:blank]="[[:blank:]]+"
|
273
285
|
@@h[:valueSep]=","
|
274
286
|
@@h[:parenStart]="\\("
|
@@ -281,7 +293,9 @@ module MmlReg
|
|
281
293
|
@@h[:modifier]="_[^_]__[^\\?]+\\?"
|
282
294
|
r=self.r(@@keys)
|
283
295
|
RwAll=/#{r}|./
|
284
|
-
MacroDef=self.
|
296
|
+
MacroDef=self.rPlusPre([:macrodefAStart,:macrodefStart,:macrodefA,:macrodef],"macro *")+"|"+
|
297
|
+
self.r([:macrodefAStart,:macrodefStart,:macrodefA,:macrodef])
|
298
|
+
RepStrArray=["[","]",".CODA",".DS",".DC",".FINE",".toCODA",".$",".SKIP"]
|
285
299
|
ArgIsOne=%w[ bendCent mark p gm gs xg loadf text ]
|
286
300
|
def self.event m,rest=[]
|
287
301
|
((@@keys-rest).map{|k|m=~/\A#{@@h[k]}\z/ ? k : nil}-[nil])[0]
|
@@ -628,7 +642,6 @@ end
|
|
628
642
|
def trackSizeHex d,cmark="#"
|
629
643
|
d=d.commentoff("",cmark).split.join
|
630
644
|
i=(d.size+8)/2
|
631
|
-
# p [d,i,i.to_s(16)]
|
632
645
|
#("00000000"+i.to_s(16))[-8..-1]
|
633
646
|
format("%08x",i)+" # size: #{i}"
|
634
647
|
end
|
@@ -708,8 +721,8 @@ def txt2hex t
|
|
708
721
|
[r*" ",varlenHex(size)]
|
709
722
|
end
|
710
723
|
def bendHex d
|
711
|
-
c=d.to_i+
|
712
|
-
c=[[c,0].max,
|
724
|
+
c=d.to_i+MidiHex::BendHalf
|
725
|
+
c=[[c,0].max,MidiHex::BendMax].min
|
713
726
|
a=c>>7
|
714
727
|
b=c & 0b01111111
|
715
728
|
r=[a,b,b*0x100+a]
|
@@ -816,7 +829,7 @@ def worddata word,d
|
|
816
829
|
depth=$3.split(',').map{|i|
|
817
830
|
case i
|
818
831
|
when "+","-" ; i
|
819
|
-
else ; i
|
832
|
+
else ; i
|
820
833
|
end
|
821
834
|
}
|
822
835
|
[:"#{word}",pos,depth]
|
@@ -1012,9 +1025,12 @@ def guitarTuning
|
|
1012
1025
|
%W[-e -a d g b +e]
|
1013
1026
|
end
|
1014
1027
|
module MidiHex
|
1028
|
+
BendMax=16383
|
1029
|
+
BendHalf=8192
|
1015
1030
|
# 設定のため最初に呼ばなければならない
|
1016
1031
|
def self.prepare bpm=120,tbase=480,vel=0x40,oct=:near,vfuzzy=2,strict=false
|
1017
1032
|
@ready=true
|
1033
|
+
@bendHalfMax=BendHalf
|
1018
1034
|
@strictmode=strict
|
1019
1035
|
@autopan= strict ? false : true
|
1020
1036
|
@strokefaster= strict ? 1 : 3
|
@@ -1033,7 +1049,9 @@ module MidiHex
|
|
1033
1049
|
@rythmChannel=9
|
1034
1050
|
@notes=Notes.new
|
1035
1051
|
@ch=0
|
1036
|
-
@
|
1052
|
+
@expressionRest=0x60
|
1053
|
+
@expressionDef=0x7f
|
1054
|
+
@expression=@expressionDef
|
1037
1055
|
@velocity=vel
|
1038
1056
|
@velocityOrg=vel
|
1039
1057
|
@velocityFuzzy=vfuzzy
|
@@ -1046,7 +1064,7 @@ module MidiHex
|
|
1046
1064
|
@pancenter=64
|
1047
1065
|
@scalenotes=ScaleNotes.new.reset
|
1048
1066
|
@gtune=guitarTuning
|
1049
|
-
|
1067
|
+
self.setDefault
|
1050
1068
|
@chmax=15
|
1051
1069
|
@bendrangemax=127
|
1052
1070
|
file="midi-programChange-list.txt"
|
@@ -1058,6 +1076,15 @@ module MidiHex
|
|
1058
1076
|
self.loadPercussionMap(pfile)
|
1059
1077
|
self.dumpstatus if $DEBUG && $debuglevel>3
|
1060
1078
|
end
|
1079
|
+
def self.setDefault
|
1080
|
+
@prepareSet=[
|
1081
|
+
@tbase,@ch,@velocity,@expression,@velocityFuzzy,@basekey,@gateRate,@bendrange,@bendCent,@scalenotes,@gtune,@expressionRest,@expressionDef
|
1082
|
+
]
|
1083
|
+
end
|
1084
|
+
def self.getDefault
|
1085
|
+
@tbase,@ch,@velocity,@expression,@velocityFuzzy,@basekey,@gateRate,@bendrange,@bendCent,@scalenotes,@gtune,@expressionRest,@expressionDef=
|
1086
|
+
@prepareSet
|
1087
|
+
end
|
1061
1088
|
def self.dumpstatus
|
1062
1089
|
self.instance_variables.each{|i|
|
1063
1090
|
val=self.instance_variable_get(i)
|
@@ -1098,6 +1125,7 @@ module MidiHex
|
|
1098
1125
|
@gateRate=[g,100].min
|
1099
1126
|
end
|
1100
1127
|
def self.bendRange v
|
1128
|
+
@lastbend=0
|
1101
1129
|
case v
|
1102
1130
|
when /^\+/
|
1103
1131
|
@bendrange+=$'.to_i
|
@@ -1115,10 +1143,12 @@ module MidiHex
|
|
1115
1143
|
end
|
1116
1144
|
def self.bendCent on
|
1117
1145
|
@bendCent=1
|
1118
|
-
@bendCent
|
1146
|
+
@bendCent=@bendHalfMax/@bendrange/100.0 if on
|
1147
|
+
@lastbend=0
|
1119
1148
|
end
|
1120
1149
|
def self.trackPrepare tc=0
|
1121
|
-
|
1150
|
+
self.getDefault
|
1151
|
+
@theremin=false
|
1122
1152
|
@strokespeed=0
|
1123
1153
|
@strokeUpDown=1
|
1124
1154
|
@preGate=[]
|
@@ -1195,6 +1225,20 @@ module MidiHex
|
|
1195
1225
|
r<<Event.new(:end,start," 8#{ch} #{key} 00 # #{start} sound off only [#{(@nowtime/@tbase).to_i}, #{@nowtime%@tbase}]\n")
|
1196
1226
|
r
|
1197
1227
|
end
|
1228
|
+
def self.thereminNote pos,key,velocity,ch,exp=@expressionDef
|
1229
|
+
r=[]
|
1230
|
+
@expression=exp
|
1231
|
+
if @expression
|
1232
|
+
r<<self.expre(0,@expression)
|
1233
|
+
end
|
1234
|
+
start=@waitingtime
|
1235
|
+
@waitingtime=0
|
1236
|
+
pos-=start
|
1237
|
+
depth=(key-@thereminNote)*100
|
1238
|
+
r<<self.bend(start,depth.to_s,ch)
|
1239
|
+
r<<self.bend(pos,depth.to_s,ch)
|
1240
|
+
r
|
1241
|
+
end
|
1198
1242
|
def self.oneNote len=@tbase,key=@basekey,velocity=@velocity,ch=@ch,sharp=0
|
1199
1243
|
velocity=@preVelocity.shift if @preVelocity.size>0
|
1200
1244
|
gate=@gateRate
|
@@ -1203,6 +1247,7 @@ module MidiHex
|
|
1203
1247
|
velocity=[velocity,0x7f].min
|
1204
1248
|
key+=sharp
|
1205
1249
|
@key=[[key,0x7f].min,0].max
|
1250
|
+
return self.thereminNote(len,key,velocity,ch) if @theremin
|
1206
1251
|
key=format("%02x",@key)
|
1207
1252
|
ch=format("%01x",ch)
|
1208
1253
|
vel=format("%02x",velocity)
|
@@ -1270,7 +1315,8 @@ module MidiHex
|
|
1270
1315
|
vel+=@accentPlus if accent
|
1271
1316
|
self.oneNote(len,key,vel,@rythmChannel,sharp)
|
1272
1317
|
end
|
1273
|
-
def self.notes c,l=false,accent=false,sharp=0
|
1318
|
+
def self.notes c,l=false,accent=false,sharp=0,sharpFloat=false
|
1319
|
+
@lastnoteName=c
|
1274
1320
|
n=@notes[c]
|
1275
1321
|
if @octmode==:near && n.class != Array
|
1276
1322
|
if @lastnote
|
@@ -1282,7 +1328,17 @@ module MidiHex
|
|
1282
1328
|
(@basekey-=12;@lastnote+=12) if n<0
|
1283
1329
|
n=@lastnote
|
1284
1330
|
end
|
1285
|
-
|
1331
|
+
r=[]
|
1332
|
+
if sharpFloat && sharpFloat!=0
|
1333
|
+
v=sharpFloat*@bendHalfMax
|
1334
|
+
v=sharpFloat*100 if @bendCent>1
|
1335
|
+
r<<self.bend(0,v)
|
1336
|
+
r<<self.notekey(n,l,accent,sharp)
|
1337
|
+
r<<self.bend(0,0)
|
1338
|
+
else
|
1339
|
+
r<<self.notekey(n,l,accent,sharp)
|
1340
|
+
end
|
1341
|
+
r
|
1286
1342
|
end
|
1287
1343
|
def self.shiftChord chord, base, limit=6
|
1288
1344
|
octave=12
|
@@ -1419,12 +1475,19 @@ module MidiHex
|
|
1419
1475
|
chx=format("%01x",ch)
|
1420
1476
|
@nowtime+=len
|
1421
1477
|
r=[]
|
1422
|
-
|
1478
|
+
if @theremin
|
1479
|
+
min=@expressionRest
|
1480
|
+
r<<Event.new(:comment,"# rest; ")
|
1481
|
+
r<<self.expre(0,min)
|
1482
|
+
r<<self.expre(len,min)
|
1483
|
+
else
|
1484
|
+
r<<Event.new(:end,len," 8#{chx} 3C 00 # rest #{len.to_i}(#{len.round(2)})ticks later, off:ch#{ch}, key:3C\n")
|
1485
|
+
end
|
1423
1486
|
r
|
1424
1487
|
end
|
1425
1488
|
def self.restHex len=@tbase,ch=@ch
|
1426
1489
|
r=self.rest(len,ch)
|
1427
|
-
r[0]
|
1490
|
+
r[0]
|
1428
1491
|
end
|
1429
1492
|
# d : hex data
|
1430
1493
|
def self.metaEvent d,type=1
|
@@ -1436,7 +1499,7 @@ module MidiHex
|
|
1436
1499
|
hexd,len=txt2hex(d)
|
1437
1500
|
delta=varlenHex(pos)
|
1438
1501
|
e=self.metaEvent hexd,type
|
1439
|
-
"#{delta} #{e} # #{d}\n"
|
1502
|
+
Event.new(:raw,"#{delta} #{e} # #{d}\n")
|
1440
1503
|
end
|
1441
1504
|
def self.metaTitle d=@title,pos=0
|
1442
1505
|
return "" if not d
|
@@ -1461,7 +1524,7 @@ module MidiHex
|
|
1461
1524
|
delta=varlenHex(pos)
|
1462
1525
|
t=format("%02X",type)
|
1463
1526
|
len=varlenHex(d.split.join.size/2)
|
1464
|
-
"#{delta} FF #{t} #{len} #{d} # #{pos} #{comment}\n"
|
1527
|
+
Event.new(:raw,"#{delta} FF #{t} #{len} #{d} # #{pos} #{comment}\n")
|
1465
1528
|
end
|
1466
1529
|
def self.tempo bpm, len=0
|
1467
1530
|
@bpmStart=bpm if ! @bpm
|
@@ -1611,6 +1674,21 @@ module MidiHex
|
|
1611
1674
|
end
|
1612
1675
|
def self.bend pos,depth,ch=false
|
1613
1676
|
ch=@ch if ! ch
|
1677
|
+
depth.to_s=~/([+-]*)/
|
1678
|
+
sign=$1
|
1679
|
+
plus=false
|
1680
|
+
case sign.size
|
1681
|
+
when 0..1
|
1682
|
+
depth=depth.to_f
|
1683
|
+
plus=true if sign=="+"
|
1684
|
+
when 2
|
1685
|
+
depth=depth[1..-1].to_f
|
1686
|
+
plus=true
|
1687
|
+
else
|
1688
|
+
STDERR.puts "bend: ?"
|
1689
|
+
end
|
1690
|
+
depth=@lastbend+depth if plus
|
1691
|
+
@lastbend=depth
|
1614
1692
|
depth=(depth*@bendCent).to_i
|
1615
1693
|
pos+=@waitingtime
|
1616
1694
|
@waitingtime=0
|
@@ -1805,9 +1883,41 @@ module MidiHex
|
|
1805
1883
|
@strokespeed=s.abs
|
1806
1884
|
end
|
1807
1885
|
end
|
1886
|
+
def self.setTheremin flag
|
1887
|
+
r=[]
|
1888
|
+
if flag
|
1889
|
+
if not @lastnote
|
1890
|
+
@lastnoteName="c"
|
1891
|
+
@lastnote=@notes["c"]
|
1892
|
+
end
|
1893
|
+
@thereminNote=@lastnote+@basekey
|
1894
|
+
r<<self.notes(@lastnoteName,0)
|
1895
|
+
key=format("%02x",@thereminNote)
|
1896
|
+
ch=format("%01x",@ch)
|
1897
|
+
vel=format("%02x",@velocity)
|
1898
|
+
r<<Event.new(:e,0," 9#{ch} #{key} #{vel} # theremin sound on note #{@thereminNote} velocity #{@velocity}\n")
|
1899
|
+
r<<self.bendRange(12*4)
|
1900
|
+
self.bendCent(true)
|
1901
|
+
else
|
1902
|
+
@thereminNote=false
|
1903
|
+
self.bendCent(false)
|
1904
|
+
end
|
1905
|
+
@theremin=flag
|
1906
|
+
r
|
1907
|
+
end
|
1808
1908
|
def self.setmark m
|
1809
|
-
|
1810
|
-
|
1909
|
+
m=~/^([^,]+),/
|
1910
|
+
count=$'.to_i
|
1911
|
+
if $&
|
1912
|
+
if count>1
|
1913
|
+
m="#{$1}@#{$'.to_i}"
|
1914
|
+
else
|
1915
|
+
m=$1
|
1916
|
+
end
|
1917
|
+
else
|
1918
|
+
n=@marktrack.getcount(m,@tracknum)
|
1919
|
+
m="#{m}@#{n+1}" if n>0
|
1920
|
+
end
|
1811
1921
|
@marktrack.set(m,@tracknum,@nowtime)
|
1812
1922
|
Event.new(:mark,m,@tracknum,@nowtime)
|
1813
1923
|
end
|
@@ -1883,14 +1993,8 @@ module MidiHex
|
|
1883
1993
|
end
|
1884
1994
|
end
|
1885
1995
|
}
|
1886
|
-
|
1887
|
-
|
1888
|
-
when String
|
1889
|
-
i
|
1890
|
-
when Event
|
1891
|
-
i.data
|
1892
|
-
end
|
1893
|
-
}
|
1996
|
+
# Array of String or Event class instance
|
1997
|
+
rr
|
1894
1998
|
end
|
1895
1999
|
def self.makefraze mmldata,tc
|
1896
2000
|
return "" if not mmldata
|
@@ -1905,6 +2009,7 @@ module MidiHex
|
|
1905
2009
|
@shiftbase=40
|
1906
2010
|
accent=false
|
1907
2011
|
sharp=0
|
2012
|
+
sharpFloat=0
|
1908
2013
|
@h<<[:controlChange,"10,#{@panoftrack}"] if @autopan
|
1909
2014
|
cmd=mmldata.scan(/#{MmlReg.trackr}|./)
|
1910
2015
|
cmd<<" " # dummy
|
@@ -1930,19 +2035,21 @@ module MidiHex
|
|
1930
2035
|
end
|
1931
2036
|
end
|
1932
2037
|
wait.each{|m,c|
|
2038
|
+
arg=[c,t,accent,sharp]
|
2039
|
+
arg2=[c,t,accent,sharp,sharpFloat]
|
1933
2040
|
case m
|
1934
2041
|
when :percussion
|
1935
|
-
@h<<[:percussionNote
|
2042
|
+
@h<<[:percussionNote,*arg]
|
1936
2043
|
when :rawsound
|
1937
|
-
@h<<[:byKey
|
2044
|
+
@h<<[:byKey,*arg]
|
1938
2045
|
when :sound
|
1939
|
-
@h<<[:notes
|
2046
|
+
@h<<[:notes,*arg2]
|
1940
2047
|
when :dummyNote
|
1941
|
-
@h<<[:dummyNote
|
2048
|
+
@h<<[:dummyNote,*arg]
|
1942
2049
|
when :chord
|
1943
|
-
@h<<[:chord
|
2050
|
+
@h<<[:chord,*arg]
|
1944
2051
|
when :chordName
|
1945
|
-
@h<<[:chordName
|
2052
|
+
@h<<[:chordName,*arg]
|
1946
2053
|
when :rest
|
1947
2054
|
@h<<[:rest,t]
|
1948
2055
|
end
|
@@ -1951,20 +2058,35 @@ module MidiHex
|
|
1951
2058
|
wait=[]
|
1952
2059
|
accent=false
|
1953
2060
|
sharp=0
|
2061
|
+
sharpFloat=0
|
1954
2062
|
end
|
1955
2063
|
case i
|
1956
|
-
when /^\(([-+]*)([[:digit:]])?\)/
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
2064
|
+
when /^\(([-+]*)([[:digit:]\.]+)?\)/
|
2065
|
+
s1,s2=$1,$2
|
2066
|
+
n=1
|
2067
|
+
sharpFloat=0
|
2068
|
+
if s2
|
2069
|
+
n=s2.to_i
|
2070
|
+
if s2=~/\./
|
2071
|
+
sharpFloat=s2.to_f-n
|
2072
|
+
end
|
2073
|
+
end
|
2074
|
+
if s1.size>1
|
2075
|
+
n=s1.size
|
1960
2076
|
end
|
1961
|
-
|
1962
|
-
|
1963
|
-
sharp=
|
2077
|
+
plus=s1 ? s1[0..0] : "+"
|
2078
|
+
sharpFloat*=-1 if plus=="-"
|
2079
|
+
sharp="#{plus}#{n}".to_i
|
1964
2080
|
when /^\(key:(-?)\+?([[:digit:]]+)\)/
|
1965
2081
|
tr=$2.to_i
|
1966
2082
|
tr*=-1 if $1=="-"
|
1967
2083
|
@h<<[:basekeyPlus,tr]
|
2084
|
+
when /^\(theremin:(.*)\)/
|
2085
|
+
if $1=~/off/
|
2086
|
+
@h<<[:setTheremin,false]
|
2087
|
+
else
|
2088
|
+
@h<<[:setTheremin,true]
|
2089
|
+
end
|
1968
2090
|
when /^\(mark:(.*)\)/
|
1969
2091
|
@h<<[:setmark,$1]
|
1970
2092
|
when /^\(V:(.*)\)/
|
@@ -2007,7 +2129,7 @@ module MidiHex
|
|
2007
2129
|
instrument=$4.to_i
|
2008
2130
|
end
|
2009
2131
|
@h<<[:ProgramChange,channel,instrument]
|
2010
|
-
when /^\(bend:(([[:digit:]]+),)?([
|
2132
|
+
when /^\(bend:(([[:digit:]]+),)?([-+,.[:digit:]]+)\)|^_b__([^?]+)\?/
|
2011
2133
|
i="(bend:#{$4.gsub('_'){','}})" if $4
|
2012
2134
|
x,pos,b=worddata("bend",i)
|
2013
2135
|
npos=0
|
@@ -2178,7 +2300,17 @@ module MidiHex
|
|
2178
2300
|
puts "float rest add times: #{@frestc}" if $DEBUG
|
2179
2301
|
@h=self.eventlist2str(@h)
|
2180
2302
|
p [:number_with_totaltime, Event.new(:dummy).showTotalTime],[:allevent,@eventlist.map{|i|i.display}] if $DEBUG && $debuglevel>2
|
2181
|
-
@h
|
2303
|
+
@h
|
2304
|
+
end
|
2305
|
+
def self.eventArray2str data,tc
|
2306
|
+
data.map{|i|
|
2307
|
+
case i
|
2308
|
+
when String
|
2309
|
+
i
|
2310
|
+
when Event
|
2311
|
+
i.data
|
2312
|
+
end
|
2313
|
+
}*"\n# track: #{tc} ==== \n"
|
2182
2314
|
end
|
2183
2315
|
def self.loadMap file, base=0
|
2184
2316
|
if not File.exist?(file)
|
@@ -2285,15 +2417,15 @@ module MidiHex
|
|
2285
2417
|
end
|
2286
2418
|
end
|
2287
2419
|
# substitute mark comment lines with shift delta time and dummy event hex data to adjust to most preceding track.
|
2288
|
-
def self.trackMake data
|
2420
|
+
def self.trackMake data,tc
|
2289
2421
|
@marksh||=@marktrack.calc
|
2290
|
-
data=data.split("\n").map{|i|
|
2422
|
+
data=self.eventArray2str(data,tc).split("\n").map{|i|
|
2291
2423
|
i=~/^# marktrack\(([^\)]+)\)/
|
2292
2424
|
if $&
|
2293
2425
|
key=$1
|
2294
2426
|
pos=@marksh[key]
|
2295
2427
|
c="position mark: #{key}, #{pos*1.0/@tbase}"
|
2296
|
-
@marksh.keys.member?(key) ? self.dummyEvent(c,pos) : i
|
2428
|
+
@marksh.keys.member?(key) ? self.dummyEvent(c,pos).data : i
|
2297
2429
|
else
|
2298
2430
|
i
|
2299
2431
|
end
|
@@ -2323,7 +2455,8 @@ def multiplet d,tbase
|
|
2323
2455
|
else
|
2324
2456
|
total=tbase*rate
|
2325
2457
|
end
|
2326
|
-
|
2458
|
+
regex=MmlReg.multipletr
|
2459
|
+
r=i.scan(/#{regex}|./)
|
2327
2460
|
lengths=[]
|
2328
2461
|
notes=[]
|
2329
2462
|
mod=[]
|
@@ -2406,7 +2539,8 @@ def macroDef data
|
|
2406
2539
|
tmp=[]
|
2407
2540
|
name=""
|
2408
2541
|
num=1
|
2409
|
-
|
2542
|
+
rstr=MmlReg.macroDefr
|
2543
|
+
s=data.scan(/#{rstr}| *\) *;|[^;]+|./)
|
2410
2544
|
data=s.map{|i|
|
2411
2545
|
case i
|
2412
2546
|
when /^(macro +)? *([^ ;:=]+) *:= *\( *;/
|
@@ -2442,7 +2576,7 @@ def macroDef data
|
|
2442
2576
|
end
|
2443
2577
|
def nestsearch d,macro
|
2444
2578
|
a=d.scan(/\[[^\[\]]*\] *[[:digit:]]+/)!=[]
|
2445
|
-
r=d.scan(/\/[^\/]
|
2579
|
+
r=d.scan(/\/[^\/]+\/|#{MmlReg.repeatr}|\$\{[^ \{\}]+\}|\$[^ ;\$*_^`'+-]+|;|./).map{|i|
|
2446
2580
|
case i
|
2447
2581
|
when /^\$\{([^\}]+)\}/
|
2448
2582
|
$1
|
@@ -2466,7 +2600,7 @@ def tie d,tbase
|
|
2466
2600
|
res=[]
|
2467
2601
|
# if no length word after '~' length is 1
|
2468
2602
|
d.gsub!(/~([^*[:digit:]])?/){$1 ? "~1#{$1}" : $&} while d=~/~[^*[:digit:]]/
|
2469
|
-
li=d.scan(
|
2603
|
+
li=d.scan(MmlReg::RwAll)
|
2470
2604
|
li.each{|i|
|
2471
2605
|
case i
|
2472
2606
|
when /^(\*)?([[:digit:].]+)/
|
@@ -2530,7 +2664,8 @@ def repCalc line,macro,tbase
|
|
2530
2664
|
r ? r : b
|
2531
2665
|
end
|
2532
2666
|
}*""
|
2533
|
-
|
2667
|
+
repmark=MmlReg.repeatr
|
2668
|
+
regex=/\/[^\/]+\/|#{repmark}|\$\{[^ \{\}]+\}|\$[^ ;\$_*^,\)\(`'\/+-]+|\([^\)]*:|\)|./
|
2534
2669
|
a=line.scan(regex)
|
2535
2670
|
a=a.map{|i|
|
2536
2671
|
if i=~/^\/[^\/]+\//
|
@@ -2607,7 +2742,7 @@ def repCalc line,macro,tbase
|
|
2607
2742
|
end
|
2608
2743
|
res<<current
|
2609
2744
|
end
|
2610
|
-
res=(res-
|
2745
|
+
res=(res-MmlReg::RepStrArray)*""
|
2611
2746
|
res=repCalc(res,macro,tbase) while macro.keys.size>0 && nestsearch(res,macro)
|
2612
2747
|
p res if $DEBUG && $debuglevel>1
|
2613
2748
|
# 空白
|
@@ -2758,15 +2893,21 @@ class Smml
|
|
2758
2893
|
@mx.autopan(@autopan)
|
2759
2894
|
tc=0
|
2760
2895
|
# remember starting position check if data exist before sound
|
2761
|
-
@htracks
|
2896
|
+
@htracks[tc]=[]
|
2897
|
+
@htracks[tc]=[@mx.metaTitle, @mx.generaterText, @mx.starttempo, @mx.makefraze(@rundatas[0],tc), @mx.lastrest].flatten
|
2762
2898
|
@rundatas[1..-1].each{|track|
|
2763
2899
|
tc+=1
|
2764
|
-
@htracks
|
2900
|
+
@htracks[tc]=[]
|
2901
|
+
@htracks[tc]=[@mx.restHex,@mx.makefraze(track,tc), @mx.lastrest].flatten
|
2765
2902
|
}
|
2766
2903
|
end
|
2767
2904
|
def pack
|
2768
2905
|
@header=@mx.header(1, @tracknum, @tbase)
|
2769
|
-
|
2906
|
+
tc=0
|
2907
|
+
alla=[@header]+@htracks.map{|t|
|
2908
|
+
tc+=1
|
2909
|
+
@mx.trackMake(t,tc-1)
|
2910
|
+
}.flatten
|
2770
2911
|
puts alla if $DEBUG
|
2771
2912
|
all=alla.map{|i|i.commentoff("","#")}*""
|
2772
2913
|
array=[all.split.join]
|
data/lib/smml/version.rb
CHANGED
data/sample/midi-preModifier.txt
CHANGED
File without changes
|
data/smml.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/tabasano/wavseq"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.files = Dir.glob("lib/*")+Dir.glob("lib/smml/*")+Dir.glob("bin/*")+["Gemfile","Rakefile","LICENSE.txt","smml.gemspec","README_smml.md","tutorial_smml.md"]+["sample/midi-preModifier.txt","sample/midi-test.mml"]
|
16
|
+
spec.files = Dir.glob("lib/*")+Dir.glob("lib/smml/*")+Dir.glob("bin/*")+["Gemfile","Rakefile","LICENSE.txt","smml.gemspec","README_smml.md","tutorial_smml.md"]+["sample/midi-preModifier.txt","sample/midi-test.mml","sample/ssmml.rb"]
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.extra_rdoc_files =%w[README_smml.md LICENSE.txt tutorial_smml.md]
|
data/tutorial_smml.md
CHANGED
@@ -188,7 +188,9 @@ minus value is for to stroke up. currently, up value affects once only as it sim
|
|
188
188
|
(+)a (-)b (0)c
|
189
189
|
```
|
190
190
|
|
191
|
-
strange ways can be affective currently.
|
191
|
+
strange ways of sharp/flat can be affective currently. ```(+4)a``` , ```(-1.2)a``` etc. in float value, bend data is used inside.
|
192
|
+
|
193
|
+
|
192
194
|
;; instead of 'd' etc., note numbers can be used if you want.
|
193
195
|
;; MIDI note value is from 0 to 127. it's over Piano's 88. but too high/low note may not be played and heard.
|
194
196
|
|
@@ -242,6 +244,21 @@ _snare! = = =
|
|
242
244
|
|
243
245
|
first two tracks are 'organ' sound by the track names declared.
|
244
246
|
|
247
|
+
|
248
|
+
currenly track names are not used, and tracks continue with apprearing order. so if there are no data in some tracks in mid parts of pages,
|
249
|
+
use blank tracks by track seperaters.
|
250
|
+
|
251
|
+
```
|
252
|
+
c ;; track 1
|
253
|
+
||| e ;; track 2
|
254
|
+
||| g ;; track 3
|
255
|
+
///////////////////////////////////////
|
256
|
+
abc ;; track 1
|
257
|
+
||| ;; track 2 , no data but it can't be omitted to adjust track counters after this track.
|
258
|
+
||| def ;; track 3
|
259
|
+
```
|
260
|
+
|
261
|
+
|
245
262
|
## page
|
246
263
|
;; then seperate pages by three or longer one line '/'.
|
247
264
|
;; but this command do not adjust time potisions. it simply resets track number increment.
|
@@ -297,6 +314,7 @@ these are played like this.
|
|
297
314
|
```
|
298
315
|
|
299
316
|
;; same mark names 'm' in repeated section or one track will be automaticaly substituded by 'm m@2 m@3'. to adjust, use it in other tracks.
|
317
|
+
or use a comma , '(mark:hoge@3)' = '(mark:hoge,3)'
|
300
318
|
|
301
319
|
```
|
302
320
|
a b c (mark:m) a b c (mark:m@2) a b c (mark:m@3)
|
@@ -333,36 +351,40 @@ so in this list, instrument number 1,2 and 3 match the keyword 'piano'.
|
|
333
351
|
So '(p:guitar,2)' selects an instrument line '5 two' as the 2nd result of searching 'guitar' and will be used instead of no word 'guitar' on it.
|
334
352
|
|
335
353
|
## hex data
|
336
|
-
;; until smml syntax is completed, raw hex parts can be used for
|
337
|
-
search MIDI format and set hex data.
|
354
|
+
;; until smml syntax is completed, or other reasons, raw hex parts can be used for deep level data and things you don't know how to inprement by smml data.
|
355
|
+
search MIDI format and set valid hex data.
|
338
356
|
|
339
357
|
```
|
340
358
|
&(00 00 00)
|
341
359
|
```
|
342
360
|
|
361
|
+
hex data must be ``` 00 01 02 ... FD FE FF ```. one byte is by two hex letters. seperaters are a blank or comma.
|
343
362
|
;; currently hex only can be used. oct/decimal may be able to use someday.
|
344
363
|
all in SMF track data, unique formated prefix delta tick time data is needed. so if want, you can use '$delta(240)' for 240 ticks.
|
345
364
|
the tick means a minimum time span in SMF , one beat equals to 480 ticks as default. in this case, delta time is set to half beat.
|
346
365
|
also '$se(F0 41 ..)' can be used for system exclusive message data.
|
347
366
|
currently, nest data of parenthesis is not implemented except very limited cases.
|
367
|
+
anyway, when you use hex data, be careful not to set invalid data. smml don't check its MIDI data validation.
|
368
|
+
|
348
369
|
|
349
|
-
## macro
|
370
|
+
## define and apply macro variable
|
350
371
|
;; for repeating phrase, macro can be used. use prefix '$' for refering.
|
351
372
|
|
352
373
|
```
|
353
|
-
|
374
|
+
VeryLongPhraze:=cde
|
354
375
|
macro W:=abc
|
355
376
|
|
356
|
-
ggg $
|
377
|
+
ggg $VeryLongPhraze fff $W
|
357
378
|
```
|
358
379
|
|
359
|
-
the 4th line will be
|
380
|
+
the 4th line will be replaced by
|
360
381
|
|
361
382
|
```
|
362
|
-
ggg cde fff abc
|
383
|
+
ggg cde fff abc
|
363
384
|
```
|
364
385
|
|
365
|
-
the keyword 'macro' is used just for
|
386
|
+
the keyword 'macro' is used just for easy readability and will simply be ignored.
|
387
|
+
a macro definition is normally within and whole one line. you can write any valid smml data after '```:=```'.
|
366
388
|
|
367
389
|
|
368
390
|
;; macro with args
|
@@ -385,10 +407,11 @@ will be
|
|
385
407
|
ab10 (wait:4) ab20 (wait:4) ab30
|
386
408
|
```
|
387
409
|
|
388
|
-
'(wait:4)' was inserted by '4' in first place before args. it means 4 beats of rest (exact mean of '(wait:..)' is
|
410
|
+
'(wait:4)' was inserted by '4' in first place before args. it means 4 beats of rest (exact mean of '(wait:..)' is
|
411
|
+
'do nothing, set it free even if sound is on and wait for the next command' ).
|
389
412
|
|
390
413
|
|
391
|
-
multiline macro definition
|
414
|
+
multiline macro definition is ;
|
392
415
|
|
393
416
|
```
|
394
417
|
EFF:=(
|
@@ -399,7 +422,8 @@ EFF:=(
|
|
399
422
|
)
|
400
423
|
```
|
401
424
|
|
402
|
-
|
425
|
+
after parenthesis, don't set any letters without blanks.
|
426
|
+
but now, this is for easy way of writing only, and may not be so useful. to use this multi line values, each line must be seperated.
|
403
427
|
|
404
428
|
```
|
405
429
|
$EFF[1] $EFF[2] $EFF[3] $EFF[4]
|
@@ -413,11 +437,12 @@ but, these are MIDI system exclusive HEX data, so to make it really effective da
|
|
413
437
|
```
|
414
438
|
|
415
439
|
```$se()``` translates hex SysEx data to SMF hex data, and it needs pre delta-time data by ```$delta(ticks)``` like other data.
|
416
|
-
```$delta(0)``` is ```00``` , so both of these are effective.
|
440
|
+
```$delta(0)``` is ```00``` , so both of these are effective. inside ```$delta()``` value is not hex, use decimal number.
|
417
441
|
|
442
|
+
'${ff}' can be used for '$ff' as macro variable.
|
418
443
|
|
419
444
|
## comment
|
420
|
-
;;
|
445
|
+
;; words after ';;' of each line are ignored. write comments there.
|
421
446
|
multi line comments start with longer ';'.
|
422
447
|
end mark is same or longer mark of ';' than start mark. these must start from the top of the line.
|
423
448
|
|
@@ -618,11 +643,20 @@ so,
|
|
618
643
|
|
619
644
|
;; set this track's channel 1. when several tracks use same channel, for example it will behave as the same instrument.
|
620
645
|
|
646
|
+
|
647
|
+
```
|
648
|
+
(bend:100) c
|
649
|
+
```
|
650
|
+
|
651
|
+
pitch bend 100 of note 'c'.
|
652
|
+
|
621
653
|
```
|
622
|
-
(bend
|
654
|
+
(bend:+100) c
|
655
|
+
(bend:+-200) c
|
623
656
|
```
|
624
657
|
|
625
|
-
|
658
|
+
'+' relative value. if these are after above, three notes are bend 100 of 'c', bend 200 of 'c' and bend 0 of 'c'.
|
659
|
+
|
626
660
|
|
627
661
|
```
|
628
662
|
(bendRange:12)
|
@@ -693,6 +727,16 @@ now, note type commands are :
|
|
693
727
|
|
694
728
|
```'~'``` seems likely note type, but it is compressed to preceding note as calculated note length. most commands cannot be set inside of ```'c~~~'.```
|
695
729
|
|
730
|
+
;; theremin like sound,
|
731
|
+
|
732
|
+
```
|
733
|
+
(p:organ)
|
734
|
+
(theremin:on)
|
735
|
+
ab /:cde/ f
|
736
|
+
```
|
737
|
+
|
738
|
+
after on command, data is manipulated as bend data inside smml. not completed about modifiers for this.
|
739
|
+
|
696
740
|
|
697
741
|
## preprocess
|
698
742
|
;; some pre-process commands.
|
@@ -720,6 +764,7 @@ all after that are real values. the '+' adds 10 to latest value as default.
|
|
720
764
|
so expression data is ;``` 40,50,60,70,80,70,60,50,40,50,60,70,80...``` with each 20 ticks interval.
|
721
765
|
bend and expression values inside these parts will be reseted after the modified note ends.
|
722
766
|
series of ```(A:..)``` parts are merged. if not, old one is overwtitten.
|
767
|
+
'o' is dummy and it set nil value and simply ignored. it is for visibility purpose only.
|
723
768
|
|
724
769
|
|
725
770
|
## text
|
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.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tabasano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,7 +44,6 @@ email:
|
|
44
44
|
executables:
|
45
45
|
- mmlsmml
|
46
46
|
- smml
|
47
|
-
- ssmml
|
48
47
|
extensions: []
|
49
48
|
extra_rdoc_files:
|
50
49
|
- README_smml.md
|
@@ -58,7 +57,6 @@ files:
|
|
58
57
|
- lib/smml/version.rb
|
59
58
|
- bin/mmlsmml
|
60
59
|
- bin/smml
|
61
|
-
- bin/ssmml
|
62
60
|
- Gemfile
|
63
61
|
- Rakefile
|
64
62
|
- LICENSE.txt
|
@@ -67,6 +65,7 @@ files:
|
|
67
65
|
- tutorial_smml.md
|
68
66
|
- sample/midi-preModifier.txt
|
69
67
|
- sample/midi-test.mml
|
68
|
+
- sample/ssmml.rb
|
70
69
|
homepage: https://github.com/tabasano/wavseq
|
71
70
|
licenses:
|
72
71
|
- MIT
|