View difference between Paste ID: yf013znn and QrZ33T6H
SHOW: | | - or go back to the newest paste.
1-
local note_lookup_table = {
1+
-- make global functions local for faster lookup
2-
	['1000'] = '4',    ['0100'] = '2',
2+
local table = table
3-
	['0010'] = '8',    ['0001'] = '6',
3+
local append, concat = table.insert, table.concat
4-
	['1100'] = '1',    ['1010'] = '7',
4+
local string = string
5-
	['1001'] = 'B',    ['0110'] = 'A',
5+
local sub, gsub, lower = string.sub, string.gsub, string.lower
6-
	['0101'] = '3',    ['0011'] = '9',
6+
local find, match, gmatch = string.find, string.match, string.gmatch
7-
	['1110'] = '<81>', ['0111'] = '<83>',
7+
local ipairs, pairs = ipairs, pairs
8-
	['1101'] = '<61>', ['1011'] = '<8B>',
8+
9-
	['1111'] = '<19>', ['0000'] = '0',
9+
local function file_search(filter, dir_path)
10-
}
10+
	local function c_in(value, tab)
11
		for _, v in pairs(tab) do
12-
function string:getFieldContents(field)
12+
			if v == value then return true end
13-
	local _, idx = self:find('#' .. field .. ':')
13+
14-
	local str = self:match('%b:;', idx)
14+
		return false
