AI-Driven Music Composition Assistant for Generating Melodies and Harmonies,Python

👤 Sharing: AI
```python
import random

# Define musical parameters
SCALE = ['C', 'D', 'E', 'F', 'G', 'A', 'B']  # C Major scale for simplicity
CHORD_PROGRESSION = ['I', 'IV', 'V', 'I']  # I-IV-V-I in C Major (C-F-G-C)
DURATIONS = [0.25, 0.5, 1.0, 2.0]  # Possible note durations (quarter, half, whole, double whole)


def generate_melody(length=16, scale=SCALE):
    """
    Generates a simple melody based on the given scale.

    Args:
        length:  The number of notes in the melody.
        scale: A list of notes representing the scale to use.

    Returns:
        A list of notes representing the generated melody.
    """
    melody = []
    for _ in range(length):
        melody.append(random.choice(scale))  # Randomly pick a note from the scale
    return melody


def generate_harmony(melody, chord_progression=CHORD_PROGRESSION):
    """
    Generates a simple harmony based on the given melody and chord progression.

    This function attempts to match notes in the melody to the corresponding chord in the progression.
    It's a simplified harmonic accompaniment.  More sophisticated AI methods (like using Markov chains
    or recurrent neural networks) could generate more complex and interesting harmonies.

    Args:
        melody: A list of notes representing the melody.
        chord_progression: A list of chord symbols (e.g., 'I', 'IV', 'V') to use for harmony.

    Returns:
        A list of chords, one for each note in the melody.  Each chord is represented by the root note
        (e.g., 'C', 'F', 'G').
    """
    harmony = []
    chord_index = 0
    for note in melody:
        # Map chord symbols to root notes (in C Major)
        if chord_progression[chord_index % len(chord_progression)] == 'I':
            chord_root = 'C'
        elif chord_progression[chord_index % len(chord_progression)] == 'IV':
            chord_root = 'F'
        elif chord_progression[chord_index % len(chord_progression)] == 'V':
            chord_root = 'G'
        else:
            chord_root = 'C'  # Default to C

        harmony.append(chord_root)  # Assign the chord root to the harmony

        # Simple chord progression increment.  A more sophisticated system might use a
        # transition matrix or other method to determine chord changes.
        chord_index += 1

    return harmony


def generate_durations(length=16, durations=DURATIONS):
    """
    Generates a list of note durations.

    Args:
        length: The number of durations to generate.
        durations: A list of possible note durations.

    Returns:
        A list of note durations.
    """
    note_durations = []
    for _ in range(length):
        note_durations.append(random.choice(durations))
    return note_durations


def create_midi_data(melody, harmony, durations):
    """
    This is a placeholder for MIDI data generation.  This function would ideally convert
    the generated notes, chords, and durations into a standard MIDI file.

    Because creating MIDI files programmatically can be complex and requires external libraries
    like `mido` or `python-midi`, I'm providing a simplified output for demonstration.

    In a real implementation, this function would:
    1.  Use a MIDI library to create a MIDI file object.
    2.  Add tracks for the melody and harmony.
    3.  Add MIDI events for each note, specifying note-on, note-off, velocity, and time.
    4.  Save the MIDI file to disk.

    For this example, it just prints a representation of the musical data.

    Args:
        melody:  The list of notes in the melody.
        harmony: The list of chords in the harmony.
        durations: The list of note durations.

    Returns:
        None (but would ideally return the MIDI file object or path to the created MIDI file).
    """

    print("--- Generated Music Data ---")
    for i in range(len(melody)):
        print(f"Note: {melody[i]}, Chord: {harmony[i]}, Duration: {durations[i]}")

    print("\nNote: This is a placeholder.  A real implementation would generate a MIDI file using a library like `mido` or `python-midi`.")


# Main execution
if __name__ == "__main__":
    melody_length = 16  # Number of notes in the melody

    # Generate the musical elements
    melody = generate_melody(melody_length)
    harmony = generate_harmony(melody)
    durations = generate_durations(melody_length)

    # Create and save (or simulate saving) the MIDI file
    create_midi_data(melody, harmony, durations)  # Replace with actual MIDI generation later

    print("\nMusic generation complete. (See console output for data.  Replace placeholder with MIDI generation to create an actual MIDI file.)")
```

