Skip to content

Instantly share code, notes, and snippets.

@SwadicalRag
Last active December 30, 2021 09:21
Show Gist options
  • Save SwadicalRag/3479530980b2f46d98dd555470d983a0 to your computer and use it in GitHub Desktop.
Save SwadicalRag/3479530980b2f46d98dd555470d983a0 to your computer and use it in GitHub Desktop.
Panasonic Voice Recorder Triple Rate Codec Decoder (for VM1 files) - uses LuaJIT FFI to call native code
-- saved at 12000Hz, 16 bit PCM, little endian
local vcName = "SD_VC001"
local folder = "SD_VOICE/"..vcName
ffi=require'ffi'
ffi.cdef [[
void vInitDecoder(void);
void vDecode(uint8_t* param_1,uint8_t *param_2);
void vSet_volume(uint32_t param_1,uint32_t param_2);
]]
function fileExists(name) local f = io.open(name,"rb") if f ~= nil then io.close(f) return true else return false end end
local trc = ffi.load("trcL.dll")
local rawMetadataF = io.open(folder.."/SD_VOICE.TKM","rb")
local rawMetadata = rawMetadataF:read("*a")
rawMetadataF:close()
local metadata = {}
for entry in rawMetadata:gmatch("TRC_HQ_(%d+/%d+/%d+ %d+%:%d+)\\TRC") do
metadata[#metadata + 1] = entry
end
local clk = os.clock()
local fileIdx = 1
while true do
trc.vInitDecoder()
trc.vSet_volume(0x400,0x40)
local input = ffi.new("uint8_t[?]",8192)
local output = ffi.new("uint8_t[?]",8192)
local infile = io.open(string.format(folder.."/MOB%03d.VM1",fileIdx),"rb")
if infile == nil then print("Job complete!") break end
local outfileName = string.format("output/OUT_"..vcName.."_MOB%03d.pcm",fileIdx)
local outfile = io.open(outfileName,"wb")
print(string.format("Processing file "..folder.."/MOB%03d.VM1 (%s)",fileIdx,metadata[fileIdx] or "???"))
local curFileMetadata = metadata[fileIdx]
fileIdx = fileIdx + 1
-- Dump first 512 bytes
infile:read(512)
local complete_input = {}
local len = 0
while true do
local b = infile:read(1)
if b == nil then break end
complete_input[len] = string.byte(b)
len = len + 1
end
infile:close()
local loc = 0
while true do
local cancel = false
-- fill frame buffer
for i=1,0x200 do
if complete_input[i-1 + loc] == nil then cancel = true break end
input[i-1] = complete_input[i-1 + loc]
end
if cancel then break end
loc = loc + 0x200
local remaining = 0x200
local cur_loc = 0
while remaining >= 0x18 do
local bytesPerFrameRef = 0x18
if fin then break end
local cur_input = ffi.cast("uint8_t*",input) + cur_loc
local bVar1 = bit.band(cur_input[0], 0xc0)
local ok = false
if (bVar1 == 0) or (bVar1 == 0x40) then
ok = true
else
bytesPerFrameRef = 8
if bVar1 == 0x80 then
ok = true
end
end
if ok then
trc.vDecode(output,cur_input)
for i=1,0x140 do
outfile:write(string.char(output[i-1]))
end
bytesPerFrameRef = 0x18
end
cur_loc = cur_loc + bytesPerFrameRef
remaining = remaining - bytesPerFrameRef
end
if (os.clock() - clk) > 1 then
print(string.format("Decoding %.02f%%...",loc / #complete_input * 100))
clk = os.clock()
end
end
outfile:close()
local niceOutFile = curFileMetadata or outfileName:gsub("%.pcm$","")
niceOutFile = niceOutFile:gsub("[/:]","-")
while fileExists("output/"..niceOutFile..".mp3") do niceOutFile = niceOutFile.."-copy" end
print("ffmpeg -f s16le -ar 12k -ac 1 -i "..outfileName.." \"output/"..niceOutFile..".mp3\"")
os.execute("ffmpeg -f s16le -ar 12k -ac 1 -i "..outfileName.." \"output/"..niceOutFile..".mp3\"")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment