|
1 | | -# BMS to RPP v0.8 |
| 1 | +# BMS to RPP v0.82 |
2 | 2 | # Copyright (C) 2020 shockdude |
3 | 3 | # REAPER is property of Cockos Incorporated |
4 | 4 |
|
|
23 | 23 | from pydub import AudioSegment |
24 | 24 |
|
25 | 25 | def usage(): |
26 | | - print("BMS to RPP v0.8") |
| 26 | + print("BMS to RPP v0.82") |
27 | 27 | print("Convert a BMS or DTX chart into a playable REAPER project") |
28 | 28 | print("WAV keysounds recommended, OGG keysounds require ffmpeg/avconv and are slow to parse.") |
29 | 29 | print("Usage: {} chart_file.bms [output_filename.rpp]".format(sys.argv[0])) |
@@ -113,73 +113,62 @@ def find_tag(line, tag): |
113 | 113 | return line[len(tag):] |
114 | 114 | return None |
115 | 115 |
|
| 116 | +# parse header value |
| 117 | +def get_header_value(line, header): |
| 118 | + header_re = re.compile("#{}([\\w\\d][\\w\\d])(:\\s*|\\s+)(.+)\\s*".format(header)) |
| 119 | + re_match = header_re.match(line) |
| 120 | + if re_match != None and re_match.start() == 0: |
| 121 | + index = re_match.group(1) |
| 122 | + value = re_match.group(3) |
| 123 | + return index, value |
| 124 | + return None, None |
| 125 | + |
116 | 126 | # create dictionary of keysounds |
117 | 127 | def add_keysound(line): |
118 | | - wav_re = re.compile("#WAV[\\w\\d][\\w\\d]") |
119 | | - re_match = wav_re.match(line) |
120 | | - if re_match != None and re_match.start() == 0: |
121 | | - line_split = line.split(" ") |
122 | | - keysound_index = line_split[0][-2:] |
123 | | - keysound_origname = " ".join(line_split[1:]).strip() |
124 | | - # look for wav or ogg, even if the original chart uses a different format |
125 | | - keysound_basename = os.path.splitext(keysound_origname)[0] |
| 128 | + index, value = get_header_value(line, "WAV") |
| 129 | + if index != None and value != None: |
| 130 | + keysound_basename = os.path.splitext(value)[0] |
126 | 131 | keysound_filename = keysound_basename + WAV_EXT |
127 | 132 | if os.path.isfile(keysound_filename): |
128 | | - keysound_dict[keysound_index] = keysound_filename |
| 133 | + keysound_dict[index] = keysound_filename |
129 | 134 | return True |
130 | 135 | keysound_filename = keysound_basename + OGG_EXT |
131 | 136 | if os.path.isfile(keysound_filename): |
132 | | - keysound_dict[keysound_index] = keysound_filename |
| 137 | + keysound_dict[index] = keysound_filename |
133 | 138 | return True |
134 | 139 | print("Error: could not find .wav or .ogg for {}".format(keysound_origname)) |
135 | 140 | usage() |
136 | 141 | return False |
137 | 142 |
|
138 | 143 | # create dictionary of keysound volume percentages |
139 | 144 | def add_keysoundvolume(line): |
140 | | - bpm_re = re.compile("#VOLUME[\\w\\d][\\w\\d]") |
141 | | - re_match = bpm_re.match(line) |
142 | | - if re_match != None and re_match.start() == 0: |
143 | | - line_split = line.split(" ") |
144 | | - vol_index = line_split[0][-2:] |
145 | | - vol = float(line_split[1].strip()) / 100.0 |
146 | | - keysoundvol_dict[vol_index] = vol |
| 145 | + index, value = get_header_value(line, "VOLUME") |
| 146 | + if index != None and value != None: |
| 147 | + keysoundvol_dict[index] = float(value) / 100.0 |
147 | 148 | return True |
148 | 149 | return False |
149 | 150 |
|
150 | 151 | # create dictionary of keysound pan percentages |
151 | 152 | def add_keysoundpan(line): |
152 | | - bpm_re = re.compile("#PAN[\\w\\d][\\w\\d]") |
153 | | - re_match = bpm_re.match(line) |
154 | | - if re_match != None and re_match.start() == 0: |
155 | | - line_split = line.split(" ") |
156 | | - pan_index = line_split[0][-2:] |
157 | | - pan = float(line_split[1].strip()) / 100.0 |
158 | | - keysoundpan_dict[pan_index] = pan |
| 153 | + index, value = get_header_value(line, "PAN") |
| 154 | + if index != None and value != None: |
| 155 | + keysoundpan_dict[index] = float(value) / 100.0 |
159 | 156 | return True |
160 | 157 | return False |
161 | 158 |
|
162 | 159 | # create dictionary of extended bpm values |
163 | 160 | def add_bpmvalue(line): |
164 | | - bpm_re = re.compile("#BPM[\\w\\d][\\w\\d]") |
165 | | - re_match = bpm_re.match(line) |
166 | | - if re_match != None and re_match.start() == 0: |
167 | | - line_split = line.split(" ") |
168 | | - bpmvalue_index = line_split[0][-2:] |
169 | | - bpmvalue = float(line_split[1].strip()) |
170 | | - extbpm_dict[bpmvalue_index] = bpmvalue |
| 161 | + index, value = get_header_value(line, "BPM") |
| 162 | + if index != None and value != None: |
| 163 | + extbpm_dict[index] = float(value) |
171 | 164 | return True |
172 | 165 | return False |
173 | 166 |
|
174 | 167 | # create dictionary of stop values |
175 | 168 | def add_stopvalue(line): |
176 | | - bpm_re = re.compile("#STOP[\\w\\d][\\w\\d]") |
177 | | - re_match = bpm_re.match(line) |
178 | | - if re_match != None and re_match.start() == 0: |
179 | | - line_split = line.split(" ") |
180 | | - stopvalue_index = line_split[0][-2:] |
181 | | - stopvalue = float(line_split[1].strip()) |
182 | | - stop_dict[stopvalue_index] = stopvalue |
| 169 | + index, value = get_header_value(line, "STOP") |
| 170 | + if index != None and value != None: |
| 171 | + stop_dict[index] = float(value) |
183 | 172 | return True |
184 | 173 | return False |
185 | 174 |
|
@@ -222,27 +211,26 @@ def update_data(data1, data2): |
222 | 211 | def add_channel(line): |
223 | 212 | global max_measure |
224 | 213 | # use regular expression to match the channel format |
225 | | - note_re = re.compile("#\\d\\d\\d\\d\\d:") |
| 214 | + note_re = re.compile("#(\\d\\d\\d[\\d\\w][\\d\\w])(:\\s*|\\s+)(\\S+)") |
226 | 215 | re_match = note_re.match(line) |
227 | 216 | if re_match != None and re_match.start() == 0: |
228 | | - line_split = line.split(":") |
229 | | - header = line_split[0][1:] |
| 217 | + header = re_match.group(1) |
230 | 218 | measure = int(header[0:3]) |
231 | 219 | channel = header[3:5] |
232 | | - data = line_split[1].strip() |
233 | | - data_array = data_to_array(data) |
| 220 | + data = re_match.group(3) |
234 | 221 |
|
235 | 222 | # set the largest measure found |
236 | 223 | if measure > max_measure: |
237 | 224 | max_measure = measure |
238 | 225 |
|
239 | | - # channel with data array |
240 | 226 | if parsing_mode == MODE_BMS: |
241 | 227 | playable_channels = BMS_PLAYABLE_CHANNELS |
242 | 228 | elif parsing_mode == MODE_DTX: |
243 | 229 | playable_channels = DTX_PLAYABLE_CHANNELS |
244 | | - |
| 230 | + |
| 231 | + # check for channel with data array |
245 | 232 | if channel in (playable_channels + (BPM_CHANNEL, EXTBPM_CHANNEL, STOP_CHANNEL)) and data != "00": |
| 233 | + data_array = data_to_array(data) |
246 | 234 | if channel == "01": |
247 | 235 | # bgm tracks are special and shouldn't be merged |
248 | 236 | # dictionary maps to array of arrays instead |
|
0 commit comments