Advertisement
Guest User

soundlib.lua

a guest
Jan 28th, 2018
932
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.50 KB | None | 0 0
  1. local computer=require"computer"
  2. local component=require"component"
  3. local soundlib={}
  4. local sounds={}
  5. local function tcheck(x,t)
  6.   return type(x)==t
  7. end
  8. local smt={}
  9. function smt:play()
  10.   self.playing=true
  11. end
  12. function smt:pause()
  13.   self.playing=false
  14. end
  15. function smt:rewind()
  16.   self.rawpoint=0
  17. end
  18. function smt:stop()
  19.   self.playing=false
  20.   self.rawpoint=0
  21. end
  22. function smt:setVolume(n)
  23.   self.volume=tcheck(n,"number") and math.max(0,math.min(n,10))
  24. end
  25. function smt:getVolume(n)
  26.   return self.volume
  27. end
  28. function smt:getDuration()
  29.   return self.duration*self.delay/1000
  30. end
  31. function smt:seek()
  32.   return self.rawpoint*self.delay/1000
  33. end
  34. function smt:set(rawpos,wave,freq,vol)
  35.   if not(tcheck(rawpos,"number") and tcheck(wave,"string") and tcheck(freq,"number") and tcheck(vol,"number")) then
  36.     error("invalid args",-2)
  37.   end
  38.   if not(self.samples[wave]) or not(self.samples[wave][math.floor(rawpos)]) then
  39.     error("out of range",-2)
  40.   end
  41.   self.samples[wave][math.floor(rawpos)][1],self.samples[wave][math.floor(rawpos)][2]=freq,vol
  42.   return true
  43. end
  44. function smt:get(rawpos,wave,freq,vol)
  45.   if not(tcheck(rawpos,"number") and tcheck(wave,"string") and tcheck(freq,"number") and tcheck(vol,"number")) then
  46.     error("invalid args",-2)
  47.   end
  48.   if not(self.samples[wave]) or not(self.samples[wave][math.floor(rawpos)]) then
  49.     error("out of range",-2)
  50.   end
  51.   local sample=self.samples[wave][math.floor(rawpos)]
  52.   return sample[1],sample[2]
  53. end
  54. function smt:getCurrentSample()
  55.   return self.rawpos
  56. end
  57. function smt:getSampleCount()
  58.   return self.duration
  59. end
  60. function smt:setSeek(pos)
  61.   --if pos*1000 > self.duration*self.delay or pos < 0 then
  62.   --  error("out of range",-2)
  63.   --end
  64.   self.rawpoint=math.min(self.duration*self.delay,math.max(0,pos*1000))
  65. end
  66. function smt:isPlaying()
  67.   return self.playing
  68. end
  69. function smt:setLooping(bool)
  70.   self.rep=not not bool
  71. end
  72. function smt:isLooping()
  73.   return self.rep
  74. end
  75. function smt:destroy()
  76.   for k,v in pairs(sounds) do
  77.     if v==self then
  78.       sounds[k]=nil
  79.       break
  80.     end
  81.   end
  82. end
  83. function smt:isDestroyed()
  84.   for k,v in pairs(sounds) do
  85.     if v==self then
  86.       return false
  87.     end
  88.   end
  89.   return true
  90. end
  91. local s=false
  92. local prevaddress=false
  93. local inited=false
  94. local function middle(numbers)
  95.   local supernumber=0
  96.   local numbercount=0
  97.   for k,v in ipairs(numbers) do
  98.     supernumber=supernumber+v.num*v.power
  99.     numbercount=numbercount+v.power
  100.   end
  101.   return supernumber/numbercount
  102. end
  103. function soundlib.init()
  104.   if not (inited) and component.isAvailable("sound") then
  105.     inited=true
  106.     s=component.sound
  107.     prevaddress=s.address
  108.     return true
  109.   end
  110.   return false
  111. end
  112. function soundlib.getSoundsCount()
  113.   local n=0
  114.   for k,v in pairs(sounds) do
  115.     n=n+1
  116.   end
  117.   return n
  118. end
  119. function soundlib.deinit()
  120.   if inited then
  121.     inited=false
  122.     s=false
  123.     for k,v in pairs(sounds) do
  124.       sounds[k]=nil
  125.     end
  126.     prevaddress=false
  127.     return true
  128.   end
  129.   return false
  130. end
  131. function soundlib.isInited()
  132.   return inited
  133. end
  134. function soundlib.reinit()
  135.   soundlib.deinit()
  136.   return soundlib.init()
  137. end
  138. --[[ Формат объекта звука:
  139. sound={repeat=булиан,playing=булиан,rawpoint=0,duration=кол-во_сэмплов,delay=длительность_сэмплов_в_мс,samples={["тип_волны"]={{freq=частота,vol=громкость}}}}
  140. ]]
  141. function soundlib.newSound(size,delay)
  142.   if not(tcheck(size,"number") and tcheck(delay,"number")) then
  143.     error("invalid args",-2)
  144.   end
  145.   delay=math.max(1,math.min(delay*1000,100000))
  146.   local sound={rep=false,volume=1,prevproc=computer.uptime(),playing=false,rawpoint=0,duration=size,delay=delay}
  147.   sound.samples={square={},sine={},noise={},triangle={}}
  148.   for n=0,size-1 do
  149.     sound.samples.square[n]={0,0}
  150.   end
  151.   for n=0,size-1 do
  152.     sound.samples.sine[n]={0,0}
  153.   end
  154.   for n=0,size-1 do
  155.     sound.samples.noise[n]={0,0}
  156.   end
  157.   for n=0,size-1 do
  158.     sound.samples.triangle[n]={0,0}
  159.   end
  160.   setmetatable(sound,{__index=smt,__newindex=function()end,__metatable={}}) -- _metatable - защита от "хакеров", от которых может рухнуть вся система звуков
  161.   table.insert(sounds,sound)
  162.   return sound
  163. end
  164. function soundlib.process(times) -- Запускать как можно чаще
  165.   local ok=false
  166.   if inited and component.isAvailable("sound") then
  167.     s=component.sound
  168.     if s.address ~= prevaddress then
  169.       soundlib.reinit()
  170.     end
  171.     local modes={square={modeid=1,ch=1},noise={modeid=-1,ch=2},sine={modeid=2,ch=3},triangle={modeid=3,ch=4}}
  172.     for k,v in pairs(sounds) do xpcall(function()
  173.       for mname,mdata in pairs(modes) do
  174.         if v.samples[mname] and v.playing then
  175.           if (not v.samples[mname][math.floor(v.rawpoint)]) or v.rawpoint > v.duration then
  176.             if v.rep then
  177.               v.rawpoint=0
  178.             else
  179.               v.rawpoint=0 v.playing=false
  180.             end
  181.           end
  182.           if v.playing then
  183.             local sample=v.samples[mname][math.floor(v.rawpoint)]
  184.             if sample[1] and sample[2] and sample[2] > 0 and sample[1] > 0 then
  185.               mdata.volume=(mdata.volume or 0)+sample[2]*v.volume
  186.               mdata.freqs=mdata.freqs or {}
  187.               table.insert(mdata.freqs,{num=math.max(0,math.min(sample[1],20000)),power=math.floor(sample[2]*v.volume*100)})
  188.             else
  189.               --print("No playing sounds")
  190.             end
  191.             v.prevproc=v.prevproc or computer.uptime()
  192.             local tm=computer.uptime()-v.prevproc
  193.             v.rawpoint=v.rawpoint+tm*1000*v.delay
  194.             --print(v.rawpoint)
  195.             v.prevproc=computer.uptime()
  196.           end
  197.         end
  198.       end
  199.     end,function(err) print("Sound system errored in sound processing: "..err) end) end
  200.     local sounders=0
  201.     for mname,mdata in pairs(modes) do
  202.       if mdata.freqs and mdata.volume then
  203.         sounders=sounders+1
  204.       end
  205.     end
  206.     for mname,mdata in pairs(modes) do xpcall(function()
  207.       if mdata.freqs and mdata.volume then
  208.         local freq=middle(mdata.freqs)
  209.         s.setWave(mdata.ch,mdata.modeid)
  210.         s.setFrequency(mdata.ch,freq)
  211.         s.open(mdata.ch)
  212.         s.delay(times/sounders)
  213.         s.setVolume(mdata.ch,mdata.volume)
  214.         s.close(mdata.ch)
  215.         while not s.process() do end
  216.         --print(mdata.ch,mdata.volume,freq,require("serialization").serialize(mdata.freqs))
  217.       end
  218.     end,function(err) print("Sound system errored in sound sending: "..err) end) end
  219.     ok=true
  220.   else
  221.     ok=false
  222.   end
  223.   if not component.isAvailable("sound") then
  224.     soundlib.deinit()
  225.   else
  226.     soundlib.init()
  227.   end
  228.   return ok
  229. end
  230. return soundlib
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement