local function num2float (c) -- http://stackoverflow.com/questions/18886447/convert-signed-ieee-754-float-to-hexadecimal-representation if c == 0 then return 0.0 end local c = string.gsub(string.format("%X", c),"(..)",function (x) return string.char(tonumber(x, 16)) end) local b1,b2,b3,b4 = string.byte(c, 1, 4) local sign = b1 > 0x7F local expo = (b1 % 0x80) * 0x2 + math.floor(b2 / 0x80) local mant = ((b2 % 0x80) * 0x100 + b3) * 0x100 + b4 if sign then sign = -1 else sign = 1 end local n if mant == 0 and expo == 0 then n = sign * 0.0 elseif expo == 0xFF then if mant == 0 then n = sign * math.huge else n = 0.0/0.0 end else n = sign * math.ldexp(1.0 + mant / 0x800000, expo - 0x7F) end return n end local function int2char(int) return string.char(int%256)..string.char(math.floor(int/256%256))..string.char(math.floor(int/256/256%256))..string.char(math.floor(int/256/256/256)) end local function char2int(char) return char:sub(1,1):byte()+char:sub(2,2):byte()*256+char:sub(3,3):byte()*65536+char:sub(4,4):byte()*16777216 end function getWAVTempo(wav,verbose) local vp=function() end local f if verbose then vp=print end vp("getWAVTempo start!") if type(wav)=="userdata" then vp("#1 type is userdata. Assuming it's a file type!") f=wav else vp("#1 type is string. It's path to wav file") f=assert(io.open(wav,"rb")) end if verbose then vp=function(txt) print("["..string.format("%08X",f:seek("cur")).."] "..txt) end end local curSeek=f:seek("cur") local fileSize=f:seek("end") f:seek("set") if f:read(12)=="RIFF"..int2char(fileSize-8).."WAVE" then vp("WAV File header correct. Reading chunks!") while(f:seek("cur")~=fileSize)do local chunk=f:read(4) if(chunk=="acid")then vp("\"acid\" chunk found. Getting tempo data!") f:read(24) tempo=num2float(char2int(f:read(4))) vp("Tempo data found!") if type(wav)=="string" then f:close() else f:seek("set",curSeek) end return tempo else local size=char2int(f:read(4)) vp("\""..chunk.."\" chunk found with size of "..size..". Skipping...") if size%2==1 then size=size+1 end f:seek("cur",size) end end else error("Invalid wav file!") end if verbose then print("Tempo data not found!") end if type(wav)=="userdata"then f:seek(curSeek) else f:close() end return 0 end
What do you need to do is:
- Save code above to file
- dofile it
- call getWAVTempo(file[,verbose])
getWAVTempo Parameters:
file - file handle(from io.open) or string to filename
verbose - show more message. If you set this to true, you can see what's going on. - a. If it returns 0, then the wav file does not come with embedded tempo data
b. If it returns value more than 0, then that's the tempo. Please note that the decimals is stripped on return.
Feel free to use some (or all) parts of code above.
No comments:
Post a Comment