Čtvrtek , 26 Červen 2025
Domů Programování MIDI generator in Python
ProgramováníPython

MIDI generator in Python

blank
blank

Description of the Python Script

This Python script generates a MIDI file based on musical notes generated according to a specified musical genre. It utilizes the music21 library for music theory and MIDI file handling, along with the random and os modules.

Overview

The script consists of two main functions:

  1. generate_midi(notes, filename): Creates a MIDI file from a list of note names.
  2. generate_notes_by_genre(genre, length): Generates a list of note names based on the specified musical genre.

At the end of the script, there is an example usage where the user is prompted to enter a genre, and the script generates a MIDI file named genre_output.mid based on that genre.


Detailed Breakdown

Import Statements

from music21 import *
import random
import os
  • music21: A Python library for computer-aided musicology, which provides tools to analyze, create, and manipulate music.
  • random: Used to generate random choices for notes and scales.
  • os: Provides functions for interacting with the operating system, such as file path manipulation.

Function: generate_midi(notes, filename="output.mid")

Purpose

Generates a MIDI file from a list of note names.

Parameters

  • notes: A list of note names as strings (e.g., ['C4', 'D4', 'E4']).
  • filename: The name of the MIDI file to create. Defaults to "output.mid".

Function Logic

  1. Create a Stream: Initializes a Stream object from music21 to hold musical elements.

midi_stream = stream.Stream()

2. Add Notes to the Stream: Iterates over the list of note names, creates a Note object for each, and appends it to the stream.

for note_name in notes:
    n = note.Note(note_name)
    midi_stream.append(n)

3. Translate Stream to MIDI: Converts the stream into a MIDI file object.

mf = midi.translate.streamToMidiFile(midi_stream)

4. Determine File Path: Gets the current working directory and constructs the full file path for the MIDI file.

current_directory = os.getcwd()
file_path = os.path.join(current_directory, filename)

5. Write MIDI File: Opens the file in write-binary mode, writes the MIDI data, and closes the file.

mf.open(file_path, 'wb')
mf.write()
mf.close()

6. Confirmation Message: Prints a message indicating the MIDI file has been created. The message is in Czech:

print(f"Soubor MIDI byl vytvořen v: {file_path}")

Translation: „The MIDI file was created at: [file_path]“


Function: generate_notes_by_genre(genre, length=10)

Purpose

Generates a list of note names based on the specified musical genre.

Parameters

  • genre: A string indicating the musical genre (e.g., „rock“, „pop“).
  • length: The number of notes to generate. Defaults to 10.

Function Logic

  1. Define Scales and Rhythms Based on Genre:

    • Rock:

scales = [scale.MinorScale('A'), scale.HarmonicMinorScale('E')]
rhythms = [[0.5, 0.5, 1], [1, 0.5, 0.5], [0.25, 0.25, 0.25, 0.25, 1]]

Pop:

scales = [scale.MajorScale('C'), scale.MajorScale('G')]
rhythms = [[0.5, 0.5, 1], [1, 1], [0.5, 0.5, 0.5, 0.5]]

Other Genres (Default):

scales = [scale.MajorScale('C')]
rhythms = [[1]]

2. Initialize Notes List and Select a Scale:

notes = []
current_scale = random.choice(scales)

3. Generate Notes:

  • Loop length times to generate the specified number of notes.
  • For each iteration:
    • Randomly select a pitch from the current_scale.
    • Randomly select a rhythm pattern from rhythms.
    • For each duration in the selected rhythm pattern, append the note’s name to the notes list.
for _ in range(length):
    note_pitch = random.choice(current_scale.getPitches())
    note_duration = random.choice(rhythms)

    for duration in note_duration:
        notes.append(str(note_pitch))
  • Note: In this implementation, the note durations are not utilized when generating the MIDI file; only the note pitches are used.

4. Return the List of Notes:

return notes

Example Usage

# Example usage:
genre = input("Zadejte žánr (rock, pop, nebo jiný a stiskněte Enter): ")
notes = generate_notes_by_genre(genre, length=20)  # Generate 20 notes
generate_midi(notes, filename="genre_output.mid")

Explanation

  1. User Input:

    • The script prompts the user to enter a genre. The prompt is in Czech:

"Zadejte žánr (rock, pop, nebo jiný a stiskněte Enter): "

Translation: „Enter a genre (rock, pop, or other and press Enter): „

2. Generate Notes:

  • Calls generate_notes_by_genre with the user’s input and generates a list of 20 notes.

3. Generate MIDI File:

  • Calls generate_midi with the generated notes and creates a MIDI file named "genre_output.mid".

How to Use the Script

  1. Install Dependencies:

    • Ensure you have music21 installed:

pip install music21

2. Run the Script:

  • Execute the script in a Python environment.

