Skip to content

Commit

Permalink
named the project... continued to work toward a timespan
Browse files Browse the repository at this point in the history
  • Loading branch information
XiNNiW committed Jan 6, 2023
1 parent dbfc8f7 commit 1ee5d77
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 63 deletions.
15 changes: 15 additions & 0 deletions Abstract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Abstract

Tidalcycles is a popular language for improvising live-coded music. Tidalcycles allows artists to manipulate musical pattern using a Domain Specific Language (DSL) written in the Haskell programming language.
Alex McLean, who is the primary author of Tidalcycles has recently begun several related projects that involve re-writing Tidalcycles from scratch as a form of design inquiry.
In addition to a "clean-room" re-write of Tidalcycles in Haskell, McLean and the larger community have undertaken the project of translating Tidalcycles into other programming languages.
Tidalcycles has so far been translated into Python, Javascript, and Kotlin. These projects, codenamed vortex, strudel, and kidal respectively, _______

This project aims to continue exploring the design space afforded by the process of translation/re-implimentation.
Individually, I hope to learn about the constrution of livecoding languages by "hand-building" one - much as an apprentice luthier might build a guitar in order to learn how to build guitars.
Additionally, I hope to begin answering some larger questions about livecoding languages as musical tools:
- To what extent can the pattern language of a livecoding language be seperated from its formal language?
- What can we learn about the nature of the pattern language by attempting to seperate it from its host programming language?
- How to the affordances of a particular formal language affect the implementation and end user experience of a livecoding system?
- What new design possiblities does the process of translation reveal? How will they affect the development of Tidalcycles? How will they affect the development of new livecoding systems?
-
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# NAME
# Tranquility

