Skip to content

Latest commit

 

History

History
171 lines (154 loc) · 7.08 KB

skitz.py.README.md

File metadata and controls

171 lines (154 loc) · 7.08 KB

Issues found in the code:

  1. The imports at the beginning of the code should be on separate lines for better readability.
  2. The class name "Skitz" does not follow the recommended naming convention. It should be "SkitzGenerator" or a more descriptive name.
  3. The load_inspiration method should be made a staticmethod or moved outside of the class since it does not depend on any instance variables.
  4. The extract_markdown method does not need to be inside the class. It can be a separate function.
  5. The quality_check and compose_song methods are missing error handling in case the API request fails.
  6. The write_abc_file method should be made a staticmethod or moved outside of the class since it does not depend on any instance variables.
  7. The convert_to_midi and convert_to_audio methods should be made staticmethods or moved outside of the class since they do not depend on any instance variables.
  8. The get_user_input_easy and get_user_input_advanced methods can be combined into a single method with a parameter to handle the different sets of questions.
  9. The log_messages method does not need to be inside the class. It can be a separate function.
  10. The generate_song method is missing the rest of its implementation.

Suggestions for improvements and fixes:

  1. Import statements at the beginning of the code should be on separate lines:
    import os
    import openai
    from dotenv import load_dotenv
    from music21 import *
    from midi2audio import FluidSynth
    
  2. Rename the class "Skitz" to "SkitzGenerator" or a more descriptive name.
  3. Make the load_inspiration method a staticmethod or move it outside of the class:
    @staticmethod
    def load_inspiration():
        # Load inspiration from file if it exists, otherwise return an empty string
        try:
            with open(os.path.join("Inspirations", 'inspiration.md'), 'r') as file:
                inspiration = file.read()
                return inspiration
        except FileNotFoundError:
            print("The inspiration file is not found, continuing with the program...")
            return ""
    
  4. Move the extract_markdown method outside of the class:
    def extract_markdown(song):
        # Split the song into lines
        lines = song.split('\n')
        # Find the start and end of the markdown content
        start = None
        end = None
        for i, line in enumerate(lines):
            if line.strip() == '```':
                if start is None:
                    start = i
                else:
                    end = i
                    break
        # Extract the markdown content
        if start is not None and end is not None:
            markdown = '\n'.join(lines[start+1:end])
        else:
            markdown = song
        return markdown
    
  5. Add error handling to the quality_check and compose_song methods:
    except openai.OpenAIError as e:
        print(f"\nAn error occurred: {e}")
        return None
    
  6. Move the write_abc_file method outside of the class:
    @staticmethod
    def write_abc_file(song, filename):
        os.makedirs("Generations", exist_ok=True)
        original_filename = filename
        counter = 2
        while os.path.exists(os.path.join("Generations", filename)):
            filename = f"{original_filename[:-4]}_{counter}.abc"
            counter += 1
        filepath = os.path.join("Generations", filename)
        with open(filepath, 'w') as file:
            file.write(song)
        print(f"File saved as: {filename}")
        return filepath
    
  7. Move the convert_to_midi and convert_to_audio methods outside of the class:
    @staticmethod
    def convert_to_midi(abc_file, midi_file):
        # Convert ABC to MIDI using music21
        abcScore = converter.parse(abc_file)
        midiScore = abcScore.write('midi', midi_file)
    
    @staticmethod
    def convert_to_audio(midi_file, audio_file):
        # Convert MIDI to audio using FluidSynth
        fs = FluidSynth()
        fs.midi_to_audio(midi_file, audio_file)
    
  8. Combine the get_user_input_easy and get_user_input_advanced methods into a single method:
    def get_user_input(self, advanced=False):
        user_instructions = ""
        questions = [
            "\nPlease enter the genre of the song: ",
            "\nPlease enter the tempo of the song: ",
            "\n
    

The code is not formatted properly. It lacks indentation and has issues with line breaks. Here's a refactored version of the code with better formatting:

import sys

class Skitz:

    def __init__(self):
        pass

    def generate_song(self):
        print("Welcome to Skitz!")
        print("Please enter the instructions for your song below:")
        user_instructions = sys.stdin.read()
        regenerate = input("Would you like to regenerate the song with the same instructions? (yes/no): ")

        if regenerate.lower() == 'yes':
            filepath = self.generate_song_with_same_instructions(user_instructions)
        elif regenerate.lower() == 'no':
            return
        else:
            print("Invalid input. Please type 'yes' or 'no'.")

    def generate_song_with_same_instructions(self, user_instructions):
        print("\nGenerating your song. This may take a few moments...")
        song = self.compose_song(user_instructions)

        if song is None:
            print("\nFailed to generate a song. Please try again.")
            return

        # Extract the title from the user instructions
        lines = user_instructions.split('\n')
        title_line = next((line for line in lines if line.startswith("Please enter the title of the song:")), None)

        if title_line is not None:
            # Extract the title from the line
            title = title_line.split(":")[1].strip()
            # Use the title as the filename (replacing spaces with underscores)
            filename = f"{title.replace(' ', '_')}.abc"
        else:
            # If no title was found, fall back to the original filename
            filename = f"{user_instructions[:20].replace(' ', '_')}.abc"

        filepath = self.write_abc_file(song, filename)

        if filepath:
            print(f"\nThe song has been written to: {filepath}")
        else:
            print("\nFailed to write the song to a file. Please try again.")

        return filepath


if __name__ == "__main__":
    try:
        skitz = Skitz()
        skitz.generate_song()
    except Exception as e:
        print(f"An error occurred: {e}")

Improvements and suggestions:

  1. Import the sys module at the top of the code, next to the other imports.
  2. Use proper indentation and consistent spacing.
  3. Add docstrings and comments to explain the purpose and logic of the code.
  4. Consider adding error handling for better user experience.
  5. Avoid using pass in the __init__ method if there is no logic needed. You can remove it altogether.
  6. Consider breaking down the generate_song and generate_song_with_same_instructions methods into smaller, more manageable functions. This will improve readability and maintainability.
  7. Use a try-except block around the code in the if __name__ == "__main__" block to catch and handle specific exceptions.