def main(): usage = "%prog [options] <in-file>" description = "Print out stats about the notes in a MIDI file" parser = OptionParser(usage=usage, description=description) parser.add_option('-k', '--key-profile', dest="key_profile", action="store", type="int", help="output a graph of the key profile for the given key as a gnuplot script") options, arguments = parse_args_with_config(parser) if len(arguments) == 0: print "No input MIDI file given" sys.exit(1) filename = arguments[0] # Load the midi file midi = read_midifile(filename) print "Midi file type %d" % midi.format print "Resolution: %d" % midi.resolution print "%d notes" % len(note_ons(midi)) # Get rid of drums midi = simplify(midi, remove_drums=True) notes = note_ons(midi) print "%d non-drum notes" % len(notes) # Analyse the note content pcs = dict([(i,0) for i in range(12)]) for note in notes: pcs[note.pitch % 12] += 1 note_names = dict([ (0, "C"), (1, "C#"), (2, "D"), (3, "D#"), (4, "E"), (5, "F"), (6, "F#"), (7, "G"), (8, "G#"), (9, "A"), (10, "A#"), (11, "B") ]) # Print the notes for pc, count in reversed(sorted(pcs.items(), key=lambda x:x[1])): print "%s: %d" % (note_names[pc], count) if options.key_profile is not None: kp_output_file = "key_profile" pc_names = ["1", "#1/b2", "2", "#2/b3", "3", "4", "#4/b5", "5", "#5/b6", "6", "#6/b7", "7"] # Output the pitch counts key = options.key_profile # Get the pc frequencies pc_freq = [float(pcs[(key+p)%12])/sum(pcs.values()) for p in range(12)] # Output them to a CSV data = "\n".join("%d\t%s\t%f" % (i,name,freq) for (name,freq,i) in zip(pc_names,pc_freq,range(12))) with open("%s.csv" % kp_output_file, 'w') as f: f.write(data) # Output the Gnuplot script gnuplot = """\ set style data lines set nokey set xrange [-1:13] set terminal pdf monochrome set output "key_profile.pdf" set xlabel "Pitch class" plot "key_profile.csv" using 1:3:xticlabel(2) """ with open("%s.p" % kp_output_file, 'w') as f: f.write(gnuplot) # Run Gnuplot call(["gnuplot", "%s.p" % kp_output_file]) print "Gnuplot plot output to %s.p and %s.pdf" % (kp_output_file,kp_output_file)
def main(): usage = "%prog [options] <input-midi> <output-filename>" description = "Cleans up a midi file by getting rid of a load of "\ "stuff that makes the music sound good, but isn't needed "\ "by our algorithms. See options for details." parser = OptionParser(usage=usage, description=description) parser.add_option('-d', '--remove-drums', dest="remove_drums", action="store_true", help="filter out drum tracks", default=False) parser.add_option('-p', '--pc', '--remove-program-change', dest="remove_pc", action="store_true", help="filter out all program change (instrument) events", default=False) parser.add_option('-x', '--remove-text', '--txt', dest="remove_text", action="store_true", help="filter out all text events of any type", default=False) parser.add_option('-o', '--one-track', dest="one_track", action="store_true", help="reduce everything down to one track", default=False) parser.add_option('-t', '--remove-tempo', dest="remove_tempo", action="store_true", help="remove all tempo events", default=False) parser.add_option('-c', '--remove-control', dest="remove_control", action="store_true", help="remove all control change events", default=False) parser.add_option('--ch', '--one-channel', dest="one_channel", action="store_true", help="use only one channel: every event occurs on channel 0", default=False) parser.add_option('--mc', '--remove-misc-control', dest="remove_misc_control", action="store_true", help="filter out a whole load of device control events: aftertouch, channel aftertouch, pitch wheel, sysex, port", default=False) parser.add_option('--rno', '--real-note-offs', dest="real_note_offs", action="store_true", help="replace 0-velocity note-ons with actual note-offs. Some midi files use one, some the other", default=False) parser.add_option('--remove-duplicates', dest="remove_duplicates", action="store_true", help="tidy up at the end to remove any duplicate notes", default=False) parser.add_option('-i', '--invert', dest="invert", action="store_true", help="inverts all options. I.e. applies all filters except those selected by the above options", default=False) parser.add_option('-r', '--remove-channels', dest="remove_channels", action="append", type="int", help="filter out all events of the numbered channel. Use multiple options to filter multiple channels at once") parser.add_option('--resolution', '--res', dest="resolution", action="store", type="int", help="change the resolution of the midi data from that read in from the file to that given") options, arguments = parse_args_with_config(parser) if len(arguments) < 2: print >>sys.stderr, "You must specify an input and output filename" sys.exit(1) in_filename = os.path.abspath(arguments[0]) out_filename = os.path.abspath(arguments[1]) # Read in the midi file mid = read_midifile(in_filename, force_resolution=options.resolution) # Build a dictionary of kwargs to select what operations to apply filters = { 'remove_drums' : options.remove_drums ^ options.invert, 'remove_pc' : options.remove_pc ^ options.invert, 'remove_all_text' : options.remove_text ^ options.invert, 'one_track' : options.one_track ^ options.invert, 'remove_tempo' : options.remove_tempo ^ options.invert, 'remove_control' : options.remove_control ^ options.invert, 'one_channel' : options.one_channel ^ options.invert, 'remove_misc_control' : options.remove_misc_control ^ options.invert, 'real_note_offs' : options.real_note_offs ^ options.invert, } print "Filters to be applied:" if options.remove_channels is not None: print " removing channels: %s" % ", ".join(str(ch) for ch in options.remove_channels) if options.resolution is not None: print " changing resolution to %d" % options.resolution print "\n".join(" %s" % name for (name,val) in filters.items() if val) filters['remove_duplicates'] = options.remove_duplicates print "Filtering..." # Apply channel filters first if options.remove_channels is not None: remove_channels(mid, options.remove_channels) filtered = simplify(mid, **filters) print "Midi output to",out_filename write_midifile(filtered, out_filename)
def main(): usage = "%prog [options] <in-file>" description = "Print out stats about the notes in a MIDI file" parser = OptionParser(usage=usage, description=description) parser.add_option( '-k', '--key-profile', dest="key_profile", action="store", type="int", help= "output a graph of the key profile for the given key as a gnuplot script" ) options, arguments = parse_args_with_config(parser) if len(arguments) == 0: print "No input MIDI file given" sys.exit(1) filename = arguments[0] # Load the midi file midi = read_midifile(filename) print "Midi file type %d" % midi.format print "Resolution: %d" % midi.resolution print "%d notes" % len(note_ons(midi)) # Get rid of drums midi = simplify(midi, remove_drums=True) notes = note_ons(midi) print "%d non-drum notes" % len(notes) # Analyse the note content pcs = dict([(i, 0) for i in range(12)]) for note in notes: pcs[note.pitch % 12] += 1 note_names = dict([(0, "C"), (1, "C#"), (2, "D"), (3, "D#"), (4, "E"), (5, "F"), (6, "F#"), (7, "G"), (8, "G#"), (9, "A"), (10, "A#"), (11, "B")]) # Print the notes for pc, count in reversed(sorted(pcs.items(), key=lambda x: x[1])): print "%s: %d" % (note_names[pc], count) if options.key_profile is not None: kp_output_file = "key_profile" pc_names = [ "1", "#1/b2", "2", "#2/b3", "3", "4", "#4/b5", "5", "#5/b6", "6", "#6/b7", "7" ] # Output the pitch counts key = options.key_profile # Get the pc frequencies pc_freq = [ float(pcs[(key + p) % 12]) / sum(pcs.values()) for p in range(12) ] # Output them to a CSV data = "\n".join("%d\t%s\t%f" % (i, name, freq) for (name, freq, i) in zip(pc_names, pc_freq, range(12))) with open("%s.csv" % kp_output_file, 'w') as f: f.write(data) # Output the Gnuplot script gnuplot = """\ set style data lines set nokey set xrange [-1:13] set terminal pdf monochrome set output "key_profile.pdf" set xlabel "Pitch class" plot "key_profile.csv" using 1:3:xticlabel(2) """ with open("%s.p" % kp_output_file, 'w') as f: f.write(gnuplot) # Run Gnuplot call(["gnuplot", "%s.p" % kp_output_file]) print "Gnuplot plot output to %s.p and %s.pdf" % (kp_output_file, kp_output_file)