| User-Defined Opcode Database |
|---|
Converts a string-array which just consists of numbers or simple math expressions to a function table
Download UDO FilePuts all numbers in Stray (which must not contain non-numerical elements) in a function table and returns its variable ift (which is produced by iftno, default=0) and the length of the elements written iftlen. (An empty string as input writes a function table of size=1 to avoid an error but returns 0 as length of elements written.) Simple binary math expressions using +, -, *, /, ^ and % are allowed, with just one parenthesis in total (see the examples below).
Elements are defined by two seperators as ASCII coded characters: isep1 defaults to 32 (= space), isep2 defaults to 9 (= tab). If just one seperator is used, isep2 equals isep1.
Requires csound 5.15 or higher, and the UDOs StrayLen, StrExpr1 and StrExpr2
ift, iftlen StrayNumToFt Stray [, iftno [, isep1 [, isep2]]]
Stray - a string as array
iftno - like in an ftgen statement: if 0 (which is also the default) an automatic number is generated by Csound; if any positive number, this is then the number of the function table
isep1 - the first seperator (default=32: space)
isep2 - the second seperator (default=9: tab)
ift - the number of the function table which has been created
iftlen - the length of the elements written to the function table (usually this equals the length of the function table; just an empty string as input will create a function table of size=1 but with iftlen=0)
opcode StrayNumToFt, ii, Sojj
;requires the UDOs StrayLen, StrExpr1 and StrExpr2
Stray, iftno, isepA, isepB xin
;;DEFINE THE SEPERATORS
isep1 = (isepA == -1 ? 32 : isepA)
isep2 = (isepA == -1 && isepB == -1 ? 9 : (isepB == -1 ? isep1 : isepB))
Sep1 sprintf "%c", isep1
Sep2 sprintf "%c", isep2
;;CREATE A FUNCTION TABLE
iftlen StrayLen Stray, isep1, isep2
if iftlen == 0 then
prints "WARNING! StrayNumToFt got empty string as input. Function table with length=1 created, but iftlen=0 returned.\n"
iftl = 1
else
iftl = iftlen
endif
ift ftgen iftno, 0, -iftl, -2, 0
;;INITIALIZE SOME PARAMETERS
ilen strlen Stray
istartsel = -1; startindex for searched element
iel = -1; number of element in Stray and ift
iwarleer = 1; is this the start of a new element
indx = 0 ;character index
inewel = 0 ;new element to find
;;LOOP
if ilen == 0 igoto end ;don't go into the loop if Stray is empty
loop:
Schar strsub Stray, indx, indx+1; this character
isep1p strcmp Schar, Sep1; returns 0 if Schar is sep1
isep2p strcmp Schar, Sep2; 0 if Schar is sep2
is_sep = (isep1p == 0 || isep2p == 0 ? 1 : 0) ;1 if Schar is a seperator
;END OF STRING AND NO SEPARATORS BEFORE?
if indx == ilen && iwarleer == 0 then
Sel strsub Stray, istartsel, -1
inewel = 1
;FIRST CHARACTER OF AN ELEMENT?
elseif is_sep == 0 && iwarleer == 1 then
istartsel = indx ;if so, set startindex
iwarleer = 0 ;reset info about previous separator
iel = iel+1 ;increment element count
;FIRST SEPERATOR AFTER AN ELEMENT?
elseif iwarleer == 0 && is_sep == 1 then
Sel strsub Stray, istartsel, indx ;get element
inewel = 1 ;tell about
iwarleer = 1 ;reset info about previous separator
endif
;WRITE THE ELEMENT TO THE TABLE
if inewel == 1 then
inum StrExpr2 Sel ;convert expression to number
tabw_i inum, iel, ift ;write to ift
endif
inewel = 0
loop_le indx, 1, ilen, loop
end:
xout ift, iftlen
endop
<CsoundSynthesizer>
<CsOptions>
-n -m0
</CsOptions>
<CsInstruments>
opcode StrayLen, i, Sjj
;returns the number of elements in Stray. elements are defined by two seperators as ASCII coded characters: isep1 defaults to 32 (= space), isep2 defaults to 9 (= tab). if just one seperator is used, isep2 equals isep1
Stray, isepA, isepB xin
;;DEFINE THE SEPERATORS
isep1 = (isepA == -1 ? 32 : isepA)
isep2 = (isepA == -1 && isepB == -1 ? 9 : (isepB == -1 ? isep1 : isepB))
Sep1 sprintf "%c", isep1
Sep2 sprintf "%c", isep2
;;INITIALIZE SOME PARAMETERS
ilen strlen Stray
icount = 0; number of elements
iwarsep = 1
indx = 0
if ilen == 0 igoto end ;don't go into the loop if String is empty
loop:
Snext strsub Stray, indx, indx+1; next sign
isep1p strcmp Snext, Sep1; returns 0 if Snext is sep1
isep2p strcmp Snext, Sep2; 0 if Snext is sep2
if isep1p == 0 || isep2p == 0 then; if sep1 or sep2
iwarsep = 1; tell the log so
else ; if not
if iwarsep == 1 then ; and has been sep1 or sep2 before
icount = icount + 1; increase counter
iwarsep = 0; and tell you are ot sep1 nor sep2
endif
endif
loop_lt indx, 1, ilen, loop
end: xout icount
endop
opcode StrExpr1, i, S
Str xin
isum strindex Str, "+"; sum
idif strindex Str, "-"; difference
ipro strindex Str, "*"; product
irat strindex Str, "/"; ratio
ipow strindex Str, "^"; power
imod strindex Str, "%"; modulo
if ipow > 0 then
ifirst strindex Str, "^"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 ^ i2
elseif imod > 0 then
ifirst strindex Str, "%"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 % i2
elseif ipro > 0 then
ifirst strindex Str, "*"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 * i2
elseif irat > 0 then
ifirst strindex Str, "/"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 / i2
elseif isum > 0 then
ifirst strindex Str, "+"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 + i2
elseif idif > -1 then
ifirst strrindex Str, "-";(last occurrence: -3-4 is possible, but not 3--4)
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
iS1len strlen S1
if iS1len == 0 then ;just a negative number
inum strtod S2
ires = -inum
else
ifirst strtod S1
isec strtod S2
ires = ifirst - isec
endif
else
ires strtod Str
endif
xout ires
endop
opcode StrExpr2, i, S
Sin xin
ilen strlen Sin
;if a parenthesis can be found
iparenth strindex Sin, "("
if iparenth > -1 then
;if in first half and no '-' preceeds
if iparenth == 0 then
;then first element ends in ")"
iprend strindex Sin, ")"
S1 strsub Sin, 1, iprend
;convert this element into a number
i1 StrExpr1 S1
;append the rest and convert again
S2 strsub Sin, iprend+2
Sep strsub Sin, iprend+1, iprend+2
Scoll sprintf "%f%s%s", i1, Sep, S2
ires StrExpr1 Scoll
;if in first half and '-' preceeds
elseif iparenth == 1 then
;then first element ends in ")"
iprend strindex Sin, ")"
S1 strsub Sin, 2, iprend
;convert this element into a number
i1 StrExpr1 S1
i1 = -i1
;append the rest and convert again
S2 strsub Sin, iprend+2
Sep strsub Sin, iprend+1, iprend+2
Scoll sprintf "%f%s%s", i1, Sep, S2
ires StrExpr1 Scoll
;if the parenthesis is in the second half
else
;isolate first element and the conjunction
S1 strsub Sin, 0, iparenth-1
Sep strsub Sin, iparenth-1, iparenth
;convert the second element
S2 strsub Sin, iparenth+1, ilen-1
i2 StrExpr1 S2
;if subtraction and i2 negative, convert to addition
isepminus strcmp Sep, "-"
if i2 < 0 && isepminus == 0 then
i2 = -i2
Sep = "+"
endif
;convert the whole
Scoll sprintf "%s%s%f", S1, Sep, i2
ires StrExpr1 Scoll
endif
;if no parenthesis, simply convert
else
ires StrExpr1 Sin
endif
xout ires
endop
opcode StrayNumToFt, ii, Sojj
;requires the UDOs StrayLen, StrExpr1 and StrExpr2
Stray, iftno, isepA, isepB xin
;;DEFINE THE SEPERATORS
isep1 = (isepA == -1 ? 32 : isepA)
isep2 = (isepA == -1 && isepB == -1 ? 9 : (isepB == -1 ? isep1 : isepB))
Sep1 sprintf "%c", isep1
Sep2 sprintf "%c", isep2
;;CREATE A FUNCTION TABLE
iftlen StrayLen Stray, isep1, isep2
if iftlen == 0 then
prints "WARNING! StrayNumToFt got empty string as input. Function table with length=1 created, but iftlen=0 returned.\n"
iftl = 1
else
iftl = iftlen
endif
ift ftgen iftno, 0, -iftl, -2, 0
;;INITIALIZE SOME PARAMETERS
ilen strlen Stray
istartsel = -1; startindex for searched element
iel = -1; number of element in Stray and ift
iwarleer = 1; is this the start of a new element
indx = 0 ;character index
inewel = 0 ;new element to find
;;LOOP
if ilen == 0 igoto end ;don't go into the loop if Stray is empty
loop:
Schar strsub Stray, indx, indx+1; this character
isep1p strcmp Schar, Sep1; returns 0 if Schar is sep1
isep2p strcmp Schar, Sep2; 0 if Schar is sep2
is_sep = (isep1p == 0 || isep2p == 0 ? 1 : 0) ;1 if Schar is a seperator
;END OF STRING AND NO SEPARATORS BEFORE?
if indx == ilen && iwarleer == 0 then
Sel strsub Stray, istartsel, -1
inewel = 1
;FIRST CHARACTER OF AN ELEMENT?
elseif is_sep == 0 && iwarleer == 1 then
istartsel = indx ;if so, set startindex
iwarleer = 0 ;reset info about previous separator
iel = iel+1 ;increment element count
;FIRST SEPERATOR AFTER AN ELEMENT?
elseif iwarleer == 0 && is_sep == 1 then
Sel strsub Stray, istartsel, indx ;get element
inewel = 1 ;tell about
iwarleer = 1 ;reset info about previous separator
endif
;WRITE THE ELEMENT TO THE TABLE
if inewel == 1 then
inum StrExpr2 Sel ;convert expression to number
tabw_i inum, iel, ift ;write to ift
endif
inewel = 0
loop_le indx, 1, ilen, loop
end:
xout ift, iftlen
endop
opcode TbDmpSmpS, 0, iiSo
;prints the content of a table in a simple way, with an additional string as 'introduction'
ifn, iprec, String, ippr xin; function table, float precision while printing, String, parameters per row (maximum = 32)
ippr = (ippr == 0 ? 10 : ippr)
iend = ftlen(ifn)
indx = 0
Sformat sprintf "%%.%df, ", iprec
Sdump sprintf "%s[", String
loop:
ival tab_i indx, ifn
Snew sprintf Sformat, ival
Sdump strcat Sdump, Snew
imod = (indx+1) % ippr
if imod == 0 && indx != iend-1 then
puts Sdump, 1
Sdump = ""
endif
loop_lt indx, 1, iend, loop
ilen strlen Sdump
Slast strsub Sdump, 0, ilen-2
printf_i "%s]\n", 1, Slast
endop
instr 1
Stray strget p4
printf_i "\nStray = '%s'\n", 1, Stray
ipcnt pcount
if ipcnt == 4 then
ift, ilen StrayNumToFt Stray
elseif ipcnt == 5 then
ift, ilen StrayNumToFt Stray, p5
elseif ipcnt == 6 then
ift, ilen StrayNumToFt Stray, p5, p6
elseif ipcnt == 7 then
ift, ilen StrayNumToFt Stray, p5, p6, p7
endif
prints "ift# = %d, iftlen = %d%n", ift, ilen
TbDmpSmpS ift, 5, "table content = "
endin
</CsInstruments>
<CsScore>
i 1 0 .01 "1 -2 3 4 5 6 7"
i . + . "1.2 2+3.45 6.7/-8.09 "
i . + . " 15%12 -5-3 "
i . + . " 2^0.6 2^(1/12) 2^(-1/12) 16 32"
i . + . "123*-4.56 "
i . + . "123*(-4.56) "
i . + . " "
i . + . ""
i . + . "-(1+2.7)*-3 2^-(-1/-12) -(-3.10*-65)/-3.4567 27%5"
i . + . "1+2.7 2^(1/12) 3.10*65 27%5"
i . + . "1+2.7 2^(1/12) 3.10*65 27%6" 13 ;write table number 13
i . + . "1+2.7,2^(1/12),3.10*65,27%7" 0 44 ;just commas are seperators
i . + . "1+2.7, 2^(1/12), 3.10*65, 27%8" 0 44 ;no problem to write spaces though
i . + . "1+2.7,2^(1/12)|3.10*65,27%9" 0 44 124 ;commas and '|' are seperators
e
</CsScore>
</CsoundSynthesizer>
returns:
Stray = '1 -2 3 4 5 6 7'
ift# = 101, iftlen = 7
table content = [1.00000, -2.00000, 3.00000, 4.00000, 5.00000, 6.00000, 7.00000]
Stray = '1.2 2+3.45 6.7/-8.09 '
ift# = 102, iftlen = 3
table content = [1.20000, 5.45000, -0.82818]
Stray = ' 15%12 -5-3 '
ift# = 103, iftlen = 2
table content = [3.00000, -8.00000]
Stray = ' 2^0.6 2^(1/12) 2^(-1/12) 16 32'
ift# = 104, iftlen = 5
table content = [1.51572, 1.05946, 0.94387, 16.00000, 32.00000]
Stray = '123*-4.56 '
ift# = 105, iftlen = 1
table content = [-560.88000]
Stray = '123*(-4.56) '
ift# = 106, iftlen = 1
table content = [-560.88000]
Stray = ' '
WARNING! StrayNumToFt got empty string as input. Function table with length=1 created, but iftlen=0 returned.
ift# = 107, iftlen = 0
table content = [0.00000]
Stray = ''
WARNING! StrayNumToFt got empty string as input. Function table with length=1 created, but iftlen=0 returned.
ift# = 108, iftlen = 0
table content = [0.00000]
Stray = '-(1+2.7)*-3 2^-(-1/-12) -(-3.10*-65)/-3.4567 27%5'
ift# = 109, iftlen = 4
table content = [11.10000, 0.94387, 58.29259, 2.00000]
Stray = '1+2.7 2^(1/12) 3.10*65 27%5'
ift# = 110, iftlen = 4
table content = [3.70000, 1.05946, 201.50000, 2.00000]
Stray = '1+2.7 2^(1/12) 3.10*65 27%6'
ift# = 13, iftlen = 4
table content = [3.70000, 1.05946, 201.50000, 3.00000]
Stray = '1+2.7,2^(1/12),3.10*65,27%7'
ift# = 111, iftlen = 4
table content = [3.70000, 1.05946, 201.50000, 6.00000]
Stray = '1+2.7, 2^(1/12), 3.10*65, 27%8'
ift# = 112, iftlen = 4
table content = [3.70000, 1.05946, 201.50000, 3.00000]
Stray = '1+2.7,2^(1/12)|3.10*65,27%9'
ift# = 113, iftlen = 4
table content = [3.70000, 1.05946, 201.50000, 0.00000]
joachim heintz april 2010 / sept 2011 / feb 2012 / dec 2012
| Previous | Home | Next |
| StrayNumSum | StrayRemDup |