From 267170167d52cab9e97f879d9127a1cf04f6bb58 Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Tue, 15 Mar 2011 20:53:57 +0000 Subject: This is a version of Claude Heiland-Allen's lua for Pd. The objects are named pdlua and pdluax instead of lua and luax. So far it seems to work on linux. svn path=/trunk/externals/pdlua/; revision=15030 --- examples/luametro.pd_lua | 161 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 examples/luametro.pd_lua (limited to 'examples/luametro.pd_lua') diff --git a/examples/luametro.pd_lua b/examples/luametro.pd_lua new file mode 100644 index 0000000..8041e6e --- /dev/null +++ b/examples/luametro.pd_lua @@ -0,0 +1,161 @@ +-- reimplementation of [metro] with a twist +-- fbar 2007 + +-- we need an urn: +local urn = {} + +function urn.new(size) + assert(size > 0, "Error: size of urn must be greater than 0") + local t = {size=size, last=size} + for i=1,size do + t[i] = i + end + return t +end + +function urn.get(u) + if u.last > 0 then + local i = math.random(u.last) + local res = u[i] + u[i] = u[u.last] + u.last = u.last - 1 + return res + else + return nil + end +end + +function urn.reset(u) + u.last = u.size + for i=1,u.size do + u[i] = i + end +end + +local modes = {"alea", "series", "sequence", "rota"} + +local function contains(t,x) + for k,v in pairs(t) do + if v == x then return true end + end + return false +end + +-- pd: + +local M = pd.Class:new():register("luametro") + +function M:initialize(name, atoms) + self.periods = {} + self.i = 1 + self.mode = "sequence" + self.direction = 1 + self.u = urn.new(math.max(1, #atoms)) + if not self:setperiods(atoms) then return false end + self.inlets = 2 + self.outlets = 2 + return true +end + +function M:postinitialize() + self.clock = pd.Clock:new():register(self, "tick") +end + +function M:finalize() + self.clock:destruct() +end + +function M:setperiods(periods) + self.periods = {} + for i,j in ipairs(periods) do + if type(j) == "number" then + self.periods[i] = math.max(0.01, j) + else + self:error("non-number in period list!") + return false + end + end + -- start over at front: + self.i = 1 + return true +end + +function M:in_2(sel, atoms) + if sel == "list" or sel == "float" then + self:setperiods(atoms) + end +end + +function M:in_1_float(f) + if f ~= 0 then + self:tick() + else + self.clock:unset() + end +end + +function M:in_1_bang() + self.i = 1 + self:tick() +end + +function M:in_1_start() + self.i = 1 + self:tick() +end + +function M:in_1_stop() + self.clock:unset() +end + +function M:in_1_mode(atoms) + if type(atoms[1]) == "number" then + self.mode = modes[atoms[1]] + if self.mode == "series" then + self.u = urn.new(#self.periods) + end + self.i = 1 + elseif type(atoms[1]) == "string" then + if contains(modes, atoms[1]) then + self.mode = atoms[1] + else + self:error("no such mode: " .. atoms[1]) + end + end + pd.post("Mode set to: " .. self.mode) +end + + +function M:tick() + self:outlet(1, "bang", {}) + -- pd.post("selection: " .. tostring(self.i)) + if type(self.periods[self.i]) == "number" then + self.clock:delay(self.periods[self.i]) + end + if self.mode == "sequence" then + self.i = self.i + 1 + if self.i > #self.periods then + self.i = 1 + self:outlet(2, "bang", {}) + end + elseif self.mode == "alea" then + self.i = math.random(#self.periods) + elseif self.mode == "series" then + local f = urn.get(self.u) + if not f then + urn.reset(self.u) + f = urn.get(self.u) + self:outlet(2, "bang", {}) + end + self.i = f + elseif self.mode == "rota" then + self.i = self.i + self.direction + if self.i > #self.periods or self.i < 1 then + self.direction = -self.direction + self.i = self.i + self.direction + self:outlet(2, "bang", {}) + end + else + self:error("Unknown mode") + end +end -- cgit v1.2.1