smml 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|