Tranquility is an experimental port of the livecoding music language [Tidalcycles](http://tidalcycles.org/) to the lua programming language.
This project follows in the footsteps of [vortex](https://github.com/tidalcycles/vortex) and [strudel](https://strudel.tidalcycles.org).
For me the main purpose of this project is to learn about how to implement a livecoding language.

## Motivation

NAME is an experimental port of the livecoding music language [Tidalcycles](http://tidalcycles.org/) to the lua programming language. This project follows in the footsteps of [vortex](https://github.com/tidalcycles/vortex) and [strudel](https://strudel.tidalcycles.org). For me the main purpose of this project is to learn about how to implement a livecoding language. It is not likely to be directly useful as a tool or instrument.


16 changes: 15 additions & 1 deletion src/fractional.lua → src/fraction.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require('math')
-- require('src/time_span')

-- this is a quick and dirty port of python's Fraction library pulling in only the things i need to get a first version working
-- this should probably all be C calls instead
Expand Down Expand Up @@ -230,7 +231,7 @@ function Fraction:__pow (f2)
return Fraction:new(self:numerator()^power, self:denominator()^power, false)
elseif self:numerator() >= 0 then
return Fraction:new(self:denominator()^-power, self:numerator()^-power, false)
else
else
return Fraction:new((-self:numerator())^-power, (-self:denominator())^-power, false)
end
else
Expand All @@ -252,6 +253,19 @@ function Fraction:__unm ()
return Fraction:new(-self:numerator(), self:denominator(), false)
end

function Fraction:__eq (rhs)
return (self:numerator()/self:denominator())==(rhs:numerator()/rhs:denominator())
end

function Fraction:__lt (rhs)
return (self:numerator()/self:denominator())<(rhs:numerator()/rhs:denominator())
end


function Fraction:__lte (rhs)
return (self:numerator()/self:denominator())<=(rhs.numerator()/rhs.denominator())
end

function Fraction:floor ()
return self:numerator()//self:denominator()
end
51 changes: 33 additions & 18 deletions src/time_span.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require("math")
require('src/fractional')
require("table")
require('src/fraction')

-- """Returns the start of the cycle."""
-- Fraction.sam = lambda self: Fraction(math.floor(self))
Expand All @@ -20,35 +21,49 @@ function TimeSpan:nextSam(frac)
return Fraction:new(frac:floor()+1)
end

function TimeSpan:wholeCycle(frac)
return TimeSpan:new(TimeSpan:sam(frac), TimeSpan:nextSam(frac))
end

function TimeSpan:create (o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end

function TimeSpan:wholeCycle()
return TimeSpan:new(TimeSpan:sam(self:beginTime()), TimeSpan:nextSam(self:endTime()))
function TimeSpan:new(_begin, _end)
return TimeSpan:create{_begin=_begin, _end=_end}
end

function TimeSpan:beginTime ()
function TimeSpan:beginTime()
return self._begin
end

function TimeSpan:endTime ()
function TimeSpan:endTime()
return self._end
end

--function TimeSpan.span_cycles()
-- local spans = {}
-- local _begin = self._begin
-- local _end = self._end
-- local end_sam = _end.sam()
--
-- while _end > _begin do
-- if begin.sam() == end_sam then
-- spans.
-- end
-- end
-- return spans
--end
function TimeSpan:spanCycles()
local spans = {}
local _begin = self._begin
local _end = self._end
local end_sam = TimeSpan:sam(_end)

if _begin == _end then
return {TimeSpan:new(_begin, _end)}
end

while _end > _begin do
if TimeSpan:sam(_begin) == end_sam then
table.insert(spans, TimeSpan:new(_begin, self._end))
break
end

local next_begin = TimeSpan:nextSam(_begin)
table.insert(spans, TimeSpan:new(_begin, next_begin))

_begin = next_begin
end
return spans
end
2 changes: 1 addition & 1 deletion test/all_tests.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---@diagnostic disable: different-requires
local lu = require('test/luaunit/luaunit')
require('test/fractional_test')
require('test/fraction_test')
require('test/pattern_test')
require('test/time_span_test')

Expand Down
78 changes: 64 additions & 14 deletions test/fractional_test.lua → test/fraction_test.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---@diagnostic disable: different-requires
local lu = require('test/luaunit/luaunit')
require('src/fractional')
require('src/fraction')

function TestFractional__create()
function TestFraction__create()
local f = Fraction:create()
lu.assertEquals(f:numerator(), 0)
lu.assertEquals(f:denominator(), 1)
Expand All @@ -13,7 +13,7 @@ end

function CreateFraction(n,d) return Fraction:new(n,d) end

function TestFractional__new()
function TestFraction__new()
local f = Fraction:new()
lu.assertEquals(f:numerator(), 0)
lu.assertEquals(f:denominator(), 1)
Expand All @@ -32,10 +32,21 @@ function TestFractional__new()
f = Fraction:new(-4,-8)
lu.assertEquals(f:numerator(), 1)
lu.assertEquals(f:denominator(), 2)
-- Does Fraction need to reduce decimal numbers to closest approximation?
--f = Fraction:new(1.5, 7.6)
-- lu.assertEquals(f:numerator(), 1.5)
-- lu.assertEquals(f:denominator(), 7.6)
lu.assertError(CreateFraction, 1, 0)
end

function TestFractional__add()
-- Does Fraction need to infer fraction from string representation?
--function TestFractional__new__fromString()
-- local f = Fraction:new("1/2")
-- lu.assertEquals(f:numerator(), 1)
-- lu.assertEquals(f:denominator(), 2)
--end

function TestFraction__add()
local f1 = Fraction:new(1,2)
local f2 = Fraction:new(1,2)
lu.assertEquals(f1+f2, Fraction:new(1))
Expand All @@ -49,7 +60,7 @@ function TestFractional__add()
lu.assertEquals(f1+f2, Fraction:new(1,6))
end

function TestFractional__sub()
function TestFraction__sub()
local f1 = Fraction:new(1,2)
local f2 = Fraction:new(1,2)
lu.assertEquals(f1-f2, Fraction:new(0))
Expand All @@ -63,7 +74,7 @@ function TestFractional__sub()
lu.assertEquals(f1-f2, Fraction:new(5,6))
end

function TestFractional__mult()
function TestFraction__mult()
local f1 = Fraction:new(1,2)
local f2 = Fraction:new(1,2)
lu.assertEquals(f1*f2, Fraction:new(1,4))
Expand All @@ -75,7 +86,7 @@ function TestFractional__mult()
lu.assertEquals(f1*f2, Fraction:new(-1,6))
end

function TestFractional__div()
function TestFraction__div()
local f1 = Fraction:new(1,2)
local f2 = Fraction:new(1,2)
lu.assertEquals(f1/f2, Fraction:new(1))
Expand All @@ -88,32 +99,31 @@ function TestFractional__div()
end


function TestFractional__mod()
function TestFraction__mod()
local f1 = Fraction:new(1,2)
local f2 = Fraction:new(2,3)
lu.assertEquals(f1%f2, Fraction:new(1,2))
f1 = Fraction:new(3,4)
f2 = Fraction:new(2,3)
-- 9/12 % 8/12 = 1/12
lu.assertEquals(f1%f2, Fraction:new(1,12))

end

function TestFractional__pow()
function TestFraction__pow()
local f1 = Fraction:new(1,4)
local f2 = Fraction:new(1,2)
lu.assertEquals(f1^f2, 0.5)
local f1 = Fraction:new(1,4)
local f2 = Fraction:new(2,1)
f1 = Fraction:new(1,4)
f2 = Fraction:new(2,1)
lu.assertEquals(f1^f2, Fraction:new(1,16))
end

function TestFractional__neg()
function TestFraction__neg()
local f1 = Fraction:new(1,4)
lu.assertEquals(-f1, Fraction:new(-1,4))
end

function TestFractional__floor()
function TestFraction__floor()
local f1 = Fraction:new(1,4)
lu.assertEquals(f1:floor(), 0)
f1 = Fraction:new(5,4)
Expand All @@ -122,5 +132,45 @@ function TestFractional__floor()
lu.assertEquals(f1:floor(), 2)
end

function TestFraction__gt()
lu.assertTrue(Fraction:new(3,4) > Fraction:new(1,3))
lu.assertTrue(Fraction:new(5,4) > Fraction:new(1,1))
lu.assertFalse(Fraction:new(1,3)> Fraction:new(1,2))
lu.assertFalse(Fraction:new(5,4)> Fraction:new(7,4))
end

function TestFraction__lt()
lu.assertTrue(Fraction:new(1,4) < Fraction:new(1,3))
lu.assertTrue(Fraction:new(1,4) < Fraction:new(1,3))
lu.assertTrue(Fraction:new(5,4) < Fraction:new(7,3))
lu.assertFalse(Fraction:new(2,3)< Fraction:new(1,2))
lu.assertFalse(Fraction:new(9,1)< Fraction:new(7,4))
end

function TestFraction__gte()
lu.assertTrue(Fraction:new(3,4) >= Fraction:new(1,3))
lu.assertTrue(Fraction:new(1,3) >= Fraction:new(1,3))
lu.assertTrue(Fraction:new(-1,3) >= Fraction:new(-7,3))
lu.assertTrue(Fraction:new(5,4) >= Fraction:new(5,4))
lu.assertFalse(Fraction:new(1,3)>= Fraction:new(1,2))
lu.assertFalse(Fraction:new(5,4)>= Fraction:new(7,4))
end

function TestFraction__lte()
lu.assertTrue(Fraction:new(1,4) <= Fraction:new(1,3))
lu.assertTrue(Fraction:new(1,4) <= Fraction:new(1,4))
lu.assertTrue(Fraction:new(5,4) <= Fraction:new(7,3))
lu.assertTrue(Fraction:new(-5,4) <= Fraction:new(7,3))
lu.assertFalse(Fraction:new(2,3)<= Fraction:new(1,2))
lu.assertFalse(Fraction:new(9,1)<= Fraction:new(7,4))
end

function TestFraction__eq()
lu.assertTrue(Fraction:new(1,4) == Fraction:new(1,4))
lu.assertTrue(Fraction:new(5,4) == Fraction:new(10,8))
lu.assertTrue(Fraction:new(-2,3)== Fraction:new(8,-12))
lu.assertTrue(Fraction:new(-1,3)== Fraction:new(-3,9))
lu.assertFalse(Fraction:new(254,255) == Fraction:new(255,256))
end

--os.exit( lu.LuaUnit.run() )
59 changes: 32 additions & 27 deletions test/time_span_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,57 @@ local lu = require('test/luaunit/luaunit')
require('src/time_span')

function TestTimeSpan_sam()
local f = Fraction:new(3,4)
local f = Fraction:new(3, 4)
local sam = TimeSpan:sam(f)
lu.assertEquals(sam,Fraction:new(0,1))
f = Fraction:new(5,4)
lu.assertEquals(sam, Fraction:new(0, 1))
f = Fraction:new(5, 4)
sam = TimeSpan:sam(f)
lu.assertEquals(sam,Fraction:new(1,1))
lu.assertEquals(sam, Fraction:new(1, 1))
end

function TestTimeSpan_nextSam()
local f = Fraction:new(3,4)
local f = Fraction:new(3, 4)
local sam = TimeSpan:nextSam(f)
lu.assertEquals(sam,Fraction:new(1,1))
f = Fraction:new(5,4)
lu.assertEquals(sam, Fraction:new(1, 1))
f = Fraction:new(5, 4)
sam = TimeSpan:nextSam(f)
lu.assertEquals(sam,Fraction:new(2,1))
lu.assertEquals(sam, Fraction:new(2, 1))
end

function TestTimeSpan_wholeCycle()
local ts = TimeSpan:new(Fraction:new(3,4), Fraction:new(4,4))
local cycle = ts:wholeCycle()
lu.assertEquals(cycle:beginTime(), Fraction:new(0))
lu.assertEquals(cycle:endTime(), Fraction:new(1))
function TestFractional__wholeCycle()
local f1 = Fraction:new(1, 2)
lu.assertEquals(TimeSpan:new(Fraction:new(0, 1), Fraction:new(1, 1)), TimeSpan:wholeCycle(f1))
f1 = Fraction:new(3, 2)
lu.assertEquals(TimeSpan:new(Fraction:new(1, 1), Fraction:new(2, 1)), TimeSpan:wholeCycle(f1))
end

function TestTimeSpan__create()
local ts = TimeSpan:create()
lu.assertEquals(Fraction:new(1), ts:beginTime())
lu.assertEquals(Fraction:new(1), ts:endTime())
lu.assertEquals(ts:beginTime(), Fraction:new(1))
lu.assertEquals(ts:endTime() , Fraction:new(1))
ts = TimeSpan:create{}
lu.assertEquals(Fraction:new(1), ts:beginTime())
lu.assertEquals(Fraction:new(1), ts:endTime())
lu.assertEquals(ts:beginTime(), Fraction:new(1))
lu.assertEquals(ts:endTime() , Fraction:new(1))
end

function TestTimeSpan__new()
local ts = TimeSpan:new(Fraction:new(3), Fraction:new(4))
lu.assertEquals(Fraction:new(3), ts:beginTime())
lu.assertEquals(Fraction:new(4), ts:endTime())
lu.assertEquals(ts:beginTime(), Fraction:new(3))
lu.assertEquals(ts:endTime() , Fraction:new(4))
end


-- function TestTimeSpan__spanCycles()
-- local ts = TimeSpan:new(Fraction:new(3), Fraction:new(4))
-- local spans = ts:spanCycles()
-- lu.assertEquals(Fraction:new(1), ts:beginTime())
-- lu.assertEquals(Fraction:new(1), ts:endTime())

-- end
function TestTimeSpan__spanCycles()
local ts = TimeSpan:new(Fraction:new(3, 4), Fraction:new(7, 2))
local spans = ts:spanCycles()
lu.assertEquals(4, #(spans))
lu.assertEquals(spans[1]:beginTime(), Fraction:new(3, 4))
lu.assertEquals(spans[1]:endTime() , Fraction:new(1, 1))
lu.assertEquals(spans[2]:beginTime(), Fraction:new(1, 1))
lu.assertEquals(spans[2]:endTime() , Fraction:new(2, 1))
lu.assertEquals(spans[3]:beginTime(), Fraction:new(2, 1))
lu.assertEquals(spans[3]:endTime() , Fraction:new(3, 1))
lu.assertEquals(spans[4]:beginTime(), Fraction:new(3, 1))
lu.assertEquals(spans[4]:endTime() , Fraction:new(7, 2))
end

--os.exit( lu.LuaUnit.run() )

0 comments on commit 1ee5d77

Please sign in to comment.