From b6289fd8ccf3fc2645b139a49d5154da8e58656c Mon Sep 17 00:00:00 2001 From: Kimapr Date: Sun, 26 May 2024 17:27:13 +0500 Subject: [PATCH] initial --- main.lua | 96 ++++++++++++++++++++++++ soundgen.lua | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++ sounds/1.lua | 40 ++++++++++ sounds/2.lua | 15 ++++ sounds/3.lua | 7 ++ sounds/4.lua | 9 +++ sounds/5.lua | 8 ++ sounds/6.lua | 16 ++++ sounds/7.lua | 29 ++++++++ sounds/8.lua | 19 +++++ sounds/9.lua | 25 +++++++ 11 files changed, 468 insertions(+) create mode 100644 main.lua create mode 100644 soundgen.lua create mode 100644 sounds/1.lua create mode 100644 sounds/2.lua create mode 100644 sounds/3.lua create mode 100644 sounds/4.lua create mode 100644 sounds/5.lua create mode 100644 sounds/6.lua create mode 100644 sounds/7.lua create mode 100644 sounds/8.lua create mode 100644 sounds/9.lua diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..5950902 --- /dev/null +++ b/main.lua @@ -0,0 +1,96 @@ +soundgen=require "soundgen" +love.window.setMode(800,600,{resizable=true}) + +function znoise(...) + return love.math.noise(...)*2-1 +end + +local sdata +local source + +function love.keypressed(k) + local p="sounds/"..k..".lua" + if love.filesystem.getInfo(p) and k~="0" and k~="space" then + if source then + source:stop() + source=nil + sdata=nil + end + package.loaded.soundgen=nil + soundgen=require"soundgen" + local ok,err=xpcall(function()return dofile("sounds/"..k..".lua")end,debug.traceback) + if ok and err then + print("booooom") + sdata=err + source=love.audio.newSource(sdata) + source:setLooping(true) + source:play() + else + print("bad",ok,source,err) + end + elseif k=="0" then + if source then + source:stop() + source=nil + sdata=nil + end + elseif k=="space" then + if source then + local _ = source:isPlaying() and {source:pause()} or source:play() + end + end +end +local l1={} +local l2={} +local res=4096 +local chanc=0 +local upd=nil +local pitch=1 +function love.mousemoved(x,y,dx,dy) + local w,h=love.graphics.getDimensions() + local dy=-dy/h*2*(math.abs(pitch)+.1) + if love.mouse.isDown(1) then + pitch=math.min(10,math.max(-10,pitch+dy)) + end +end +function love.update(dt) + local w,h=love.graphics.getDimensions() + local rate=sdata and sdata:getSampleRate() or 0 + chanc=sdata and sdata:getChannelCount() or 1 + local s2i=chanc==2 + if source then + source:setPitch(math.max(0.001,pitch)) + if pitch<0.001 then + source:seek(math.max(0,source:tell()+pitch*dt)) + end + end + local ma=sdata and sdata:getSampleCount() or 1 + for n=1,res do + local sami=(source and source:tell("samples") or 0)-math.floor(rate*((n-1)/(res-1))*0.05) + sami=sami%ma + l1[(n-1)*2+1],l1[(n-1)*2+2] + =w-(n-1)/(res-1)*w,(sdata and (-sdata:getSample(s2i and sami*2 or sami)*0.5*0.5+0.5) or 0.5)*h + if s2i then + l2[(n-1)*2+1],l2[(n-1)*2+2] + =w-(n-1)/(res-1)*w,(sdata and (-sdata:getSample(sami*2+1)*0.5*0.5+0.5) or 0.5)*h + end + end + upd=true +end +function love.draw() + love.graphics.print(pitch) + love.graphics.push("all") + love.graphics.setLineJoin("none") + love.graphics.setLineWidth(1) + love.graphics.setLineStyle("rough") + if chanc==1 then + love.graphics.setColor(1,1,1) + love.graphics.line(l1) + elseif chanc==2 then + love.graphics.setColor(0.8,0.8,1) + love.graphics.line(l1) + love.graphics.setColor(1,0.8,0.8) + love.graphics.line(l2) + end + love.graphics.pop() +end diff --git a/soundgen.lua b/soundgen.lua new file mode 100644 index 0000000..e172d5d --- /dev/null +++ b/soundgen.lua @@ -0,0 +1,204 @@ +local smt={} +smt.__index=smt +smt.proto=smt + +local function round(x) + return math.floor(x+.5) +end + +function smt:bounds_and(a,b,c,...) + if not a or not b then return false end + local mi,ma + mi=math.max(a[1],b[1]) + ma=math.min(a[2],b[2]) + if ma-mi<=0 then return false end + if c then + return self:bounds_and({mi,ma},c,...) + end + return {mi,ma} +end + +function smt:bounds_or(a,b,c,...) + local mi,ma=math.min(a[1],b[1]),math.max(a[2],b[2]) + if not a then return b end + if not b then return a end + if c then + return self:bounds_or({mi,ma},c,...) + end + return {mi,ma} +end + +function smt:new(fn,bounds) + local obj={} + obj.bounds=bounds + if obj.bounds==nil then + obj.bounds={-math.huge,math.huge} + end + obj.sample=fn + return setmetatable(obj,self.proto) +end + +function smt:sine() + return self:new(function(self,t) + return math.sin(t*math.pi*2) + end) +end + +function smt:square() + return self:new(function(self,t) + return (t%1)<=0.5 and -1 or 1 + end) +end + +function smt:sawtooth() + return self:new(function(self,t) + return (t%1)*2-1 + end) +end + +function smt:triangle() + return self:new(function(self,t) + --return ((t%1)<=0.5 and (t*2)%1 or 1-(t*2)%1)*2-1 -- sounds cool and glitchy but wrong + local a=t%1 + if a>0.5 then + return (1-(a*2-1))*2-1 + end + return (a*2)*2-1 + end) +end + +function smt:noise(y,z,x) + return self:new(function(self,t) + return love.math.noise(t,y,z,x)*2-1 + end) +end + +function smt:silence(a) + a=a or 0 + return smt:new(function()return a end) +end + +local function rated_bounds(bounds,rate) + local mi,ma=bounds[1],bounds[2] + mi,ma=mi*rate,ma*rate + mi,ma=round(mi),round(ma)-1 + return mi,ma +end + +local function prefi(y) + return math.min(1,math.max(-1,y)) +end + +function smt:compile(rate,bits,alt) + rate=rate or 44100 + bits=bits or 16 + local bounds=self.bounds + local mi,ma=rated_bounds(bounds,rate) + if alt then + bounds=self:bounds_and(bounds,alt.bounds) + local mi,ma=rated_bounds(bounds,rate) + local sdata=love.sound.newSoundData(ma-mi+1,rate,bits,2) + for x=mi,ma do + local x=x+mi + sdata:setSample(x*2,prefi(self:sample(x/rate+0.5/rate))) + sdata:setSample(x*2+1,prefi(alt:sample(x/rate+0.5/rate))) + end + return sdata + end + local sdata=love.sound.newSoundData(ma-mi+1,rate,bits,1) + for x=mi,ma do + local xx=x-mi + sdata:setSample(xx,prefi(self:sample(x/rate+0.5/rate))) + end + return sdata +end + +function smt:phase(p) + local bb=self.bounds + if bb then + bb={bb[1]-p,bb[2]-p} + end + return self:new(function(obj,t) + return self:sample(t+p) + end,bb) +end + +function smt:amp(a) + return self:new(function(obj,t) + return self:sample(t)*a + end,self.bounds) +end + +function smt:freq(f) + local bb=self.bounds + if bb then + bb={bb[1]/f,bb[2]/f} + if bb[2]ma then return 0 end + return self.sample(self,t) + end,self:bounds_and(self.bounds,{mi,ma})) +end + +function smt.am(car,mod,mi,ma) + return smt:new(function(self,t) + return car:sample(t)*((mod:sample(t)*0.5+0.5)*(ma-mi)+mi) + end,car:bounds_and(car.bounds,mod.bounds)) +end + +function smt.pm(car,mod,mi,ma) + assert(car.bounds + and car.bounds[1]==-math.huge + and car.bounds[2]==math.huge, + "infinite carrier expected") + mod=mod:add(mod:silence()) + return smt:new(function(self,t) + return car:sample(t+((mod:sample(t)*0.5+0.5)*(ma-mi)+mi)) + end,car.bounds) +end + +function smt.add(a,b,...) + if not b then + if not a then return smt:silence() end + return a + end + local ls={a,b,...} + local bbs={} + for k,v in pairs(ls) do + bbs[k]=v.bounds + end + return smt:new(function(self,t) + local r=0 + for k,v in pairs(ls) do + r=r+v:sample(t) + end + return r + end,a:bounds_or(unpack(bbs))) +end + +do + local fwav=smt:sine():phase(0.75):freq(0.25) + fwav=fwav:clamp(0,1) + fwav=fwav:add(smt:silence(-1):clamp(-math.huge,0)) + function smt.fade(wave,ma,mi) + local ff=fwav:freq(1/(mi-ma)):phase(-ma) + return wave:am(ff,1,-1) + end +end + +function smt.fm(car,mod,rate,mi,ma) -- TODO + local cframe,cache=0,{} + return smt.new(function(self,t) + end,mod.bounds) +end + +return smt diff --git a/sounds/1.lua b/sounds/1.lua new file mode 100644 index 0000000..fcf549d --- /dev/null +++ b/sounds/1.lua @@ -0,0 +1,40 @@ +local rate=44100 +local len=1 +local bfreq=500 +local lacu,pers=1.5,0.5 +local octas=4 +local rta=0 +local oofs={} +math.randomseed(os.time()) +do + local pe=1 + for n=1,octas do + oofs[n]=math.random()*2-1 + rta=rta+(pe) + pe=pe*pers + end +end +local sd=love.sound.newSoundData(rate*len,rate,16,1) +local function gsample(t) + local arg=(bfreq*(t^((1+math.sin(t*2*math.pi)*0.1)*love.math.noise(t*0.1-0.05,5244,love.math.noise(t*1000,2949)*0.01-0.005)))) + --print(arg) + local nn=0 + local pe=1/rta + local ao=1 + for n=1,octas do + local nnn=znoise(arg*ao,n/5+oofs[n])*pe + --nn=math.max(-1,math.min(1,nn+nnn)) + nn=nn+nnn + --print(n,nn,nnn,pe,ao) + pe=pe*pers + ao=ao*lacu + end + nn=nn*0.5+znoise((1-t)^(math.sin(t*math.pi*10*math.cos(t*10))*1+6+znoise(423,5453,t*1000)*0.05)*1000)*0.5 + nn=nn*1.5 + return (nn*(1-t)^5)*(math.min(1,math.max(t*100))^0.5) +end +for n=0,len*rate-1 do + local a=gsample(n/(rate)) + sd:setSample(n,a) +end +return sd diff --git a/sounds/2.lua b/sounds/2.lua new file mode 100644 index 0000000..cff639c --- /dev/null +++ b/sounds/2.lua @@ -0,0 +1,15 @@ +local ss= + soundgen:sine():freq(100) + :pm(soundgen:sine():freq(50),-0.01,0.01) + :pm(soundgen:sine():freq(50.5):pm(soundgen:sine():freq(1000):am(soundgen:sine():freq(10),0.4,0.6),-0.0001,0.0001),-0.01,0.01) + :pm(soundgen:sine():freq(0.5):phase(0.4552),0,0.01) + :am(soundgen:sine():freq(500):pm(soundgen:sine():freq(50),-0.015,0.015),0.5,1) + :clamp(0,2):amp(0.5):add( + soundgen:sine():freq(2500) + :pm(soundgen:sine():freq(100) + :am(soundgen:sine():freq(100),-0.01,0.01) + ,-0.1,0.1):amp(0.05):am(soundgen:sine():freq(50),0,1):am(soundgen:sine():freq(0),0.5,1) + :clamp(0,2) + ) + :compile() +return ss diff --git a/sounds/3.lua b/sounds/3.lua new file mode 100644 index 0000000..e603495 --- /dev/null +++ b/sounds/3.lua @@ -0,0 +1,7 @@ +local sg=soundgen +local ss= + sg:sine():freq(1000):pm(sg:sine():freq(105.46):am(sg:sine():freq(505.3),-1,1),-0.001,0.001) + :am(sg:sine():freq(500),-2,0.1) + :am(sg:sine():phase(0.25):freq(0.5):clamp(0,0.5):freq(0.5):freq(3):add(sg:silence(-1)),0,1):clamp(0,1) + :compile() +return ss diff --git a/sounds/4.lua b/sounds/4.lua new file mode 100644 index 0000000..0469abc --- /dev/null +++ b/sounds/4.lua @@ -0,0 +1,9 @@ +local sg=soundgen +return + sg:square():freq(1000) + :pm(sg:sine():phase(0.5):freq(0.1):am(sg:sine():freq(100),0,0.1),-0.05,0.05) + :am(sg:sine():freq(200),-1,1):amp(0.4):am(sg:sine():freq(150):pm(sg:sine():freq(0.5),-0.1,0.1),0.25,1) + --:clamp(0,10) + :fade(0.01,0):fade(0.01,0.5):add(sg:silence()):clamp(0,2) + :compile() + diff --git a/sounds/5.lua b/sounds/5.lua new file mode 100644 index 0000000..d18b95f --- /dev/null +++ b/sounds/5.lua @@ -0,0 +1,8 @@ +local sg=soundgen +--[[local sine=sg:sine():freq(800) +for n=1,8 do + sine=sine:am(sg:sine():freq(50*2^n):phase(n/8),0.85-(2^-n),0.85+(2^-n)):pm(sg:sine():freq(4*2^(n*0.99)):phase(1/n),-0.004/(n*0.8),0.004/(n*0.8)) +end]] +local sine=sg:noise(0):freq(200):pm(sg:noise():freq(5000),-1/500,1/500):am(sg:sine():freq(150),0.2,1):am(sg:sine():phase(0.2):clamp(0,0.27):freq(2):add(sg:silence(0)),-1,1) +sine=sine:clamp(0,1):freq(0.5) +return sine:compile() diff --git a/sounds/6.lua b/sounds/6.lua new file mode 100644 index 0000000..9b66ce7 --- /dev/null +++ b/sounds/6.lua @@ -0,0 +1,16 @@ +local sg=soundgen +local wave=sg.add( + sg:sine():freq(1):amp(0.1), + sg:sine():freq(2):amp(0.1), + sg:sine():freq(4):amp(0.1), + sg:sine():freq(8):amp(0.1), + sg:sine():freq(16):amp(0.1), + sg:sine():freq(32):amp(0.1), + sg:sine():freq(64):amp(0.1), + sg:sine():freq(128):amp(0.1), + sg:sine():freq(256):amp(0.1), + sg:sine():freq(512):amp(0.1), + sg:sine():freq(1024):amp(0.1) +) +wave=wave:clamp(0,10) +return wave:compile(44100,16) diff --git a/sounds/7.lua b/sounds/7.lua new file mode 100644 index 0000000..65167d3 --- /dev/null +++ b/sounds/7.lua @@ -0,0 +1,29 @@ +local sg=soundgen +local fade +do + local fwav=sg:sine():phase(0.75):freq(0.25) + fwav=fwav:clamp(0,1) + fwav=fwav:add(sg:silence(-1):clamp(-math.huge,0)) + function fade(wave,ma,mi) + local ff=fwav:freq(1/(mi-ma)):phase(-ma) + return wave:am(ff,1,-1) + end +end +local function new() + local wave=sg:noise():phase(math.random()*1000):freq(1000):amp(0.25) + :pm(sg:triangle():freq(50):am(sg:silence(1):fade(0,0.04),-1,1),-0.01,0.01) + :add(sg:sine():amp(0.55):freq(50):pm(sg:noise():freq(500):phase(0.834715384),-0.01,0.01)) + wave=wave:fade(0,0.1) + wave=wave:fade(0.001,0) + return wave +end +local waves={} +for n=0,1-1 do + waves[#waves+1]=new():phase(-n*0.1):amp(0.3) +end +local wave=sg:silence():clamp(0,1):add(unpack(waves)) +return wave:compile() + + + + diff --git a/sounds/8.lua b/sounds/8.lua new file mode 100644 index 0000000..0e154f6 --- /dev/null +++ b/sounds/8.lua @@ -0,0 +1,19 @@ +local sg=soundgen +local waves={} +local function sign(n) + return n>0 and 1 or (n<0 and -1 or 0) +end +for n=1,32 do + local a=sg:noise(0):phase(n):freq(50*2^(n^0.8*2)):amp(0.5^(n/2)^1.2) + local b=sg:noise(0):freq(50*n) + waves[n]=sg:new(function(self,t) + local aa=(n)/100 + local t=t + local y=a:sample(t^(0.15*((n-1)^1.1/30+1))+b:sample(t)*aa) + return math.abs(y)^2*sign(y) + end) +end +local wave=sg.add(unpack(waves)):amp(1.2) +wave=wave:fade(0.001,0) +wave=wave:fade(0.001,0.5) +return wave:compile() diff --git a/sounds/9.lua b/sounds/9.lua new file mode 100644 index 0000000..4cd25cd --- /dev/null +++ b/sounds/9.lua @@ -0,0 +1,25 @@ +local sg=soundgen +local wave=sg:square():freq(50*(1+math.random()*0.4-0.2)):phase(math.random()) +local wave=sg:new(function(self,t) + local ttcc,ttt=0,0 + for n=1,20 do + local ttc,tt=0,0 + local ma=1/(512+math.random()*256-128) + local st=ma/2 + for n=-ma,ma,st do + ttc=ttc+1 + tt=tt+wave:sample(t+n) + end + ttcc,ttt=ttcc+1,tt/ttc + end + return ttt/ttcc +end) +--wave=wave:pm(wave:am(sg:sine():freq(70):phase(math.random()),0,1),-0.01,0.01) +--wave=wave:pm(sg:noise():phase(0.5+math.random()*100):freq(3000):am(wave,-0.1,0.1),-0.005,0.005) +local wave=sg:new(function(self,t) + return wave:sample((t/4)^0.5*4) +end) +--wave=wave:amp(0.5):add(sg:sine():freq(102):pm(sg:sine():freq(49),-0.01,0.01):amp(0.5)) +wave=wave:fade(0.001,0) +wave=wave:fade(0.001,0.5) +return wave:compile()