| #!/bin/bash |
|
|
| |
| |
|
|
| set -e |
|
|
| |
| RED='\033[0;31m' |
| GREEN='\033[0;32m' |
| YELLOW='\033[1;33m' |
| BLUE='\033[0;34m' |
| PURPLE='\033[0;35m' |
| CYAN='\033[0;36m' |
| NC='\033[0m' |
|
|
| |
| print_color() { |
| local color=$1 |
| local text=$2 |
| echo -e "${color}${text}${NC}" |
| } |
|
|
| |
| print_header() { |
| echo |
| print_color $CYAN "======================================" |
| print_color $CYAN "$1" |
| print_color $CYAN "======================================" |
| echo |
| } |
|
|
| |
| prompt_input() { |
| local prompt=$1 |
| local default=$2 |
| local var_name=$3 |
| |
| if [ -n "$default" ]; then |
| read -e -p "$(print_color $GREEN "$prompt") [default: $default]: " input |
| if [ -z "$input" ]; then |
| input="$default" |
| fi |
| else |
| read -e -p "$(print_color $GREEN "$prompt"): " input |
| fi |
| |
| eval "$var_name='$input'" |
| } |
|
|
| |
| prompt_yn() { |
| local prompt=$1 |
| local default=$2 |
| local var_name=$3 |
| |
| while true; do |
| if [ "$default" = "y" ]; then |
| read -p "$(print_color $GREEN "$prompt") [Y/n]: " yn |
| yn=${yn:-y} |
| else |
| read -p "$(print_color $GREEN "$prompt") [y/N]: " yn |
| yn=${yn:-n} |
| fi |
| |
| case $yn in |
| [Yy]* ) eval "$var_name=true"; break;; |
| [Nn]* ) eval "$var_name=false"; break;; |
| * ) echo "Please answer yes or no.";; |
| esac |
| done |
| } |
|
|
| |
| prompt_choice() { |
| local prompt=$1 |
| local var_name=$2 |
| shift 2 |
| local options=("$@") |
| |
| while true; do |
| print_color $GREEN "$prompt" |
| for i in "${!options[@]}"; do |
| echo " $((i+1))) ${options[i]}" |
| done |
| read -p "Select option (1-${#options[@]}): " choice |
| |
| if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then |
| eval "$var_name='${options[$((choice-1))]}'" |
| break |
| else |
| print_color $RED "Invalid choice. Please select 1-${#options[@]}." |
| fi |
| done |
| } |
|
|
| |
| prompt_multiselect() { |
| local prompt=$1 |
| local var_name=$2 |
| shift 2 |
| local options=("$@") |
| local num_options=${#options[@]} |
| local selections=() |
| for (( i=0; i<num_options; i++ )); do |
| selections[i]=0 |
| done |
| local current_idx=0 |
|
|
| |
| tput civis 2>/dev/null || true |
| |
| trap 'tput cnorm; return' EXIT |
|
|
| |
| tput clear |
| |
| while true; do |
| |
| tput cup 0 0 |
|
|
| echo -e "${GREEN}${prompt}${NC}" |
| echo "(Use UP/DOWN to navigate, SPACE to select/deselect, ENTER to confirm)" |
|
|
| for i in "${!options[@]}"; do |
| local checkbox="[ ]" |
| if [[ ${selections[i]} -eq 1 ]]; then |
| checkbox="[${GREEN}x${NC}]" |
| fi |
|
|
| if [ "$i" -eq "$current_idx" ]; then |
| echo -e " ${CYAN}> $checkbox ${options[i]}${NC}" |
| else |
| echo -e " $checkbox ${options[i]}" |
| fi |
| done |
| |
| tput ed |
|
|
| |
| |
| IFS= read -rsn1 key |
| |
| |
| if [[ "$key" == $'\e' ]]; then |
| read -rsn2 -t 0.1 key |
| fi |
|
|
| case "$key" in |
| '[A') |
| current_idx=$(( (current_idx - 1 + num_options) % num_options )) |
| ;; |
| '[B') |
| current_idx=$(( (current_idx + 1) % num_options )) |
| ;; |
| ' ') |
| if [[ ${selections[current_idx]} -eq 1 ]]; then |
| selections[current_idx]=0 |
| else |
| selections[current_idx]=1 |
| fi |
| ;; |
| '') |
| break |
| ;; |
| esac |
| done |
|
|
| |
| tput cnorm 2>/dev/null || true |
| trap - EXIT |
|
|
| |
| tput cup $(tput lines) 0 |
| clear |
|
|
| |
| local selected_options=() |
| for i in "${!options[@]}"; do |
| if [[ ${selections[i]} -eq 1 ]]; then |
| selected_options+=("${options[i]}") |
| fi |
| done |
|
|
| |
| if [ ${#selected_options[@]} -gt 0 ]; then |
| local formatted_items="" |
| for item in "${selected_options[@]}"; do |
| if [ -n "$formatted_items" ]; then |
| |
| formatted_items="$formatted_items,\"$item\"" |
| else |
| formatted_items="\"$item\"" |
| fi |
| done |
| |
| eval "$var_name='[$formatted_items]'" |
| else |
| |
| eval "$var_name=''" |
| fi |
| } |
|
|
|
|
| |
| validate_file() { |
| local file_path=$1 |
| if [ ! -f "$file_path" ]; then |
| print_color $RED "File not found: $file_path" |
| return 1 |
| fi |
| return 0 |
| } |
|
|
| convert_path_if_needed() { |
| local input_path="$1" |
|
|
| |
| if [[ -z "$input_path" ]]; then |
| echo "" |
| return |
| fi |
|
|
| local uname_out |
| uname_out="$(uname -s)" |
|
|
| case "$uname_out" in |
| CYGWIN*|MINGW*|MSYS*) |
| cygpath -w "$input_path" |
| ;; |
| *) |
| echo "$input_path" |
| ;; |
| esac |
| } |
|
|
| |
| print_color $PURPLE "╔═══════════════════════════════════════════╗" |
| print_color $PURPLE "║ Mapperatorinator CLI ║" |
| print_color $PURPLE "║ Interactive Inference Setup ║" |
| print_color $PURPLE "╚═══════════════════════════════════════════╝" |
| echo |
|
|
| |
| print_header "Required Paths" |
|
|
| |
| prompt_input "Python executable path" "python" python_executable |
|
|
| |
| while true; do |
| prompt_input "Audio file path (required)" "input/demo.mp3" audio_path |
| if [ -z "$audio_path" ]; then |
| print_color $RED "Audio path is required!" |
| continue |
| fi |
| if validate_file "$audio_path"; then |
| break |
| fi |
| done |
|
|
| |
| prompt_input "Output directory path" "$(dirname "$audio_path")" output_path |
|
|
| |
| prompt_input "Beatmap file path (optional, for in-context learning)" "" beatmap_path |
| if [ -n "$beatmap_path" ] && ! validate_file "$beatmap_path"; then |
| print_color $YELLOW "Warning: Beatmap file not found, continuing without it" |
| beatmap_path="" |
| fi |
|
|
| |
| audio_path=$(convert_path_if_needed "$audio_path") |
| output_path=$(convert_path_if_needed "$output_path") |
| beatmap_path=$(convert_path_if_needed "$beatmap_path") |
|
|
| |
| print_header "Basic Settings" |
|
|
| |
| model_options=( |
| "v28:Mapperatorinator V28" |
| "v29:Mapperatorinator V29 (Supports gamemodes and descriptors)" |
| "v30:Mapperatorinator V30 (Best stable model)" |
| "v31:Mapperatorinator V31 (Slightly more accurate than V29)" |
| "beatheritage_v1:BeatHeritage V1 (Enhanced stability & quality)" |
| ) |
|
|
| print_color $GREEN "Select Model:" |
| for i in "${!model_options[@]}"; do |
| IFS=':' read -r value desc <<< "${model_options[i]}" |
| echo " $((i+1))) $desc" |
| done |
|
|
| while true; do |
| read -p "Select model (1-${#model_options[@]}) [default: 5 - BeatHeritage V1]: " model_choice |
| model_choice=${model_choice:-5} |
| |
| if [[ "$model_choice" =~ ^[1-5]$ ]]; then |
| IFS=':' read -r model_config model_desc <<< "${model_options[$((model_choice-1))]}" |
| print_color $BLUE "Selected: $model_desc" |
| break |
| else |
| print_color $RED "Invalid choice. Please select 1-${#model_options[@]}." |
| fi |
| done |
|
|
| |
| gamemode_options=("osu!" "Taiko" "Catch" "Mania") |
| while true; do |
| print_color $GREEN "Game mode:" |
| for i in "${!gamemode_options[@]}"; do |
| echo " $i) ${gamemode_options[$i]}" |
| done |
| read -p "$(print_color $GREEN "Select option (0-3)") [default: 0]: " gamemode_input |
| |
| gamemode=${gamemode_input:-0} |
|
|
| if [[ "$gamemode" =~ ^[0-3]$ ]]; then |
| break |
| else |
| print_color $RED "Invalid choice. Please select a number between 0 and 3." |
| echo |
| fi |
| done |
|
|
| |
| prompt_input "Difficulty (1.0-10.0)" "5.5" difficulty |
|
|
| |
| |
| prompt_input "Year" "2023" year |
| if ! [[ "$year" =~ ^(200[7-9]|201[0-9]|202[0-3])$ ]]; then |
| print_color $RED "Invalid year! Year must be between 2007 and 2023. Defaulting to 2023." |
| year=2023 |
| fi |
|
|
| |
| print_header "Advanced Settings (Optional - Press Enter to skip)" |
| print_color $BLUE "Difficulty Settings:" |
| prompt_input "HP Drain Rate (0-10)" "" hp_drain_rate |
| prompt_input "Circle Size (0-10)" "" circle_size |
| prompt_input "Overall Difficulty (0-10)" "" overall_difficulty |
| prompt_input "Approach Rate (0-10)" "" approach_rate |
| print_color $BLUE "Slider Settings:" |
| prompt_input "Slider Multiplier" "" slider_multiplier |
| prompt_input "Slider Tick Rate" "" slider_tick_rate |
| if [ "$gamemode" -eq 3 ]; then |
| print_color $BLUE "Mania Settings:" |
| prompt_input "Key Count" "" keycount |
| prompt_input "Hold Note Ratio (0-1)" "" hold_note_ratio |
| prompt_input "Scroll Speed Ratio" "" scroll_speed_ratio |
| fi |
| print_color $BLUE "Generation Settings:" |
| prompt_input "CFG Scale (1-20)" "" cfg_scale |
| prompt_input "Temperature (0-2)" "" temperature |
| prompt_input "Top P (0-1)" "" top_p |
| prompt_input "Seed (random if empty)" "" seed |
| prompt_input "Mapper ID" "" mapper_id |
| print_color $BLUE "Timing Settings:" |
| prompt_input "Start Time (seconds)" "" start_time |
| prompt_input "End Time (seconds)" "" end_time |
|
|
| |
| print_header "Export & Processing Options" |
| prompt_yn "Export as .osz file?" "n" export_osz |
| prompt_yn "Add to existing beatmap?" "n" add_to_beatmap |
| prompt_yn "Add hitsounds?" "n" hitsounded |
| prompt_yn "Use super timing analysis?" "n" super_timing |
|
|
| |
| print_header "Style Descriptors" |
|
|
| |
| descriptor_options=("jump aim" "stream" "tech" "aim" "speed" "flow" "clean" "complex" "simple" "modern" "classic" "spaced" "stacked") |
| prompt_multiselect "Positive descriptors (describe desired mapping style):" descriptors "${descriptor_options[@]}" |
|
|
| |
| prompt_multiselect "Negative descriptors (styles to avoid):" negative_descriptors "${descriptor_options[@]}" |
|
|
| |
| if [ -n "$beatmap_path" ]; then |
| print_header "In-Context Learning Options" |
| context_options_list=("timing" "patterns" "structure" "style") |
| prompt_multiselect "In-context learning aspects:" in_context_options "${context_options_list[@]}" |
| fi |
|
|
|
|
| |
| print_header "Command Generation" |
|
|
| |
| cmd_args=("$python_executable" "inference.py" "-cn" "$model_config") |
|
|
| |
| add_arg() { |
| local key=$1 |
| local value=$2 |
| if [ -n "$value" ]; then |
| |
| |
| cmd_args+=("${key}=${value}") |
| fi |
| } |
|
|
| |
| add_bool_arg() { |
| local key=$1 |
| local value=$2 |
| if [ "$value" = "true" ]; then |
| cmd_args+=("${key}=true") |
| else |
| cmd_args+=("${key}=false") |
| fi |
| } |
|
|
| |
| add_arg "audio_path" "'$audio_path'" |
| add_arg "output_path" "'$output_path'" |
| add_arg "beatmap_path" "'$beatmap_path'" |
| add_arg "gamemode" "$gamemode" |
| add_arg "difficulty" "$difficulty" |
| add_arg "year" "$year" |
|
|
| |
| add_arg "hp_drain_rate" "$hp_drain_rate" |
| add_arg "circle_size" "$circle_size" |
| add_arg "overall_difficulty" "$overall_difficulty" |
| add_arg "approach_rate" "$approach_rate" |
| add_arg "slider_multiplier" "$slider_multiplier" |
| add_arg "slider_tick_rate" "$slider_tick_rate" |
| add_arg "keycount" "$keycount" |
| add_arg "hold_note_ratio" "$hold_note_ratio" |
| add_arg "scroll_speed_ratio" "$scroll_speed_ratio" |
| add_arg "cfg_scale" "$cfg_scale" |
| add_arg "temperature" "$temperature" |
| add_arg "top_p" "$top_p" |
| add_arg "seed" "$seed" |
| add_arg "mapper_id" "$mapper_id" |
| add_arg "start_time" "$start_time" |
| add_arg "end_time" "$end_time" |
|
|
| |
| add_arg "descriptors" "$descriptors" |
| add_arg "negative_descriptors" "$negative_descriptors" |
| add_arg "in_context" "$in_context_options" |
|
|
| |
| add_bool_arg "export_osz" "$export_osz" |
| add_bool_arg "add_to_beatmap" "$add_to_beatmap" |
| add_bool_arg "hitsounded" "$hitsounded" |
| add_bool_arg "super_timing" "$super_timing" |
|
|
|
|
| |
| print_color $YELLOW "Generated command:" |
| echo |
| |
| printf "%s " "${cmd_args[@]}" |
| echo |
| echo |
|
|
| |
| prompt_yn "Execute this command?" "y" execute_cmd |
|
|
| if [ "$execute_cmd" = "true" ]; then |
| print_header "Executing Inference" |
| print_color $GREEN "Starting inference process..." |
| echo |
| |
| |
| "${cmd_args[@]}" |
| |
| exit_code=$? |
| echo |
| if [ $exit_code -eq 0 ]; then |
| print_color $GREEN "✓ Inference completed successfully!" |
| else |
| print_color $RED "✗ Inference failed with exit code: $exit_code" |
| fi |
| else |
| print_color $YELLOW "Command generation cancelled." |
| echo |
| print_color $BLUE "You can copy and run the command manually:" |
| |
| printf "%s " "${cmd_args[@]}" |
| echo |
| fi |
|
|
| echo |
| print_color $PURPLE "Thank you for using Mapperatorinator CLI!" |