-- title: wavetest2 -- author: mieki256 -- desc: SFX wave maker -- script: lua WAVADR=0x0ffe4 waveid=4 vol=1.0 adjust_enable=false maxi=false oct=4 mode=0 playing=true setwave=false t=0 freqtbl={ {fs=1, mul=1.0, sft=0, kind=0}, {fs=2, mul=0.0, sft=0, kind=0}, {fs=3, mul=0.0, sft=0, kind=0}, {fs=4, mul=0.0, sft=0, kind=0}, {fs=5, mul=0.0, sft=0, kind=0}, {fs=6, mul=0.0, sft=0, kind=0}, {fs=7, mul=0.0, sft=0, kind=0}, {fs=8, mul=0.0, sft=0, kind=0}, {fs=9, mul=0.0, sft=0, kind=0}, {fs=10, mul=0.0, sft=0, kind=0}, } function makeWaveArray(p) dt={} local ang,v,fs for i=0,31 do ang = i * 360 / 32 v = 0 for j,d in ipairs(freqtbl) do fs = d.fs * p if d.kind==0 then v = v + getSin(ang, d.mul, fs, d.sft) elseif d.kind==1 then v = v + getSquare(ang, d.mul, fs, d.sft) elseif d.kind==2 then v = v + getSaw(ang, d.mul, fs, d.sft) elseif d.kind==3 then v = v + getTri(ang, d.mul, fs, d.sft) else v = v + getSin(ang, d.mul, fs, d.sft) end end v = vol * v table.insert(dt,v) end return dt end function makeWave() local odt = makeWaveArray(1.0) return odt end function getSin(ang, m, fs, sft) return m * math.sin(math.rad(fs * ang + sft)) end function getSquare(ang, m, fs, sft) local a = (fs * ang + sft) % 360 return m * ((a < 180) and 1.0 or -1.0) end function getSaw(ang, m, fs, sft) local v = (((fs * ang + sft) % 360) / 180) - 1.0 return m * v end function getTri(ang, m, fs, sft) local v = (fs * ang + sft) % 360 if v < 180 then v = (v % 180) / 90 - 1.0 else v = (2.0 - (v % 180) / 90) - 1.0 end return m * v end function resetFreqtbl() for i,d in ipairs(freqtbl) do d.mul=0.0 d.sft=0 d.kind=0 end freqtbl[1].mul=1.0 vol=1.0 end function writeWave(id,dt) -- adjust if id < 0 or id > 15 then return end if #dt>32 then return end if not adjust_enable then for i=1,#dt do dt[i] = math.floor(15 * (0.5 * dt[i] + 0.5) + 0.5) if dt[i] < 0 then dt[i] = 0 end if dt[i] > 15 then dt[i] = 15 end end else -- adjust enable local vmax,vmin vmax=0 vmin=0 for i=1,#dt do if dt[i]>vmax then vmax=dt[i] end if dt[i] 15 then dt[i] = 15 end end end -- write wave local addr=WAVADR+id*16 for i=1,#dt,2 do local v=0 v = v | ((dt[i+1] & 0x0f)<<4) v = v | (dt[i] & 0x0f) poke(addr+((i-1)//2),v) end end function drawGuide(bx,by,w,h) local x0,y0,x1,y1 local c=3 x0,x1=bx,bx+w*32-2 y0=by+h*8-1 line(x0,y0,x1,y0,c) y0=by+h*4-1 line(x0,y0,x1,y0,c) y0=by+h*12-1 line(x0,y0,x1,y0,c) x0=bx+w*16-1 y0,y1=by,by+h*16-2 line(x0,y0,x0,y1,c) x0=bx+w*8-1 line(x0,y0,x0,y1,c) x0=bx+w*24-1 line(x0,y0,x0,y1,c) end function drawWave(id) -- read wave local addr=WAVADR+id*16 local dt={} for i=0,15 do local v=peek(addr+i) local v1=v&0x0f local v2=(v>>4)&0x0f table.insert(dt,v1) table.insert(dt,v2) end -- draw wave local bx,by,w,h if maxi then bx,by,w,h=24,12,6,6 else bx,by,w,h=24,12,4,4 end local x,y for ix=0,31 do x = ix * w + bx for iy=0,15 do y = iy * h + by rect(x,y,w,h,0) rect(x,y,w-1,h-1,1) end y=(15-dt[ix+1])*h+by rect(x,y,w-1,h-1,6) end drawGuide(bx,by,w,h) end Button={} Button.new=function() local o={} o.lst={ {id=0,x=8*6, y=0, w=6,h=6,on=false,sts=false,str="<"}, {id=1,x=11*6,y=0, w=6,h=6,on=false,sts=false,str=">"}, {id=2,x=13*6,y=0, w=6*4,h=6,on=false,sts=false,str="READ"}, {id=3,x=18*6,y=0, w=6*4,h=6,on=false,sts=false,str="MAKE"}, {id=4,x=23*6,y=0, w=6*4,h=6,on=false,sts=false,str="PLAY"}, {id=5,x=28*6,y=0, w=6*4,h=6,on=false,sts=false,str="STOP"}, {id=6,x=33*6,y=0, w=6*4,h=6,on=false,sts=false,str="Sync"}, {id=7,x=0,y=6*19, w=6*4,h=6,on=false,sts=false,str="RSET"}, {id=8,x=6*0, y=6*14, w=6,h=6,on=false,sts=false,str="<"}, {id=9,x=6*2, y=6*14, w=6,h=6,on=false,sts=false,str=">"}, {id=10,x=0,y=6*17, w=6*4,h=6,on=false,sts=false,str="AJST"}, {id=11,x=0,y=6*2, w=6*4,h=6,on=false,sts=false,str="MAXI"}, } return setmetatable(o,{__index=Button}) end Button.update=function(self) local mx,my,md=mouse() local ret=-1 for i,d in ipairs(self.lst) do if d.x <= mx and mx <= d.x+d.w and d.y <= my and my <= d.y+d.h then d.on=true if d.sts then if not md then d.sts = false end else if md then ret=d.id d.sts=true end end else d.on=false d.sts=false end end return ret end Button.draw=function(self) local fg for i,d in ipairs(self.lst) do fg=7 if d.id==2 or d.id==3 then fg = (mode==(d.id-2)) and 15 or 7 elseif d.id==4 then if playing==true then fg=15 end elseif d.id==5 then if playing==false then fg=15 end elseif d.id==10 then if adjust_enable then fg=15 end elseif d.id==11 then if maxi then fg=15 end end if d.on then fg=10 end print(d.str,d.x,d.y,fg,true) end end Freq={} Freq.new=function() local o={} local y,bh,wy -- y,bh,wy = 12+6*16+1,20,136-5 y,bh,wy = 12+4*16+4,40,136-5 wy = y + bh + 4 o.tbl={ {bx=24+6*2,by=y,w=6,h=bh}, {bx=24+6*2+6*10+8,by=y,w=6,h=bh}, {bx=24+6*2,by=wy,w=6,h=6}, {bx=24+6*0,by=y,w=6,h=bh}, } o.kindsts={} for i=1,#freqtbl do table.insert(o.kindsts, false) end o.value=0 return setmetatable(o,{__index=Freq}) end Freq.chkBar=function(self,x,y,w,h,mx,my,ml,mm,mr) local k=0 local v=0.0 if x<=mx and mx<=x+w-2 and y<=my and my<=y+h-1 then if ml then v=(y+(h/2)-my)/(h/2); k=1 elseif mm then v=0.0; k=2 end end return k,v end Freq.update=function(self) local setfg=false local x,mx,my,ml,mm,mr,k,v mx,my,ml,mm,mr=mouse() for mode,d in ipairs(self.tbl) do if mode==4 then x=d.bx k,v = self:chkBar(x,d.by,d.w,d.h,mx,my,ml,mm,mr) if k>0 then vol=v+1.0; self.value=vol; setfg=true; break end else for i,dd in ipairs(freqtbl) do x = d.bx + d.w * (i-1) if mode==1 then k,v = self:chkBar(x,d.by,d.w,d.h,mx,my,ml,mm,mr) if k>0 then dd.mul=v; self.value=v; setfg=true; break end elseif mode==2 then k,v = self:chkBar(x,d.by,d.w,d.h,mx,my,ml,mm,mr) if k>0 then dd.sft=180*v; self.value=dd.sft; setfg=true; break end elseif mode==3 then k,v = self:chkBar(x,d.by,d.w,d.h,mx,my,ml,mm,mr) if k<=0 then self.kindsts[i]=false else if not self.kindsts[i] then self.kindsts[i]=true dd.kind=(dd.kind+1)%4; setfg=true; break end end end end end end return setfg end Freq.drawBar=function(self,x,y,w,h,v) rect(x,y,w-1,h,7) local ly=y+(h/2) local vy=y+(h/2)-(h/2)*v line(x,ly,x+w-2,ly,8) line(x,vy,x+w-2,vy,15) end Freq.draw=function(self) local bx,by,w,h,x,y,v for mode,d in ipairs(self.tbl) do if mode==3 then for i,dd in ipairs(freqtbl) do x = d.bx + d.w * (i-1) spr(32+dd.kind,x,d.by,0,1,0,0,1,1) end elseif mode==4 then self:drawBar(d.bx,d.by,d.w,d.h,vol-1.0) elseif mode==1 then for i,dd in ipairs(freqtbl) do x = d.bx + d.w * (i-1) self:drawBar(x,d.by,d.w,d.h,dd.mul) end elseif mode==2 then for i,dd in ipairs(freqtbl) do x = d.bx + d.w * (i-1) self:drawBar(x,d.by,d.w,d.h,dd.sft/180) end end end local s="Value:"..string.format("%.3f",self.value) local sw=print(s,0,-6) print(s,240-sw,136-6) end SyncDispObj={} SyncDispObj.new=function() local o={step=0,t=0,y=136,str="SFX Sync"} return setmetatable(o,{__index=SyncDispObj}) end SyncDispObj.update=function(self) local ct=15 if self.step==0 then return end if self.step==1 then self.y=136-8*(self.t/ct) if self.t>=ct then self.t=0; self.step=self.step+1 end elseif self.step==2 then if self.t>=60 then self.t=0; self.step=self.step+1 end elseif self.step==3 then self.y=136-8+8*(self.t/ct) if self.t>=ct then self.t=0; self.step=self.step+1 end elseif self.step==4 then self.y=136 self.t=0; self.step=0 end self.t=self.t+1 end SyncDispObj.draw=function(self) if self.step==0 then return end rect(0,self.y,240,8,6) local w=print(self.str,0,-6,15,true) print(self.str,(240-w)/2,self.y+1,15,true) end SyncDispObj.display=function(self,_str) self.step=1 self.t=0 self.str=_str end function setMakeMode() if waveid<4 then syncdisp:display("WAVE ID 0-3 can not be changed") else mode=1; setwave=true end end syncdisp=SyncDispObj.new() btn=Button.new() freq=Freq.new() function TIC() setwave=false local r = btn:update() if r==0 then waveid=(waveid-1) % 16; mode=0 elseif r==1 then waveid=(waveid+1) % 16; mode=0 elseif r==2 then mode=0 elseif r==3 then setMakeMode() elseif r==4 then playing=true; t=0 elseif r==5 then playing=false elseif r==6 then -- write to cart sync(1<<3,0,true) syncdisp:display("Sync SFX") elseif r==7 then -- reset freqtbl resetFreqtbl() setMakeMode() elseif r==8 then if oct>1 then oct=oct-1 end elseif r==9 then if oct<8 then oct=oct+1 end elseif r==10 then adjust_enable = not adjust_enable; setwave=true elseif r==11 then maxi = not maxi end if freq:update() then if mode==0 then setMakeMode() else setwave=true end end if setwave and waveid >=4 then dt=makeWave() writeWave(waveid,dt) end if t%60==0 and playing then sfx(waveid,"A-"..oct,45,0) end syncdisp:update() cls(0) freq:draw() btn:draw() drawWave(waveid) local s="" s=s.."WAVE ID: "..string.format("%02d",waveid) print(s,0,0,15,true) print("OCT",0,6*13-2) print(oct,6,6*14,15,true) syncdisp:draw() t=t+1 end