improve script berikut ini agar dapat mendownload lagu dari spotify dan menggunakan basic pitch dengan benar dan load modal nya dengan benar, lalu gunakan prettymidi atau sebagai nya untuk meng improve suara midi yang di dapatkan, buatkan dengan benar dan tepat lengkap dengan log nya : import os
import subprocess
import shutil
import tempfile
import librosa
import soundfile as sf
from basic_pitch.inference import predict_and_save
import warnings
import mido  # For MIDI processing

warnings.filterwarnings("ignore")  # Suppress warnings for cleaner output

def download_song_from_spotify(song_query):
    """Download song from Spotify using spotdl."""
    tmpdirname = tempfile.mkdtemp()
    try:
        print("Downloading song...")
        # Download the song with spotdl and save it in the temporary directory
        subprocess.run([
            'spotdl', song_query,
            '--output', os.path.join(tmpdirname, '{artist} - {title}.{output-ext}'),
            '--format', 'mp3'  # Ensure the output format is mp3
        ], check=True)
        
        # Fetch the downloaded song
        downloaded_files = os.listdir(tmpdirname)
        if downloaded_files:
            song_file = os.path.join(tmpdirname, downloaded_files[0])
            return song_file, downloaded_files[0], tmpdirname  # Return song path, song file name, and temp directory
        else:
            print("Failed to download song.")
            return None, None, tmpdirname
    except subprocess.CalledProcessError as e:
        print(f"An error occurred while downloading the song: {e}")
        return None, None, tmpdirname

def convert_audio_to_wav(input_audio_file):
    """Convert audio file to WAV format with standard settings."""
    try:
        print("Converting audio to WAV format...")
        y, sr = librosa.load(input_audio_file, sr=44100, mono=True)
        wav_file = os.path.splitext(input_audio_file)[0] + '.wav'
        sf.write(wav_file, y, sr, subtype='PCM_16')
        return wav_file, sr
    except Exception as e:
        print(f"An error occurred during audio conversion: {e}")
        return None, None

def normalize_audio(y):
    """Normalize the audio signal to have consistent volume."""
    try:
        print("Normalizing audio...")
        y_norm = librosa.util.normalize(y)
        return y_norm
    except Exception as e:
        print(f"An error occurred during audio normalization: {e}")
        return y

def reduce_noise(y):
    """Reduce noise in the audio signal."""
    try:
        print("Reducing noise...")
        # Apply harmonic-percussive source separation to emphasize harmonic content
        y_harmonic, _ = librosa.effects.hpss(y)
        return y_harmonic
    except Exception as e:
        print(f"An error occurred during noise reduction: {e}")
        return y

def audio_to_midi_with_basic_pitch(audio_file, output_dir, song_name):
    """Convert audio file to MIDI using Basic Pitch."""
    if not os.path.exists(audio_file):
        print(f"Error: Audio file {audio_file} not found.")
        return
    
    try:
        print(f"Converting audio to MIDI using Basic Pitch...")
        # Load audio
        y, sr = librosa.load(audio_file, sr=None, mono=True)
        
        # Normalize audio
        y = normalize_audio(y)
        
        # Reduce noise
        y = reduce_noise(y)
        
        # Save preprocessed audio
        sf.write(audio_file, y, sr, subtype='PCM_16')
        
        # Set Basic Pitch parameters to improve accuracy
        onset_threshold = 0.6
        frame_threshold = 0.4
        minimum_note_length = 50  # In milliseconds
        
        # Run inference and save MIDI file
        predict_and_save(
            [audio_file],                  # List of audio files
            output_directory=output_dir,   # Where to save outputs
            save_midi=True,                # Save the MIDI file
            sonify_midi=False,             # Disable sonification
            save_model_outputs=False,      # Skip saving model outputs
            save_notes=False,              # Skip saving detected notes
            onset_threshold=onset_threshold,
            frame_threshold=frame_threshold,
            minimum_note_length=minimum_note_length,
        )
        
        # The actual MIDI file created will have the format: original_file_name_basic_pitch.mid
        base_name = os.path.splitext(os.path.basename(audio_file))[0]  # Extract the base name of the audio file
        midi_file = os.path.join(output_dir, f"{base_name}_basic_pitch.mid")
        
        # Remove any file extension (e.g., .mp3) from the song name before renaming
        clean_song_name = os.path.splitext(song_name)[0]
        new_midi_file = os.path.join(output_dir, f"{clean_song_name}_piano.mid")
        os.rename(midi_file, new_midi_file)
        
        print(f"Conversion complete. MIDI file saved as {new_midi_file}.")
        
        # Optional: Post-process MIDI if needed
        post_process_midi(new_midi_file)
        
        # Delete temporary WAV file
        # if os.path.exists(audio_file):
        #     os.remove(audio_file)
        print(f"Deleted temporary WAV file: {audio_file}")
        
    except Exception as e:
        print(f"An error occurred during audio to MIDI conversion: {e}")

def post_process_midi(midi_file):
    """Adjust MIDI velocities and quantize notes if needed."""
    try:
        print("Post-processing MIDI file...")
        mid = mido.MidiFile(midi_file)
        ticks_per_beat = mid.ticks_per_beat
        quantization_unit = ticks_per_beat // 16  # Quantize to 64th notes
        
        for track in mid.tracks:
            abs_time = 0
            for msg in track:
                abs_time += msg.time
                if msg.type in ['note_on', 'note_off']:
                    # Quantize timing
                    abs_time = int(round(abs_time / quantization_unit)) * quantization_unit
                    msg.time = abs_time - (abs_time % quantization_unit)
                    # Adjust velocities
                    if msg.type == 'note_on' and msg.velocity > 0:
                        msg.velocity = min(127, max(40, msg.velocity))
            
        mid.save(midi_file)
        print("MIDI post-processing complete.")
    except Exception as e:
        print(f"An error occurred during MIDI post-processing: {e}")

def clean_up(temp_dirs):
    """Clean up temporary directories."""
    for tmpdirname in temp_dirs:
        if os.path.exists(tmpdirname):
            shutil.rmtree(tmpdirname)
            print(f"Deleted temporary directory: {tmpdirname}")

# ---- Main Program ----
if __name__ == "__main__":
    song_query = input("Enter the song title or Spotify link: ")
    
    temp_dirs = []  # Keep track of temporary directories to clean up
    
    # Step 1: Download the song
    downloaded_song, song_name, tmpdirname = download_song_from_spotify(song_query)
    temp_dirs.append(tmpdirname)
    
    if downloaded_song:
        # Step 2: Convert audio to WAV
        wav_file, sr = convert_audio_to_wav(downloaded_song)
        if wav_file:
            # Step 3: Convert audio to MIDI
            current_dir = os.path.dirname(os.path.abspath(__file__))
            output_dir = os.path.join(current_dir, 'songs')
            
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)  # Create the 'songs' directory if it doesn't exist
    
            audio_to_midi_with_basic_pitch(wav_file, output_dir, song_name)
        else:
            print("Failed to convert audio to WAV.")
        
        # Clean up temporary directories
        clean_up(temp_dirs)
    else:
        print("Failed to download the song.")