15-
	return str:sub(2, #str - 1)
15+
16
17
	function string:split(sep)
18
		local sep, fields = sep or ":", {}
19
		local pattern = string.format("([^%s]+)", sep)
20
		self:gsub(pattern, function(c) fields[#fields+1] = c end)
21
		return fields
22-
		table.insert(beat_notes, note_lookup_table[note])
22+
23-
		table.insert(beat_notes, '') -- for possible note padding
23+
24
	local fs = require 'lfs'
25
	local filter = string.lower(filter) or "*"
26
	local dir_path = dir_path or fs.currentdir()
27
	local extensions = filter:split(";")
28
29-
	elseif note_count == 8 then 
29+
	local files = {}
30
	for _, path in ipairs(dir_path:split(";")) do
31
		for f in fs.dir(path) do
32-
		beat_notes[1] = '['; table.insert(beat_notes, ']')
32+
			if f ~= "." and f ~= ".." then
33
				local attr = fs.attributes(path..'\\'..f)
34-
		beat_notes[1] = '('; table.insert(beat_notes, ')')
34+
				if attr.mode == "file" then
35
					if filter=="*" or 
36-
		beat_notes[1] = '['; table.insert(beat_notes, ']')
36+
					c_in(lower(f:match('%.%w*$')), extensions) then
37
						append(files, {path = path..'\\', name = f})
38
					end
39-
		beat_notes[1] = '{'; table.insert(beat_notes, '}')
39+
				elseif attr.mode == "directory" then
40
					local subf = file_search(filter, path..'\\'..f)
41
					for _, v in ipairs(subf) do
42-
		beat_notes[1] = '`'; table.insert(beat_notes, '\'')
42+
						append(files, {path = v.path, name = v.name})
43
					end
44-
		beat_notes[1] = '{'; table.insert(beat_notes, '}')
44+
				end
45
			end
46
		end
47-
		beat_notes[1] = '`'; table.insert(beat_notes, '\'')
47+
48
	return files
49-
		beat_notes[1] = '`'; table.insert(beat_notes, '\'')
49+
50
51
local function processMeasure(measure)
52
	local note_lookup_table = {
53
		['1000'] = '4',    ['0100'] = '2',
54-
	return table.concat(beat_notes) .. '\n'
54+
		['0010'] = '8',    ['0001'] = '6',
55
		['1100'] = '1',    ['1010'] = '7',
56
		['1001'] = 'B',    ['0110'] = 'A',
57
		['0101'] = '3',    ['0011'] = '9',
58
		['1110'] = '<81>', ['0111'] = '<83>',
59
		['1101'] = '<61>', ['1011'] = '<8B>',
60
		['1111'] = '<19>', ['0000'] = '0',
61-
		local tmp = io.open(full_path .. '.sm')
61+
	}
62
	local beat_notes = {''} -- reserve beat_notes[1] for opening tag if necessary
63
	local note_count = 0
64
65
	for note in measure:gmatch('%d%d%d%d') do
66
		append(beat_notes, note_lookup_table[note])
67
		append(beat_notes, '') -- for possible note padding
68
		note_count = note_count + 1
69
	end
70
71-
		if idx then
71+
72-
			changebpm = changebpm:sub(idx + 1)
72+
73-
		else 
73+
	elseif note_count == 8 then
74-
			changebpm = '' 
74+
75
		for i=3, 25, 2 do beat_notes[i] = '0' end
76
		beat_notes[1] = '['; append(beat_notes, ']')
77
	elseif note_count == 16 then
78-
	-- multiply all measures by 4 to convert to beat counts
78+
		beat_notes[1] = '('; append(beat_notes, ')')
79-
	local changebpm_str = {}
79+
80-
	if changebpm ~= '' then
80+
		beat_notes[1] = '['; append(beat_notes, ']')
81-
		for beat, bpm, comma in changebpm:gmatch('(%d+%.?%d*)%s*(=%s*%d+%.?%d*)(,?)') do
81+
82-
			table.insert(changebpm_str, string.format("%.3f", tonumber(beat) * 4)..bpm)
82+
83-
			if comma ~= '' then table.insert(changebpm_str, ',') end
83+
		beat_notes[1] = '{'; append(beat_notes, '}')
84
	elseif note_count == 48 then
85
		for i=3, 97, 2 do beat_notes[i] = '000' end
86
		beat_notes[1] = '`'; append(beat_notes, '\'')
87
	elseif note_count == 64 then
88
		beat_notes[1] = '{'; append(beat_notes, '}')
89-
	table.insert(file_contents, '#TITLE:'		  .. sm_file:getFieldContents('TITLE')					  .. ';\n')
89+
90-
	table.insert(file_contents, '#ARTIST:'		  .. sm_file:getFieldContents('ARTIST')					  .. ';\n')
90+
91-
	table.insert(file_contents, '#FILE:'		  .. sm_file:getFieldContents('MUSIC')					  .. ';\n')
91+
		beat_notes[1] = '`'; append(beat_notes, '\'')
92-
	table.insert(file_contents, '#BPM:'			  .. start_bpm											  .. ';\n')
92+
93-
	table.insert(file_contents, '#GAP:'			  .. tonumber(sm_file:getFieldContents('OFFSET')) * -1000 .. ';\n')
93+
		beat_notes[1] = '`'; append(beat_notes, '\'')
94-
	table.insert(file_contents, '#SAMPLESTART:'	  .. sm_file:getFieldContents('SAMPLESTART')			  .. ';\n')
94+
95-
	table.insert(file_contents, '#SAMPLELENGTH:'  .. sm_file:getFieldContents('SAMPLELENGTH')			  .. ';\n\n')
95+
96-
	if changebpm ~= '' then
96+
97-
		table.insert(file_contents, '#CHANGEBPM:' .. table.concat(changebpm_str)						  .. ';\n')
97+
98
	return concat(beat_notes) .. '\n'
99-
	table.insert(file_contents, '#SINGLE:MANIAC:1:\n')
99+
100
101-
	do -- extract start of note data to end of file
101+
-------------------------------------------------------------------------------------------------
102-
		local _, idx = sm_file:find('%d+%.%d+%s*%:', idx)
102+
103-
		sm_file = sm_file:sub(idx + 1)
103+
104
	-- open sm file to read contents into string
105
	local sm_file
106
	do
107-
		table.insert(file_contents, processMeasure(measure))
107+
		local tmp = io.open(full_path)
108
		sm_file = tmp:read('*a')
109
		tmp:close()
110-
	-- save converted file
110+
111-
	local dwi_file = io.open(full_path .. '.dwi', 'w')
111+
112-
	dwi_file:write(table.concat(file_contents)..'\n')
112+
	function string:getFieldContents(field)
113-
	dwi_file:close()
113+
		local _, idx = self:find('#'..field..':')
114
		local str = self:match('%b:;', idx)
115
		return str:sub(2, #str - 1)
116-
smToDwi('test')
116+
117
118
	local changebpm = sm_file:getFieldContents('BPMS')
119
	local start_bpm
120
	do -- separate first bpm and bpm changes
121
		start_bpm = changebpm:match('%d+%.?%d*%s*=%s*(%d+%.?%d*)')
122
		local _, idx = changebpm:find('%d+%.?%d*%s*=%s*%d+%.?%d*%s*,')
123
124
		if idx then	changebpm = changebpm:sub(idx + 1)
125
		else changebpm = ''	end
126
	end
127
128
	if changebpm then -- multiply all measures by 4 to convert to beats
129
		changebpm = changebpm:gsub('(%d+%.?%d*)(%s*=%s*%d+%.?%d*,?)', function(beat, bpm) 
130
			return string.format('%.3f', beat * 4)..bpm
131
		end)
132
	end
133
134
	-- process common .sm file fields
135
	local file_contents = {}
136
	append(file_contents, '#TITLE:'			.. sm_file:getFieldContents('TITLE')					.. ';\n')
137
	append(file_contents, '#ARTIST:'		.. sm_file:getFieldContents('ARTIST')					.. ';\n')
138
	append(file_contents, '#FILE:'			.. sm_file:getFieldContents('MUSIC')					.. ';\n')
139
	append(file_contents, '#BPM:'			.. start_bpm											.. ';\n')
140
	append(file_contents, '#GAP:'			.. tonumber(sm_file:getFieldContents('OFFSET')) * -1000 .. ';\n')
141
	append(file_contents, '#SAMPLESTART:'	.. sm_file:getFieldContents('SAMPLESTART')				.. ';\n')
142
	append(file_contents, '#SAMPLELENGTH:'  .. sm_file:getFieldContents('SAMPLELENGTH')				.. ';\n\n')
143
	if changebpm then
144
		append(file_contents, '#CHANGEBPM:' .. changebpm											.. ';\n')
145
	end
146
	append(file_contents, '#SINGLE:MANIAC:1:\n')
147
148
	sm_file = sm_file:match(':.+$') -- extract start of note data to end of file
149
150
	for measure in sm_file:gmatch('.-[,;]') do
151
		append(file_contents, processMeasure(measure))
152
	end
153
154
	do -- save converted file
155
		local contents = concat(file_contents)
156
		local dwi_file = io.open(full_path:gsub('%.%w*$', '.dwi'), 'w')
157
		dwi_file:write(contents..'\n')
158
		dwi_file:close()
159
	end
160
end
161
162
-------------------------------------------------------------------------------------------------
163
164
for _, file in ipairs(file_search('.sm;.ssc;.ds')) do
165
	smToDwi(file.path .. file.name)
166
end