python script_name.py

3. Enter a Genre:

    • When prompted, input one of the supported genres: "rock", "pop", or any other text for the default option.

4. Output:

  • The script generates a MIDI file named genre_output.mid in the current working directory.
  • A confirmation message displays the path to the created MIDI file.

Notes and Considerations

  • Genre Customization:

    • The script currently supports „rock“ and „pop“ genres with predefined scales and rhythms.
    • For „rock“, it uses minor scales and harmonic minor scales.
    • For „pop“, it uses major scales.
    • Any other input defaults to a simple C major scale.
  • Rhythm Handling:

    • While rhythms are defined in the rhythms lists, the current implementation does not apply note durations when adding notes to the MIDI file. To incorporate rhythms, additional code is needed to set the duration of each note.
  • Internationalization:

    • Some prompts and messages are in Czech. You may translate them to English or any other language as needed.

      • Input Prompt:

genre = input("Enter a genre (rock, pop, or other and press Enter): ")

Confirmation Message:

print(f"The MIDI file was created at: {file_path}")
  • Enhancements:

    • Incorporate Note Durations:

      • Modify the generate_midi function to handle note durations based on the rhythm patterns.
    • Expand Genre Support:

      • Add more genres with appropriate scales and rhythms.
    • Error Handling:

      • Add validation for user input and handle potential errors gracefully.
    • User Interface:

      • Create a graphical user interface (GUI) or a command-line menu for better usability.

Example Modification to Include Durations

To make the script utilize note durations from the rhythm patterns, you can modify the generate_notes_by_genre function to return a list of tuples containing note names and durations.

Modified generate_notes_by_genre Function

def generate_notes_by_genre(genre, length=10):
    """Generates notes with durations based on the specified genre."""
    if genre.lower() == "rock":
        # Rock scales and rhythms
        scales = [scale.MinorScale('A'), scale.HarmonicMinorScale('E')]
        rhythms = [[0.5, 0.5, 1], [1, 0.5, 0.5], [0.25, 0.25, 0.25, 0.25, 1]]
    elif genre.lower() == "pop":
        # Pop scales and rhythms
        scales = [scale.MajorScale('C'), scale.MajorScale('G')]
        rhythms = [[0.5, 0.5, 1], [1, 1], [0.5, 0.5, 0.5, 0.5]]
    else:
        # Default to a simple major scale
        scales = [scale.MajorScale('C')]
        rhythms = [[1]]

    notes = []
    current_scale = random.choice(scales)
    for _ in range(length):
        note_pitch = random.choice(current_scale.getPitches())
        note_duration_pattern = random.choice(rhythms)

        for duration in note_duration_pattern:
            notes.append((str(note_pitch), duration))

    return notes

Modified generate_midi Function

def generate_midi(notes_with_durations, filename="output.mid"):
    """Generates a MIDI file from a list of notes with durations.

    Args:
        notes_with_durations: A list of tuples containing note names and durations.
        filename: The name of the MIDI file to create.
    """
    midi_stream = stream.Stream()
    for note_name, duration in notes_with_durations:
        n = note.Note(note_name)
        n.quarterLength = duration
        midi_stream.append(n)
    mf = midi.translate.streamToMidiFile(midi_stream)

    current_directory = os.getcwd()
    file_path = os.path.join(current_directory, filename)

    mf.open(file_path, 'wb')
    mf.write()
    mf.close()

    print(f"The MIDI file was created at: {file_path}")

Adjusted Example Usage

# Example usage:
genre = input("Enter a genre (rock, pop, or other and press Enter): ")
notes = generate_notes_by_genre(genre, length=20)  # Generate 20 notes with durations
generate_midi(notes, filename="genre_output.mid")

Conclusion

This script provides a basic framework for generating MIDI files based on musical genres. By leveraging the music21 library, it allows for music theory concepts like scales and rhythms to be incorporated into the generated music. With further development and customization, it can be expanded into a more sophisticated music generation tool.

Zanechte komentář

Napsat komentář

Související články

blank
ProgramováníStrojové učeníUmělá inteligence

Neuromorfní čipy vs. GPU/TPU

Top články Neuromorfní čipy vs. GPU/TPU 19. 6. 2025 Edge-AI v IoT:...

blank
PythonTensorFlow.js

🐍 Úvod do TensorFlow Lite & Python

TensorFlow Lite (TFLite) ve spojení s Pythonem otevírá dveře on-device strojovému učení...

blank
Python

Detekční systém v Pythonu s GPU akcelerací

Desktop Motion Detection s GPU akcelerací🎯 Účel programuTento nástroj sleduje vybrané okno...

blank
PythonYouTube videa

Python generátor náhledového obrázku YouTube videa

import re import os import requests import argparse from urllib.parse import urlparse,...