--[[ lua code. create 20 random presets in "wavetable" synthesis style. for zynaddsubfx or yoshimi. this will be up for one month. ]] --[[ * by mnrvovrfc/hsiangch_ong/clear2ooo * originally written in 2016 (Cubs win!!!) * modified on 29-Jan-2025 * modified to be self-contained, used to be five separate files. * This Lua script creates 20 preset files for Zynaddsubfx/Yoshimi. * They appear in the user's Documents directory. * It takes a "xiz" suffix file of the old text format and creates a new one, messing around with many "AddSynth" parameters. It might be most interesting to people who love wavetable synthesis. * IMPORTANT: the source code file should be called "xiz-new.lua" (without double-quotation marks). If this is not acceptable search for that name in this text ("afile" variable assignment) and change it to what you want. * I'm sorry for the file length but otherwise I didn't want to create a ZIP to put into some file-sharing site. * Requires Lua v5.2 or later. * Just get interpreter from "lua-dot-org", build it for 32/64-bit and run this script. Nothing else is needed. * DISCLAIMER: I will not be held responsible for the inability to use this script as it was intended. It should NOT be used in a production environment. This script is offered AS IS, as "public domain" which means nobody else could claim to be the original author. ]] function findstr(txt, lookfor) return string.find(txt, lookfor, 1, true) end function sformat(aformat, arg1, ...) if arg1 == nil then return aformat end return string.format(aformat, arg1, ...) end function tert(valu, first, second) if valu == first then valu = second else valu = first end return valu end function table_create(atable) function local_table_copy(t) local tret function local_copy(t) local tret = { } for i = 1, #t do tret[i] = t[i] end for k, v in pairs(t) do if type(v) == "table" then tret[k] = local_copy(v) elseif type(k) ~= "number" then tret[k] = v end end return tret end tret = local_copy(t) return tret end local tret = { insert = function (s, ...) local rest = { ... } if rest == nil or #rest == 0 then return end local lrest = #rest for i = 1, lrest do table.insert(s, rest[i]) end end, first = function (s, t) if t == nil then return end table.insert(s, 1, t) end, concat = function (s, delim, pfrom, pto) return table.concat(s, delim, pfrom, pto) end, copy = function (s, ts, append) if type(ts) ~= "table" then return end if next(ts) == nil then return end if append == nil then s:delete() end local n = #ts for i = 1, n do table.insert(s, ts[i]) end end, remove = function (s, spos) table.remove(s, spos) end, delete = function (s) local n = #s while n > 0 do table.remove(s) n = n - 1 end end, clear = function (s) s:delete() end, is_empty = function (s) -- not a good way, but the alternative is to search all elements for one with numeric index -- the assumption is that if table_create() is used to create a table then -- "insert" method would be used to add elements, like an array in BASIC return (#s == 0) end } if type(atable) == "table" and next(atable) ~= nil then local t = tret tret = local_table_copy(atable) if not tret.insert then tret.insert = t.insert tret.clear = t.clear tret.concat = t.concat tret.copy = t.copy tret.delete = t.delete tret.first = t.first tret.is_empty = t.is_empty tret.remove = t.remove end end return tret end function ran(a, b) if type(a) ~= "number" then return nil end if math.floor(a) == math.floor(b) then return a end if a < 0 and b < 0 then a = a * -1 b = b * -1 if a > b then a, b = b, a end return math.random(a, b) * -1 end if a > b then a, b = b, a end if a < 0 or b < 0 then local x = a * -1 if b < 0 then x = b * -1 end return math.random(a + x, b + x) - x end return math.random(a, b) end -- recommended for this function to be used on a table that will be affected by table.sort() function table_strip(t) if t.insert then t.insert, t.first, t.remove, t.clear, t.concat, t.is_empty, t.copy, t.delete = nil, nil, nil, nil, nil, nil, nil, nil end return t end ssub = string.sub sfind = string.find supper = string.upper slower = string.lower function different_values(numval, vlo, vhi, vadd, vmult, addfirst) if numval < 2 or vlo == vhi then return nil end local tret = table_create() local n if numval == 2 then n = vlo if vadd then n = n + vadd end if vmult then n = n * vmult end tret:insert(n) n = vhi if vadd then n = n + vadd end if vmult then n = n * vmult end tret:insert(n) return tret end local sg if vlo < 0 and vhi < 0 then sg = -1 vlo = vlo * -1 vhi = vhi * -1 else sg = 1 end if vlo > vhi then vlo, vhi = vhi, vlo end local tj, goahead repeat goahead = true tj = { } tret:clear() for z = 1, numval do n = ran(vlo, vhi) * sg tret:insert(n) if tj[n] == nil then tj[n] = 1 else tj[n] = tj[n] + 1 end end for kk, vv in pairs(tj) do if vv > 1 then goahead = false; break end end until goahead if vadd and addfirst then for z = 1, numval do tret[z] = tret[z] + vadd end end if vmult then for z = 1, numval do tret[z] = tret[z] * vmult end end if vadd and not addfirst then for z = 1, numval do tret[z] = tret[z] + vadd end end return tret end function table_reverse(t) if t == nil or type(t) ~= "table" then return nil end local l = #t if l == 0 then return t end local tret = { } for i = l, 1, -1 do table.insert(tret, t[i]) end return tret end function gimme_harmonics(nlo, nhi) local t, nharm, tharm, u nharm = ran(nlo, nhi) t = different_values(nharm, 2, 16) table.sort(t) t = table_reverse(t) for j = 1, #t do u = t[j] t[j] = sformat(harmtem, u, ran(10, 16) * 8) end return t end txt, top, tob, tosc = table_create(), table_create(), table_create(), table_create() for j = 1, 16 do tosc[j] = table_create() end equal80 = string.rep(80, '=') harmtem = [=[ ]=] -- THIS HAS TO BE THE SAME NAME (FULL PATH) AS THIS FILE: afile = os.getenv("HOME") .. "/Documents/lua/xiz-new.lua" presetscan = false fu = io.open(afile, "r") if fu == nil then print("For this to work, file is required:") print(afile) return end for s in fu:lines() do if presetscan then if s == equal80 then break end txt:insert(s) elseif s == equal80 then presetscan = true end end fu:close() vo = 0 t = top passi = false for i = 1, #txt do if findstr(txt[i], "" and vo == 8 then tosc[vo]:insert(txt[i]) vo = 0 t = tob passi = true end if passi then passi = false else t:insert(txt[i]) end end for w = 1, 20 do filton = false filtenv = false for i = 1, #top do if findstr(top[i], 'string name="name"') then top[i] = sformat('randompreset%04d', w) elseif findstr(top[i], 'string name="auth') then top[i] = 'me' elseif findstr(top[i], 'string name="com') then top[i] = 'It might be useful for something.' elseif top[i] == "" then filton = true elseif top[i] == "" then filton = false elseif top[i] == "" then filtenv = true elseif top[i] == '' and filtenv then filtenv = false end if filton then if findstr(top[i], 'par name="type"') then top[i] = sformat('', ran(0, 4)) elseif findstr(top[i], 'par name="q"') then top[i] = sformat('', ran(0, 22) * 4) end end if filtenv then ta = ran(8, 12) * 4 if ran(1, 3) == 1 then td = ran(6, 12) * 4 else td = ta end fa = ran(6, 14) * 4 fd = ran(18, 26) * 4 if ran(1, 2) == 1 then fa, fd = fd, fa end if findstr(top[i], '', ta) elseif findstr(top[i], '', td) elseif findstr(top[i], '', fa) elseif findstr(top[i], '', fd) end end end for j = 9, 16 do tosc[j]:copy(tosc[j - 8]) end oscshift = ( ran(1, 4) == 1 ) if oscshift then tn = different_values(7, 0, 15, 0, 8) else tn = different_values(7, 2, 14, 0, 8) end table.insert(tn, 0) wshf = ran(0, 6) for j = 9, 16 do v = j - 8 firstdelay = true firstwsh = true attackfirst = true moreharm = true lfofreqon = false moremod = ( w % 2 == 0 ) freqparmset = "" harmonicend = 0 tharm = gimme_harmonics(3, 6) for i = 1, #tosc[j] do if findstr(tosc[j][i], 'par name="delay"') and oscshift and firstdelay and not lfofreqon then firstdelay = false tosc[j][i] = sformat('', tn[v]) elseif findstr(tosc[j][i], 'par name="wave_shaping"') and firstwsh then tosc[j][i] = sformat('', ran(32, 96)) elseif findstr(tosc[j][i], '', wshf) elseif findstr(tosc[j][i], '', u) elseif findstr(tosc[j][i], '', u) elseif findstr(tosc[j][i], '', u) elseif tosc[j][i] == "" and harmonicend == 0 then harmonicend = i elseif tosc[j][i] == "" then moreharm = false elseif tosc[j][i] == "" and tosc[j][i + 2] == '' then lfofreqon = true elseif tosc[j][i] == "" and lfofreqon then lfofreqon = false elseif tosc[j][i] == "" and freqparmset == "m" then freqparmset = "" elseif tosc[j][i] == "" and freqparmset == "i" then freqparmset = "" elseif moremod and tosc[j][i] == "" then freqparmset = "m" elseif moremod and tosc[j][i] == "" then freqparmset = "i" end if moreharm and tn[v] == 0 then u = ran(0, 1) * 5 + 1 if findstr(tosc[j][i], '', u) elseif findstr(tosc[j][i], '', ran(0, 64)) elseif findstr(tosc[j][i], '', z) end end if moreharm and v > 4 then if findstr(tosc[j][i], '', ran(2, 3)) elseif findstr(tosc[j][i], '', ran(2, 14) * 8) elseif findstr(tosc[j][i], '', ran(3, 16) * 4) elseif findstr(tosc[j][i], '', ran(0, 8) * 8) end end if lfofreqon and v < 5 then if tosc[j][i] == '' then tosc[j][i] = '' elseif findstr(tosc[j][i], '', ran(10, 1000) / 1000) elseif findstr(tosc[j][i], '', ran(1, 8) * 8) elseif findstr(tosc[j][i], '', z) elseif findstr(tosc[j][i], '', ran(0, 4)) elseif findstr(tosc[j][i], '', z) end end if w % 4 == 0 and (v == 1 or v == 3) and freqparmset == "m" then if findstr(tosc[j][i], '', ran(3328, 3840) * 4) end end if moremod and (v == 2 or v == 4) and freqparmset == "i" then if findstr(tosc[j][i], '', v - 2) end end end -- for i if harmonicend > 0 then for i = 1, #tharm do table.insert(tosc[j], harmonicend, tharm[i]) end end if moremod and (v == 1 or v == 3) then tharm = gimme_harmonics(2, 4) hs = nil for i = #tosc[j], 1, -1 do if tosc[j][i] == "" then hs = i + 5; break end end if hs then while tosc[j][hs] ~= "" do table.remove(tosc[j], hs) end for i = 1, #tharm do table.insert(tosc[j], hs, tharm[i]) end end end end -- for j outfile = os.getenv("HOME") .. "/Documents/" .. sformat("%04d-randompreset%04d.xiz", w, w) fu = io.open(outfile, "w") if fu then fu:write(top:concat('\n') .. '\n') for j = 9, 16 do fu:write(tosc[j]:concat('\n') .. '\n') end fu:write(tob:concat('\n')) fu:close() print("Created: " .. outfile) end end -- for w --[[ ================================================================================ ================================================================================ ]]