170 lines
4.5 KiB
Lua
170 lines
4.5 KiB
Lua
local type,rem=type,table.remove
|
|
local floor,rnd=math.floor,math.random
|
|
|
|
local sfxList={}
|
|
local packSetting={}
|
|
local Sources={}
|
|
local volume=1
|
|
local stereo=1
|
|
|
|
local noteVal={
|
|
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 noteName={'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'}
|
|
local function _getTuneHeight(tune)
|
|
local octave=tonumber(tune:sub(-1,-1))
|
|
if octave then
|
|
local tuneHeight=noteVal[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
|
|
local missing=0
|
|
for i=1,#sfxList do
|
|
local fullPath=path..sfxList[i]..'.ogg'
|
|
if love.filesystem.getInfo(fullPath) then
|
|
if Sources[sfxList[i]] then
|
|
for j=1,#Sources[sfxList[i]] do
|
|
Sources[sfxList[i]][j]:release()
|
|
end
|
|
end
|
|
Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')}
|
|
c=c+1
|
|
else
|
|
LOG("No SFX: "..sfxList[i]..'.ogg',.1)
|
|
missing=missing+1
|
|
end
|
|
end
|
|
LOG(c.."/"..#sfxList.." SFX files loaded")
|
|
LOG(missing.." SFX files missing")
|
|
if missing>0 then
|
|
MES.new('info',missing.." SFX files missing")
|
|
end
|
|
collectgarbage()
|
|
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,'Wrong volume')
|
|
volume=v
|
|
end
|
|
function SFX.setStereo(v)
|
|
assert(type(v)=='number' and v>=0 and v<=1,'Wrong stereo')
|
|
stereo=v
|
|
end
|
|
|
|
function SFX.getNoteName(note)
|
|
if note<1 then
|
|
return '---'
|
|
else
|
|
note=note-1
|
|
local octave=floor(note/12)+1
|
|
return noteName[note%12+1]..octave
|
|
end
|
|
end
|
|
function SFX.playSample(pack,...)-- vol-1, sampSet1, vol-2, sampSet2
|
|
if ... then
|
|
local arg={...}
|
|
local vol
|
|
for i=1,#arg do
|
|
local a=arg[i]
|
|
if type(a)=='number' and a<=1 then
|
|
vol=a
|
|
else
|
|
local base=packSetting[pack].base
|
|
local top=packSetting[pack].top
|
|
local tune=type(a)=='string' and _getTuneHeight(a) or a-- 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
|
|
SFX.play(pack..playTune-base,vol,nil,tune-playTune)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local function _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=MATH.clamp(pos,-1,1)*stereo
|
|
S:setPosition(pos,1-pos^2,0)
|
|
else
|
|
S:setPosition(0,0,0)
|
|
end
|
|
end
|
|
S:setVolume(vol^1.626)
|
|
S:setPitch(pitch and 1.0594630943592953^pitch or 1)
|
|
S:play()
|
|
end
|
|
SFX.fplay=_play-- Play sounds without apply module's volume setting
|
|
function SFX.play(name,vol,pos,pitch)
|
|
_play(name,(vol or 1)*volume,pos,pitch)
|
|
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
|