Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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)