You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
3.2 KiB
72 lines
3.2 KiB
import mido
|
|
|
|
GENERAL_MIDI_PROGRAMS = [
|
|
"Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano",
|
|
"Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet",
|
|
"Celesta", "Glockenspiel", "Music Box", "Vibraphone",
|
|
"Marimba", "Xylophone", "Tubular Bells", "Dulcimer",
|
|
"Drawbar Organ", "Percussive Organ", "Rock Organ", "Church Organ",
|
|
"Reed Organ", "Accordion", "Harmonica", "Tango Accordion",
|
|
"Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)", "Electric Guitar (clean)",
|
|
"Electric Guitar (muted)", "Overdriven Guitar", "Distortion Guitar", "Guitar harmonics",
|
|
"Acoustic Bass", "Electric Bass (finger)", "Electric Bass (pick)", "Fretless Bass",
|
|
"Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2",
|
|
"Violin", "Viola", "Cello", "Contrabass",
|
|
"Tremolo Strings", "Pizzicato Strings", "Orchestral Harp", "Timpani",
|
|
"String Ensemble 1", "String Ensemble 2", "SynthStrings 1", "SynthStrings 2",
|
|
"Choir Aahs", "Voice Oohs", "Synth Choir", "Orchestra Hit",
|
|
"Trumpet", "Trombone", "Tuba", "Muted Trumpet",
|
|
"French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2",
|
|
"Soprano Sax", "Alto Sax", "Tenor Sax", "Baritone Sax",
|
|
"Oboe", "English Horn", "Bassoon", "Clarinet",
|
|
"Piccolo", "Flute", "Recorder", "Pan Flute",
|
|
"Blown Bottle", "Shakuhachi", "Whistle", "Ocarina",
|
|
"Lead 1 (square)", "Lead 2 (sawtooth)", "Lead 3 (calliope)", "Lead 4 (chiff)",
|
|
"Lead 5 (charang)", "Lead 6 (voice)", "Lead 7 (fifths)", "Lead 8 (bass + lead)",
|
|
"Pad 1 (new age)", "Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir)",
|
|
"Pad 5 (bowed)", "Pad 6 (metallic)", "Pad 7 (halo)", "Pad 8 (sweep)",
|
|
"FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)", "FX 4 (atmosphere)",
|
|
"FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes)", "FX 8 (sci-fi)",
|
|
"Sitar", "Banjo", "Shamisen", "Koto",
|
|
"Kalimba", "Bag pipe", "Fiddle", "Shanai",
|
|
"Tinkle Bell", "Agogo", "Steel Drums", "Woodblock",
|
|
"Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal",
|
|
"Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet",
|
|
"Telephone Ring", "Helicopter", "Applause", "Gunshot"
|
|
]
|
|
|
|
|
|
def get_instrument_name(program_number):
|
|
if 0 <= program_number < len(GENERAL_MIDI_PROGRAMS):
|
|
return GENERAL_MIDI_PROGRAMS[program_number]
|
|
return f"Unknown Program ({program_number})"
|
|
|
|
|
|
def has_musical_messages(track):
|
|
musical_types = {
|
|
'note_on', 'note_off', 'program_change', 'control_change',
|
|
'pitchwheel', 'aftertouch', 'polyphonic_key_pressure'
|
|
}
|
|
for msg in track:
|
|
if msg.type in musical_types:
|
|
return True
|
|
return False
|
|
|
|
|
|
def collect_tempo_changes(midi):
|
|
tempo_changes = []
|
|
DEFAULT_TEMPO = 500000
|
|
|
|
for track in midi.tracks:
|
|
absolute_time = 0
|
|
for msg in track:
|
|
absolute_time += msg.time
|
|
if msg.type == 'set_tempo':
|
|
bpm = mido.tempo2bpm(msg.tempo)
|
|
tempo_changes.append((absolute_time, bpm))
|
|
|
|
if not tempo_changes:
|
|
tempo_changes.append((0, mido.tempo2bpm(DEFAULT_TEMPO)))
|
|
|
|
tempo_changes.sort(key=lambda x: x[0])
|
|
return tempo_changes
|