local type,rem=type,table.remove local rnd=math.random local sfxList={} local packSetting={} local Sources={} local volume=1 local stereo=1 local noteName={ C=1,c=1, D=3,d=3, E=5,e=5, F=6,f=6, G=8,g=8, A=10,a=10, B=12,b=12, } local function _getTuneHeight(tune) local octave=tonumber(tune:sub(-1,-1)) if octave then local tuneHeight=noteName[tune:sub(1,1)] if tuneHeight then tuneHeight=tuneHeight+(octave-1)*12 local s=tune:sub(2,2) if s=='s'or s=='#'then tuneHeight=tuneHeight+1 elseif s=='f'or s=='b'then tuneHeight=tuneHeight-1 end return tuneHeight end end end local SFX={} function SFX.init(list) assert(type(list)=='table',"Initialize SFX lib with a list of filenames!") for i=1,#list do table.insert(sfxList,list[i])end end function SFX.load(path) local c=0 for i=1,#sfxList do local fullPath=path..sfxList[i]..'.ogg' if love.filesystem.getInfo(fullPath)then Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')} c=c+1 else LOG("No SFX: "..sfxList[i]..'.ogg',.1) end end LOG(c.."/"..#sfxList.." SFX files loaded") end function SFX.loadSample(pack) assert(type(pack)=='table',"Usage: SFX.loadsample([table])") assert(pack.name,"No field: name") assert(pack.path,"No field: path") local num=1 while love.filesystem.getInfo(pack.path..'/'..num..'.ogg')do Sources[pack.name..num]={love.audio.newSource(pack.path..'/'..num..'.ogg','static')} num=num+1 end local base=(_getTuneHeight(pack.base)or 37)-1 local top=base+num-1 packSetting[pack.name]={base=base,top=top} LOG((num-1).." "..pack.name.." samples loaded") end function SFX.getCount() return #sfxList end function SFX.setVol(v) assert(type(v)=='number'and v>=0 and v<=1) volume=v end function SFX.setStereo(v) assert(type(v)=='number'and v>=0 and v<=1) stereo=v end function SFX.playSample(pack,...)--vol-2, sampSet1, vol-3, sampSet2, vol-1 if ... then local arg={...} local vol if type(arg[#arg])=='number'then vol=rem(arg)end for i=1,#arg do if type(arg[i])=='number'then vol=arg[i] else local base=packSetting[pack].base local top=packSetting[pack].top local tune=_getTuneHeight(arg[i])--Absolute tune in number local playTune=tune+rnd(-2,2) if playTune<=base then--Too low notes playTune=base+1 elseif playTune>top then--Too high notes playTune=top end print('play:',playTune) print('delta',tune-playTune) SFX.play(pack..playTune-base,vol,nil,tune-playTune) end end end end function SFX.play(name,vol,pos,pitch) if volume==0 or vol==0 then return end local S=Sources[name]--Source list if not S then return end local n=1 while S[n]:isPlaying()do n=n+1 if not S[n]then S[n]=S[1]:clone() S[n]:seek(0) break end end S=S[n]--AU_SRC if S:getChannelCount()==1 then if pos then pos=pos*stereo S:setPosition(pos,1-pos^2,0) else S:setPosition(0,0,0) end end S:setVolume(((vol or 1)*volume)^1.626) S:setPitch(pitch and 1.0594630943592953^pitch or 1) S:play() end function SFX.fplay(name,vol,pos) local S=Sources[name]--Source list if not S then return end local n=1 while S[n]:isPlaying()do n=n+1 if not S[n]then S[n]=S[1]:clone() S[n]:seek(0) break end end S=S[n]--AU_SRC if S:getChannelCount()==1 then if pos then pos=pos*stereo S:setPosition(pos,1-pos^2,0) else S:setPosition(0,0,0) end end S:setVolume(vol^1.626) S:play() end function SFX.reset() for _,L in next,Sources do if type(L)=='table'then for i=#L,1,-1 do if not L[i]:isPlaying()then rem(L,i) end end end end end return SFX