From 4ecf05c0983d9992185ac55b236e3e25e6708c51 Mon Sep 17 00:00:00 2001 From: Gordon Weeks <627684+gcweeks@users.noreply.github.com> Date: Sat, 31 Jan 2026 23:06:41 -0800 Subject: [PATCH] Added helper python file for anaylizing tracks in MIDI files. --- scan_tracks.py | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 scan_tracks.py diff --git a/scan_tracks.py b/scan_tracks.py new file mode 100644 index 0000000..90670cd --- /dev/null +++ b/scan_tracks.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +""" +Scans all JSON song files and reports track information. +Shows each track's note count to help with track selection. +""" + +import json +import os +from pathlib import Path +from typing import Dict, List, Tuple + + +def scan_song_file(file_path: Path) -> Dict: + """ + Scan a single JSON song file and extract track information. + + Returns: + Dict with 'name', 'artist', 'tracks' (list of note counts) + """ + try: + with open(file_path, 'r', encoding='utf-8') as f: + data = json.load(f) + + song_name = data.get('header', {}).get('name', 'Unknown') + artist = data.get('header', {}).get('artist', 'Unknown') + tracks = data.get('tracks', []) + + track_info = [] + for i, track in enumerate(tracks): + notes = track.get('notes', []) + instrument = track.get('instrument', {}) + instrument_name = instrument.get('name', 'Unknown') + note_count = len(notes) + + # Only count notes in the playable MIDI range (48-83) + playable_notes = [n for n in notes if 48 <= n.get('midi', 0) <= 83] + playable_count = len(playable_notes) + + track_info.append({ + 'index': i, + 'instrument': instrument_name, + 'total_notes': note_count, + 'playable_notes': playable_count, + 'channel': track.get('channel', 'N/A') + }) + + return { + 'name': song_name, + 'artist': artist, + 'tracks': track_info, + 'file': file_path.name + } + except Exception as e: + return { + 'name': 'ERROR', + 'artist': str(e), + 'tracks': [], + 'file': file_path.name + } + + +def find_best_track(tracks: List[Dict]) -> int: + """Find the track with the most playable notes (mimics the game logic).""" + if not tracks: + return 0 + + best_idx = 0 + best_count = 0 + for i, track in enumerate(tracks): + if track['playable_notes'] > best_count: + best_count = track['playable_notes'] + best_idx = i + + return best_idx + + +def main(): + # Find the assets/songs/json directory + script_dir = Path(__file__).parent + json_dir = script_dir / 'assets' / 'songs' / 'json' + + if not json_dir.exists(): + print(f"Error: Directory not found: {json_dir}") + return + + # Find all JSON files + json_files = sorted(json_dir.glob('*.json')) + + if not json_files: + print(f"No JSON files found in {json_dir}") + return + + print("=" * 80) + print("SONG TRACK ANALYSIS") + print("=" * 80) + print() + + # Scan each file + all_songs = [] + for json_file in json_files: + song_info = scan_song_file(json_file) + all_songs.append(song_info) + + # Print detailed report + for song in all_songs: + print(f"FILE: {song['file']}") + print(f" Song: {song['name']}") + print(f" Artist: {song['artist']}") + print(f" Tracks: {len(song['tracks'])}") + + if song['tracks']: + best_idx = find_best_track(song['tracks']) + print() + for track in song['tracks']: + is_best = track['index'] == best_idx + marker = " [AUTO-SELECTED]" if is_best else "" + print(f" Track {track['index']}: " + f"{track['playable_notes']:4d} playable notes " + f"({track['total_notes']:4d} total) - " + f"{track['instrument']}{marker}") + else: + print(" No tracks found!") + + print() + print("-" * 80) + print() + + # Summary statistics + print("\n" + "=" * 80) + print("SUMMARY") + print("=" * 80) + + total_songs = len(all_songs) + total_tracks = sum(len(s['tracks']) for s in all_songs) + avg_tracks = total_tracks / total_songs if total_songs > 0 else 0 + + print(f"Total songs: {total_songs}") + print(f"Total tracks: {total_tracks}") + print(f"Average tracks per song: {avg_tracks:.1f}") + print() + + # Show which songs would auto-select which track + print("Auto-selection would choose:") + for song in all_songs: + if song['tracks']: + best_idx = find_best_track(song['tracks']) + best_track = song['tracks'][best_idx] + print(f" {song['name']:40s} -> Track {best_idx} " + f"({best_track['playable_notes']} notes, {best_track['instrument']})") + + print() + + +if __name__ == '__main__': + main()