Learn how to create custom MIDI generator plugins for the Piano Roll application
Plugins are Python files that define classes inheriting from the PluginBase
class.
Each plugin must implement a standard interface to work with the Plugin Manager.
# plugins/my_custom_generator.py
import random
import pretty_midi
from plugin_api import PluginBase
class MyCustomGenerator(PluginBase):
"""
My custom MIDI generator plugin
"""
def __init__(self):
super().__init__()
self.name = "My Custom Generator"
self.description = "Generates MIDI notes using my algorithm"
self.author = "Your Name"
self.version = "1.0"
# Define parameters
self.parameters = {
"param_name": {
"type": "int", # Can be "int", "float", "bool", "list", or "str"
"min": 0, # For numeric types
"max": 100, # For numeric types
"default": 50, # Default value
"description": "Description of the parameter"
# For "list" type, add "options": ["Option1", "Option2", ...]
},
# More parameters...
}
def generate(self, existing_notes=None, **kwargs):
"""
Generate MIDI notes
Args:
existing_notes: Optional list of existing notes
**kwargs: Parameters passed from the UI
Returns:
List of generated pretty_midi.Note objects
"""
# Extract parameters with defaults
param_value = kwargs.get("param_name", self.parameters["param_name"]["default"])
# Your generation algorithm here...
result = []
# Example: Create a simple note
note = pretty_midi.Note(
velocity=100,
pitch=60, # Middle C
start=0.0,
end=1.0
)
result.append(note)
return result
plugins
directory.PluginBase
and implements at least the generate()
method.
The Piano Roll uses the pretty_midi
library for MIDI note representation.
Each note is a pretty_midi.Note
object with the following properties:
pitch
: The MIDI note number (0-127)velocity
: The velocity of the note (0-127)start
: The start time in secondsend
: The end time in secondsThe following parameter types are supported:
int
: Integer value with min/max rangefloat
: Floating-point value with min/max rangebool
: Boolean value (true/false)list
: Selection from a list of optionsstr
: Text value (can be combined with options for a dropdown)# Integer parameter
"tempo": {
"type": "int",
"min": 60,
"max": 240,
"default": 120,
"description": "Tempo in BPM"
}
# Float parameter
"probability": {
"type": "float",
"min": 0.0,
"max": 1.0,
"default": 0.5,
"description": "Probability of note generation"
}
# Boolean parameter
"use_existing": {
"type": "bool",
"default": True,
"description": "Use existing notes as input"
}
# List parameter
"scale": {
"type": "list",
"options": ["Major", "Minor", "Pentatonic", "Blues"],
"default": "Major",
"description": "Musical scale to use"
}
The application comes with several example plugins:
motif_generator.py
: Creates melodies based on motifs and variationsmarkov_generator.py
: Uses Markov chains to generate melodiesmelody_generator.py
: Emotional melody generator inspired by FL Studiogodzilla_piano_transformer.py
: AI-powered generation using Godzilla Piano Transformer model
The godzilla_piano_transformer.py
plugin demonstrates integration with external AI models:
api_helpers.py
for common operationsStudy these examples to understand how to create more complex generation algorithms.
validate_parameters
method to ensure valid input.print()
statements. The output will appear in the terminal where you launched the application.
For advanced plugins, you can:
For plugins that integrate with external APIs (like AI models), use the helper utilities in api_helpers.py
:
from .api_helpers import (
ApiConnectionManager,
MidiFileHandler,
TempFileManager,
validate_api_parameters,
create_fallback_melody
)
class MyAIPlugin(PluginBase):
def __init__(self):
super().__init__()
self.connection_manager = ApiConnectionManager(max_retries=3, timeout=60)
def generate(self, existing_notes=None, **kwargs):
with TempFileManager() as temp_manager:
# Create input MIDI file
input_path = MidiFileHandler.create_temp_midi_from_notes(existing_notes)
temp_manager.add_temp_file(input_path)
# Make API call with retry logic
result = self.connection_manager.call_with_retry(self._api_call, input_path, **kwargs)
# Parse result or fallback
if result:
return MidiFileHandler.parse_midi_file(result)
else:
return create_fallback_melody()
The api_helpers.py
module provides:
Share your plugins with the community! If you've created an interesting plugin, consider submitting it to our 🌟 Showcase Wiki or open a pull request to include it in the main repository.
Use the hashtag #MIDIGen
on social media to share your creations!
Download the application and start developing your custom MIDI generation algorithms today!
Download View on GitHub