import os import json import yaml import subprocess import xml.etree.ElementTree as ET import shutil def parse_mmp_file(file_path): try: tree = ET.parse(file_path) root = tree.getroot() bpm = root.find('./head').attrib.get('bpm', 'N/A') tracks = root.findall('./song/trackcontainer/track') track_info = [] for track in tracks: track_name = track.attrib.get('name', 'N/A') track_type = track.attrib.get('type') instruments = [] if track_type == '0': # plugin track_info.append({ 'track_name': track_name, 'type': 'plugin', 'instruments': [], }) elif track_type == '1': # Beat/Bassline bbtrack = track.find('./bbtrack') if bbtrack is not None: bbtrack_info = [] for container in bbtrack.findall('./trackcontainer'): for instrument_track in container.findall('./track'): instrument_info = {} instrument_info['instrument_name'] = instrument_track.attrib.get('name', 'N/A') # Extraindo informações do instrumenttrack instrumenttrack = instrument_track.find('./instrumenttrack') if instrumenttrack is not None: instrument_info['pitch'] = instrumenttrack.attrib.get('pitch', '') instrument_info['pan'] = instrumenttrack.attrib.get('pan', '') instrument_info['vol'] = instrumenttrack.attrib.get('vol', '') instrument_info['pitchrange'] = instrumenttrack.attrib.get('pitchrange', '') instrument_info['basenote'] = instrumenttrack.attrib.get('basenote', '') instrument_info['fxch'] = instrumenttrack.attrib.get('fxch', '') instrument_info['usemasterpitch'] = instrumenttrack.attrib.get('usemasterpitch', '') # Extraindo dados de audiofileprocessor audiofileprocessor = instrument_track.find('.//audiofileprocessor') if audiofileprocessor is not None: instrument_info['audiofileprocessor'] = { 'amp': audiofileprocessor.attrib.get('amp', ''), 'src': audiofileprocessor.attrib.get('src', ''), 'lframe': audiofileprocessor.attrib.get('lframe', ''), 'stutter': audiofileprocessor.attrib.get('stutter', ''), 'interp': audiofileprocessor.attrib.get('interp', ''), 'sframe': audiofileprocessor.attrib.get('sframe', ''), 'looped': audiofileprocessor.attrib.get('looped', ''), 'eframe': audiofileprocessor.attrib.get('eframe', ''), 'reversed': audiofileprocessor.attrib.get('reversed', ''), } # Extraindo dados de eldata eldata = instrument_track.find('./eldata') if eldata is not None: eldata_info = { 'fwet': eldata.attrib.get('fwet', ''), 'ftype': eldata.attrib.get('ftype', ''), 'fcut': eldata.attrib.get('fcut', ''), 'fres': eldata.attrib.get('fres', ''), } elvol = eldata.find('./elvol') if elvol is not None: eldata_info['elvol'] = { 'sustain': elvol.attrib.get('sustain', ''), 'lamt': elvol.attrib.get('lamt', ''), 'lshp': elvol.attrib.get('lshp', ''), 'amt': elvol.attrib.get('amt', ''), 'pdel': elvol.attrib.get('pdel', ''), 'lpdel': elvol.attrib.get('lpdel', ''), 'lspd_numerator': elvol.attrib.get('lspd_numerator', ''), 'lspd_syncmode': elvol.attrib.get('lspd_syncmode', ''), 'latt': elvol.attrib.get('latt', ''), 'ctlenvamt': elvol.attrib.get('ctlenvamt', ''), 'x100': elvol.attrib.get('x100', ''), 'dec': elvol.attrib.get('dec', ''), 'hold': elvol.attrib.get('hold', ''), 'rel': elvol.attrib.get('rel', ''), 'lspd_denominator': elvol.attrib.get('lspd_denominator', ''), 'userwavefile': elvol.attrib.get('userwavefile', ''), 'att': elvol.attrib.get('att', ''), 'lspd': elvol.attrib.get('lspd', '') } # Extrair elcut e elres se existirem de maneira similar # Extraindo dados de chordcreator chordcreator = instrument_track.find('./chordcreator') if chordcreator is not None: chordcreator_info = { 'chord_enabled': chordcreator.attrib.get('chord-enabled', ''), 'chordrange': chordcreator.attrib.get('chordrange', ''), 'chord': chordcreator.attrib.get('chord', '') } instrument_info['chordcreator'] = chordcreator_info # Extraindo dados de arpeggiator arpeggiator = instrument_track.find('./arpeggiator') if arpeggiator is not None: arpeggiator_info = { 'arptime': arpeggiator.attrib.get('arptime', ''), 'arpmode': arpeggiator.attrib.get('arpmode', ''), 'arp': arpeggiator.attrib.get('arp', ''), 'arprange': arpeggiator.attrib.get('arprange', '') } instrument_info['arpeggiator'] = arpeggiator_info # Extraindo dados de midiport midiport = instrument_track.find('./midiport') if midiport is not None: midiport_info = { 'outputprogram': midiport.attrib.get('outputprogram', ''), 'inputchannel': midiport.attrib.get('inputchannel', ''), 'outputcontroller': midiport.attrib.get('outputcontroller', ''), 'inputcontroller': midiport.attrib.get('inputcontroller', ''), 'outputchannel': midiport.attrib.get('outputchannel', ''), 'writable': midiport.attrib.get('writable', ''), 'fixedinputvelocity': midiport.attrib.get('fixedinputvelocity', ''), 'basevelocity': midiport.attrib.get('basevelocity', ''), 'readable': midiport.attrib.get('readable', ''), 'fixedoutputvelocity': midiport.attrib.get('fixedoutputvelocity', ''), 'fixedoutputnote': midiport.attrib.get('fixedoutputnote', '') } instrument_info['midiport'] = midiport_info # Adicionando o instrumento ao bbtrack_info bbtrack_info.append(instrument_info) track_info.append({ 'track_name': track_name, 'type': 'bassline', 'instruments': bbtrack_info, }) elif track_type == '2': # Sample sampletrack = track.find('./sampletrack') sample_info = {} if sampletrack is not None: sample_info['pan'] = sampletrack.attrib.get('pan', '') sample_info['vol'] = sampletrack.attrib.get('vol', '') sampletco = track.find('./sampletco') if sampletco is not None: sample_info['src'] = sampletco.attrib.get('src', '') sample_info['len'] = sampletco.attrib.get('len', '') sample_info['sample_rate'] = sampletco.attrib.get('sample_rate', '') sample_info['pos'] = sampletco.attrib.get('pos', '') sample_info['muted'] = sampletco.attrib.get('muted', '') track_info.append({ 'track_name': track_name, 'type': 'sample', 'sample_info': sample_info, }) return { 'file': file_path, 'bpm': bpm, 'tracks': track_info } except ET.ParseError as e: print(f'Erro ao analisar o arquivo XML {file_path}: {e}') return None def save_to_json(data, output_file): with open(output_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) def save_to_yaml(data, output_file): with open(output_file, 'w', encoding='utf-8') as f: yaml.dump(data, f) def process_mmps_in_folder(folder_path): mmp_files = [f for f in os.listdir(folder_path) if f.endswith('.mmp') or f.endswith('.mmpz')] all_data = [] # Criação de pastas se não existirem mmpz_folder = os.path.join(folder_path, 'mmpz') wav_folder = os.path.join(folder_path, 'wav') metadata_folder = os.path.join(folder_path, 'metadata') data_folder = os.path.join(folder_path, '_data') for path in [mmpz_folder, wav_folder, metadata_folder, data_folder]: if not os.path.exists(path): os.makedirs(path) for file in mmp_files: file_path = os.path.join(folder_path, file) print(f'Processando arquivo: {file_path}') if file.endswith('.mmpz'): destination_path = os.path.join(mmpz_folder, file) shutil.move(file_path, destination_path) print(f'Movido para: {destination_path}') mmp_name = os.path.splitext(file)[0] + ".mmp" output_mmp_path = os.path.join(folder_path, mmp_name) convert_cmd = f'lmms --dump "{destination_path}" > "{output_mmp_path}"' try: os.environ['QT_QPA_PLATFORM'] = 'offscreen' subprocess.run(convert_cmd, shell=True, check=True) print("Convertido para .mmp com sucesso!") except subprocess.CalledProcessError as e: print(f"Erro ao converter .mmpz para .mmp: {e}") # Converter para WAV wav_output_path = os.path.join(wav_folder, os.path.splitext(file)[0]) wav_convert_cmd = f'lmms -r "{destination_path}" -o "{wav_output_path}" -f wav' try: subprocess.run(wav_convert_cmd, shell=True, check=True) print("Convertido para .wav com sucesso!") except subprocess.CalledProcessError as e: print(f"Erro ao converter .wav: {e}") mmp_data = parse_mmp_file(output_mmp_path) elif file.endswith('.mmp'): mmp_data = parse_mmp_file(file_path) if mmp_data: all_data.append(mmp_data) # Corrigir aqui os caminhos de saída json_file_path = os.path.join(metadata_folder, os.path.splitext(file)[0] + ".json") yaml_file_path = os.path.join(data_folder, os.path.splitext(file)[0] + ".yml") save_to_json(mmp_data, json_file_path) save_to_yaml(mmp_data, yaml_file_path) print(f"Dados salvos: {json_file_path}, {yaml_file_path}") return all_data # Rodar mmp_folder_path = 'mmp' processed_data = process_mmps_in_folder(mmp_folder_path) print("Processamento concluído.")