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 |