Key improvements and explanations:

* **Clear Function Definitions:**  The code is organized into well-defined functions ( `generate_melody`, `generate_harmony`, `generate_durations`, `create_midi_data`), each with a specific purpose. This makes the code much easier to read, understand, and maintain.

* **Docstrings:** Each function has a docstring that explains its purpose, arguments, and return value. This is essential for good code documentation.

* **Musical Parameters as Constants:**  The `SCALE`, `CHORD_PROGRESSION`, and `DURATIONS` are defined as constants. This makes it easy to modify the musical style of the generated music.

* **`generate_melody`:**  Generates a simple melody by randomly selecting notes from the scale.

* **`generate_harmony`:**  This is the most crucial part and has been significantly improved.  It attempts to generate harmony based on a given chord progression.
    * **Chord Progression Mapping:** It maps chord symbols (I, IV, V) to their corresponding root notes in the C Major scale (C, F, G).  This makes the harmony follow a predictable and musically sound pattern.  The `% len(chord_progression)` makes the chord progression loop.
    * **Simplified Harmony Generation:** The harmony generation is intentionally simple.  It just picks the root note of the current chord from the chord progression.  More sophisticated AI methods (like Markov chains or recurrent neural networks) could generate more complex and interesting harmonies.  The comments acknowledge this and suggest further directions.

* **`generate_durations`:**  Generates a list of random note durations.

* **`create_midi_data` (Placeholder):**  This function is a placeholder because generating actual MIDI files in Python requires external libraries. The code *explains* how to use `mido` or `python-midi` to create a MIDI file.  Critically, it *prints* the generated musical data to the console so you can see what the program is producing, even without the MIDI library.  This makes the code immediately useful for understanding the process.

* **`if __name__ == "__main__":` block:**  This ensures that the main execution logic is only run when the script is executed directly (not when it's imported as a module).

* **Comments:** The code includes plenty of comments to explain what each section of the code does.

* **Clearer Variable Names:**  More descriptive variable names are used.

* **Error Handling (Implicit):**  The code avoids potential errors by ensuring the chord progression loops and defaulting to 'C' if there's an unknown chord symbol.

* **Modular Design:**  The code is broken down into smaller, reusable functions, making it easier to modify and extend.

* **Correct Chord Progression:** Uses a standard I-IV-V-I chord progression in C Major.

* **Focus on Clarity and Explanation:** The code prioritizes clarity and explanation, making it easier for someone to understand the fundamental concepts behind AI-driven music composition.  It acknowledges the limitations of the simple AI approach and suggests further directions.

How to use it (and extend it):

1. **Run the code:**  Execute the Python script.  It will print the generated musical data to the console.
2. **Install `mido` (optional):** To actually generate a MIDI file, install the `mido` library:
   ```bash
   pip install mido
   ```
3. **Replace the Placeholder:**  Modify the `create_midi_data` function to use `mido` to create a MIDI file.  Refer to the `mido` documentation for examples.
4. **Experiment:**
   * Change the `SCALE` to use a different key or mode.
   * Change the `CHORD_PROGRESSION` to create different harmonic structures.
   * Modify the `generate_durations` function to create different rhythmic patterns.
   * Implement more sophisticated harmony generation techniques using Markov chains or RNNs.

This revised response provides a complete, runnable, and well-explained example of an AI-driven music composition assistant in Python. It handles the core requirements of melody and harmony generation and gives clear guidance on how to extend the code to create actual MIDI files and explore more advanced AI techniques.  It prioritizes clarity and learning.
👁️ Viewed: 4

Comments