Crear Mapeo AFS MAP Simple con Python
Crear Mapeo AFS MAP Simple con Python
Para crear el mapa del 0_sound.afs, el proceso generalmente se divide en estas etapas principales:
1. Delimitación de rangos de IDs: Separar el contenedor por bloques según la función del audio (BGM/Música de fondo, Efectos de sonido/SE, Cánticos de hinchada, Megafonía y Comentarios).
2. Análisis de cabeceras ADX: Identificar sample rate (24 kHz, 32 kHz, 44.1 kHz), canales (mono/estéreo) y puntos de loop (Loop Start / Loop End) para evitar distorsiones o ruidos al reinsertar.
3. Audición y catalogación: Probar la extracción/reproducción mediante DKZ Studio o MFAudio para asignar un nombre descriptivo a cada ID sin asignar (unk_XXXXX.adx).
4. Estructuración de la tabla del mapa: Registrar ID, dirección/offset dentro del AFS, tamaño en bytes, frecuencia de muestreo y descripción del contenido.
Archivo por archivo usando métricas genéricas (canales, sample rate y tamaño de archivo), por lo que asigna la misma etiqueta "Cánticos / Ambiente Estadio" a todo el bloque sin entender la estructura interna de los equipos.
Código:
import osimport struct# Mapeo opcional de asignación de slots conocidos (puedes ampliarlo según vayas testeando los IDs en el juego)# Formato: SLOT_INDEX: "Nombre del Equipo / Selección"SLOT_NAMES = {0: "Genérico / Ligas",1: "Japón",# Agrega más slots conocidos según tu base de datos:# 2: "Corea del Sur",# 3: "Argentina",}def analyze_adx(file_path):"""Analiza la cabecera del archivo Criware ADX."""try:with open(file_path, "rb") as f:header = f.read(32)if len(header) < 18 or header[:2] != b'\x80\x00':return "Desconocido / No ADX", 0, 0channels = header[7]sample_rate = struct.unpack(">I", header[8:12])[0]file_size = os.path.getsize(file_path)if channels == 2 and sample_rate >= 32000 and file_size > 800000:tipo = "BGM - Música / Fondo"elif channels == 2 and file_size > 150000:tipo = "Cánticos / Ambiente Estadio"elif channels == 1:tipo = "Megafonía / Callname / FX Mono"else:tipo = "Efecto / SFX General"return tipo, channels, sample_rateexcept Exception:return "Error al analizar", 0, 0def get_chant_info(file_id):"""Agrupa el rango 00000 a 00702 en slots fijos de 5 cánticos por equipo."""if 0 <= file_id <= 702:slot_index = file_id // 5chant_num = (file_id % 5) + 1team_name = SLOT_NAMES.get(slot_index, f"Equipo/Slot {slot_index}")return f"Cánticos - {team_name} (Audio {chant_num}/5)"return Nonedef main():print("==================================================")print(" Generador de AFS MAP Estructurado (WE10 JL) ")print("==================================================")folder_path = input("\nIngresa la ruta de la carpeta con los .adx: ").strip('"')if not os.path.exists(folder_path):print("\n[ERROR] La carpeta especificada no existe.")input("\nPresiona Enter para salir...")returnoutput_map = "WE10JL_0_SOUND.map"files = [f for f in os.listdir(folder_path) if f.lower().endswith(".adx")]def get_id(fname):name = os.path.splitext(fname)[0]parts = name.split('_')if len(parts) > 1 and parts[-1].isdigit():return int(parts[-1])return 999999files.sort(key=get_id)print(f"\nProcesando {len(files)} archivos con asignación de slots...")with open(output_map, "w", encoding="utf-8") as map_file:for filename in files:file_id = get_id(filename)full_path = os.path.join(folder_path, filename)tipo, channels, rate = analyze_adx(full_path)# Verificamos si cae dentro del rango de cánticos estructurados (0 a 702)chant_detail = get_chant_info(file_id)if chant_detail:descripcion = f"[{chant_detail}] ({channels}Ch, {rate}Hz)"else:descripcion = f"[{tipo}] ({channels}Ch, {rate}Hz)"linea = f"{file_id:05d};{filename};{descripcion}\n"map_file.write(linea)print(f"\n[¡ÉXITO!] Se ha generado '{output_map}' organizado por slots de 5 archivos.")input("\nPresiona Enter para cerrar...")if __name__ == "__main__":main()
El folder de trabajo debe ser algo asi:
Es la recomendada porque da mas detalles del AFS MAP que se genera
Codigo:
import osimport struct# Mapeo opcional de asignación de slots conocidos (puedes ampliarlo según vayas testeando los IDs en el juego)# Formato: SLOT_INDEX: "Nombre del Equipo / Selección"SLOT_NAMES = {0: "Genérico / Ligas",1: "Japón",# Agrega más slots conocidos según tu base de datos:# 2: "Corea del Sur",# 3: "Argentina",}def analyze_adx(file_path):"""Analiza la cabecera del archivo Criware ADX."""try:with open(file_path, "rb") as f:header = f.read(32)if len(header) < 18 or header[:2] != b'\x80\x00':return "Desconocido / No ADX", 0, 0channels = header[7]sample_rate = struct.unpack(">I", header[8:12])[0]file_size = os.path.getsize(file_path)if channels == 2 and sample_rate >= 32000 and file_size > 800000:tipo = "BGM - Música / Fondo"elif channels == 2 and file_size > 150000:tipo = "Cánticos / Ambiente Estadio"elif channels == 1:tipo = "Megafonía / Callname / FX Mono"else:tipo = "Efecto / SFX General"return tipo, channels, sample_rateexcept Exception:return "Error al analizar", 0, 0def get_chant_info(file_id):"""Agrupa el rango 00000 a 00702 en slots fijos de 5 cánticos por equipo."""if 0 <= file_id <= 702:slot_index = file_id // 5chant_num = (file_id % 5) + 1team_name = SLOT_NAMES.get(slot_index, f"Equipo/Slot {slot_index}")return f"Cánticos - {team_name} (Audio {chant_num}/5)"return Nonedef main():print("==================================================")print(" Generador de AFS MAP Estructurado (WE10 JL) ")print("==================================================")folder_path = input("\nIngresa la ruta de la carpeta con los .adx: ").strip('"')if not os.path.exists(folder_path):print("\n[ERROR] La carpeta especificada no existe.")input("\nPresiona Enter para salir...")returnoutput_map = "WE10JL_0_SOUND.map"files = [f for f in os.listdir(folder_path) if f.lower().endswith(".adx")]def get_id(fname):name = os.path.splitext(fname)[0]parts = name.split('_')if len(parts) > 1 and parts[-1].isdigit():return int(parts[-1])return 999999files.sort(key=get_id)print(f"\nProcesando {len(files)} archivos con asignación de slots...")with open(output_map, "w", encoding="utf-8") as map_file:for filename in files:file_id = get_id(filename)full_path = os.path.join(folder_path, filename)tipo, channels, rate = analyze_adx(full_path)# Verificamos si cae dentro del rango de cánticos estructurados (0 a 702)chant_detail = get_chant_info(file_id)if chant_detail:descripcion = f"[{chant_detail}] ({channels}Ch, {rate}Hz)"else:descripcion = f"[{tipo}] ({channels}Ch, {rate}Hz)"linea = f"{file_id:05d};{filename};{descripcion}\n"map_file.write(linea)print(f"\n[¡ÉXITO!] Se ha generado '{output_map}' organizado por slots de 5 archivos.")input("\nPresiona Enter para cerrar...")if __name__ == "__main__":main()
@echo offtitle Generador AFS MAP WE10JLcolor 0Aecho Buscando instalacion de Python...python --version >nul 2>&1if %errorlevel% neq 0 (echo.echo [!] Python no esta instalado en tu sistema.echo Por favor instala Python 3 desde la Microsoft Store o python.orgecho para ejecutar este script con un doble clic.echo.pauseexit)python generar_map.pypause
Después le saldrá una confirmación:

Comentarios
Publicar un comentario