Giter VIP home page Giter VIP logo

py_midicsv's Introduction

py_midicsv

Downloads

A Python library inspired by the midicsv tool created by John Walker. Its main purpose is to bidirectionally convert between the binary MIDI format and a human-readable interpretation of the contained data in text format, expressed as CSV. If you found this library, you probably already know why you need it.

Installation

py_midicsv can be installed via pip:

$ pip install py_midicsv

Alternatively you can build the package by cloning this repository and installing via poetry:

$ git clone https://github.com/timwedde/py_midicsv.git
$ cd py_midicsv/
$ poetry install

Usage

As a Command Line Tool

Usage: midicsvpy [OPTIONS] INPUT_FILE OUTPUT_FILE

  Convert MIDI files to CSV files.

  midicsv reads a standard MIDI file and decodes it into a CSV file which
  preserves all the information in the MIDI file. The ASCII CSV file may be
  loaded into a spreadsheet or database application, or processed by a program
  to transform the MIDI data (for example, to key transpose a composition or
  extract a track from a multi-track sequence). A CSV file in the format
  created by midicsv may be converted back into a standard MIDI file with the
  csvmidi program.

  Specify an input file and an output file to process it. Either argument can
  be stdin/stdout.

  Some arguments are kept for backwards-compatibility with the original
  midicsv tooling. These are marked as NOOP in this command line interface.

Options:
  -n, --nostrict  Do not fail on parse/validation errors.
  -u, --usage     Print usage information (NOOP)
  -v, --verbose   Print debug information (NOOP)
  --help          Show this message and exit.
Usage: csvmidipy [OPTIONS] INPUT_FILE OUTPUT_FILE

  Convert CSV files to MIDI files.

  csvmidi reads a CSV file in the format written by midicsv and creates the
  equivalent standard MIDI file.

  Specify an input file and an output file to process it. Either argument can
  be stdin/stdout.

  Some arguments are kept for backwards-compatibility with the original
  csvmidi tooling. These are marked as NOOP in this command line interface.

Options:
  -n, --nostrict     Do not fail on parse/validation errors.
  -u, --usage        Print usage information (NOOP)
  -v, --verbose      Print debug information (NOOP)
  -z, --strict-csv   Raise exceptions on CSV errors (NOOP)
  -x, --no-compress  Do not compress status bytes (NOOP)
  --help             Show this message and exit.

As a Library

import py_midicsv as pm

# Load the MIDI file and parse it into CSV format
csv_string_list = pm.midi_to_csv("example.mid")

with open("example_converted.csv", "w") as f:
    f.writelines(csv_string_list)

# Parse the CSV output of the previous command back into a MIDI file
midi_object = pm.csv_to_midi(csv_string_list)

# Save the parsed MIDI file to disk
with open("example_converted.mid", "wb") as output_file:
    midi_writer = pm.FileWriter(output_file)
    midi_writer.write(midi_object)

Documentation

A full explanation of the midicsv file format can be found here.

Differences

This library adheres as much as possible to how the original library works, however generated files are not guaranteed to be entirely identical when compared bit-by-bit. This is mostly due to the handling of meta-event data, especially lyric events, since the encoding scheme has changed. The original library did not encode some of the characters in the Latin-1 set, while this version does.

Stargazers over time

Stargazers over time

py_midicsv's People

Contributors

joshnatis avatar snively avatar timwedde avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

py_midicsv's Issues

Don't work

in https://pypi.org/project/py-midicsv/#description

we have

import py_midicsv

# Load the MIDI file and parse it into CSV format
csv_string = py_midicsv.midi_to_csv("example.mid")

# Parse the CSV output of the previous command back into a MIDI file
midi_object = py_midicsv.csv_to_midi(csv_string)

# Save the parsed MIDI file to disk
with open("example_converted.mid", "wb") as output_file:
    midi_writer = py_midicsv.FileWriter(output_file)
    midi_writer.write(midi_object)

in https://github.com/timwedde/py_midicsv

we have

import py_midicsv as pm

# Load the MIDI file and parse it into CSV format
csv_string = pm.midi_to_csv("example.mid")

# Parse the CSV output of the previous command back into a MIDI file
midi_object = pm.csv_to_midi(csv_string)

# Save the parsed MIDI file to disk
with open("example_converted.mid", "wb") as output_file:
    midi_writer = pm.FileWriter(output_file)
    midi_writer.write(midi_object)

but none of them work or i did something wrong

Traceback (most recent call last):
  File "C:/Users/felipe/PycharmProjects/2020/PORRA.py", line 9, in <module>
    midi_writer.write(midi_object)
NameError: name 'midi_object' is not defined

Track meta-events—ignored?

I've used your library to successfully convert a midi file (or twelve) into .csv, with the exact same results as the unix midicsv functions. I was hoping your library would also handle meta-events for simplicity and convenience. The simplicity and convenience factors may be fairly limited for general use, so I will not be surprised if you feel it unnecessary.

My midi files definitely contain the information—Musescore 4 identifies the instruments correctly from the same file. Ideally I would like to have it available to any parsing scripts I pass over the .csv.

Is this a feature that is out of scope for the library?

Ignore commas at end of line

This is such a fantastic way to edit MIDI files - just change into text, edit, then change back again! Simple, but brilliant - glad to have found this project.

The issue I'm coming across is that for CSV files with mixed row lengths (such as these), Microsoft Excel will add extraneous commas to the ends of rows and they cause csvmidipy to fail. They can be removed fairly easily with Python script / RE / etc., but if the library could just ignore them it would be 1 fewer steps.

Library example mistake

In the Library example you show:

Parse the CSV output of the previous command back into a MIDI file

midi_object = pm.csv_to_midi(csv_string)

But it seems that csv_to_midi takes a file argument, not a string

Not enough values on to_TimeSignatureEvent

Hello and thank you for this great library! I am using it to do some processing on midi files, but I am having an issue with the TimeSignature of certain midi files.

Making a csv csv_string = py_midicsv.midi_to_csv(source) gives me the line 1, 0, Time_signature, 4, 2. Then when I try to parse it back to midi (without any processing) midi = py_midicsv.csv_to_midi(csv_string) I get the following error:

File ".../py_midicsv/csvmidi.py", line 46, in parse
    event = csv_to_midi_map[identifier](tr, time, identifier, line[3:])
File ".../py_midicsv/csv_converters.py", line 142, in to_TimeSignatureEvent
    num, denom, click, notesq = map(int, line)
ValueError: not enough values to unpack (expected 4, got 2)

Is this a known issue and how can I prevent it?

TypeError: ('Bad header in MIDI file.', b'')

Ran this on Google Colab, I uploaded a midi file and tested multiple and kept getting this error. What's going on?
(Also, IDK why the indentations arent working on the code)
`
#MIDI TO CSV

import py_midicsv as pm
def midi2csv():
save=input('filename\n')
print("Step 1")
owo=open(save,mode='w')
print("Step 2")
owo.write(str(pm.midi_to_csv(str(save)+'.mid')))
print("Step 3")
owo.close
print("Step 4")
messagebox.showinfo('Complete','file saved as {}'.format(save))
print("Step 5")
while 1==1:
x=input('midi to CSV: 0\nend: 2\n')
if x == '0':
midi2csv()
elif x == '2':
break
`

IndexError while Parsing MIDI

First of all, congrats for this Python library, which makes easier and integrable the parsing from MIDI files to CSV in Python. I'm encountering a problem while parsing a certain file, which gives the following error:

Traceback (most recent call last):
File "/Users/josepdecidrodriguez/Google Drive/IU/AML/Project/BachPropagation/src/dataset/parser.py", line 27, in
data = py_midicsv.midi_to_csv(file)
File "/Users/josepdecidrodriguez/Envs/BachPropagation-L4F7V3ER/lib/python3.7/site-packages/py_midicsv/midicsv.py", line 31, in parse
csv_file.append(midi_to_csv_map[type(event)](index + 1, abstime, event))
File "/Users/josepdecidrodriguez/Envs/BachPropagation-L4F7V3ER/lib/python3.7/site-packages/py_midicsv/midi_converters.py", line 117, in from_KeySignatureEvent
return write_event(track, time, "Key_signature", [event.get_alternatives(), '"major"' if event.data[1] == 0 else '"minor"'])
IndexError: list index out of range

This is given by the following file BWV_809____piano.txt (I've changed the extension to .txt to be able to upload it here).

name conflict

you should rename the command line midicsv and csvmidi scripts that you included. When I did the pip install, it overwrote my existing binaries from John Walker that were already located in /user/local/bin...

Secondly, if you're going to overwrite, then the pip installer should prompt me to make sure that is what I really want to do

thirdly, you should try to make your version of midicsv and csvmidi use the same command line options as the original binary so that if for some reason it does get overwritten and maybe I would even prefer to use your version for the Latin decoding...but if I have other scripts elsewhere based on using the binary midicsv, I don't want to break all those scripts.

csv export

Can we export a cvs file from MIDI?
Do you have an example? (new to python)

Unexpected status byte 0x80 and Warning: Unknown Meta MIDI Event: 10

File "midiToText.py", line 10, in convertMidiFile csv_string = pm.midi_to_csv(midiName) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midicsv.py", line 22, in parse pattern = read_midifile(file) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 221, in read_midifile return read_midifile(inp) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 223, in read_midifile return reader.read(midifile) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 45, in read self.parse_track(midifile, track) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 87, in parse_track event = self.parse_midi_event(trackdata) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 133, in parse_midi_event data = [trackdata.get_data_byte() for _ in range(cls.length)] File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 133, in <listcomp> data = [trackdata.get_data_byte() for _ in range(cls.length)] File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 36, in get_data_byte self.assert_data_byte(byte) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 29, in assert_data_byte assert data & 0x80 == 0, self.errmsg("Unexpected status byte", data) AssertionError: Unexpected status byte 0x80 at position 35078

https://easyupload.io/zz2wf6 midi file that causes the issue

when i comment out the assert the conversion passes, though i get a different error later with a different midi

Traceback (most recent call last): File "midiToText.py", line 35, in <module> convertMidiFolderOfFolders(midiName) File "midiToText.py", line 20, in convertMidiFolderOfFolders convertMidiFolder(path + "/" + midiName) File "midiToText.py", line 16, in convertMidiFolder convertMidiFile(path + "/" + midiName) File "midiToText.py", line 10, in convertMidiFile csv_string = pm.midi_to_csv(midiName) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midicsv.py", line 22, in parse pattern = read_midifile(file) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 221, in read_midifile return read_midifile(inp) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 223, in read_midifile return reader.read(midifile) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 45, in read self.parse_track(midifile, track) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 87, in parse_track event = self.parse_midi_event(trackdata) File "/home/user/anaconda3/lib/python3.8/site-packages/py_midicsv/midi/fileio.py", line 103, in parse_midi_event raise Warning("Unknown Meta MIDI Event: " + repr(cmd)) Warning: Unknown Meta MIDI Event: 10
https://easyupload.io/8y3mz2

file that causes the issue

Event length mismatch for PortEvent

Hi Tim,
Hope you can help me out. The package looks super cool, and I'm very much looking forward to working with it.
I'm having trouble getting it to work though. Have tried both as library in Python and as command prompts, but the error message is the same. I have also tried with different midi files (different sizes and from different sequencing software), and the error message still reads "Event length mismatch for PortEvent at position 65". Can you see, what I'm doing wrong?
I'm using:
Python 3.12.3
py-midicsv 4.1.0
windows 11

Cheers
Klaus

>>> csv_string = pm.midi_to_csv("test2B.mid")
Traceback (most recent call last):
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 134, in parse_midi_event
    event.check()
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\events.py", line 64, in check
    assert len(self.data) == self.length, f"Event length mismatch for {self.__class__.__name__}"
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Event length mismatch for PortEvent

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midicsv.py", line 22, in parse
    pattern = read_midifile(file, strict)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 275, in read_midifile
    return read_midifile(inp, strict)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 277, in read_midifile
    return reader.read(midifile, strict)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 66, in read
    self.parse_track(midifile, track, strict)
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 108, in parse_track
    event = self.parse_midi_event(trackdata, strict)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 136, in parse_midi_event
    warn_or_error(f"{e} at position {trackdata.pos()}", strict, is_parse=False)
  File "C:\Users\klsnl\Miniconda3\envs\py3_env\Lib\site-packages\py_midicsv\midi\fileio.py", line 23, in warn_or_error
    raise ValidationError(text)
py_midicsv.midi.fileio.ValidationError: Event length mismatch for PortEvent at position 65

Removing track from midi file

Hi timwedde. I'm trying to build a dataset of midi-files for use in a machine learning project. I've been using py_midicsv to try and remove the drum track from my files. I've tried looking for "Program_c, 9" in the file after conversion to CSV, deleting that whole section and converting back to MIDI, but something is breaking. Could you maybe suggest a better way to do this?
Thanks for the cool module!

Processing folder? Why not? :)

Tree project

├── csv
│   └── AllBlues.csv
├── mid
│   └── AllBlues.mid
├── midi
│   └── AllBlues.mid

Implementation

import os
import py_midicsv as pm

#MIDI folder
file_list=os.listdir(r"midi")

#Custom Path
path = ''

#Create folders where to save files
try:
    os.mkdir(path +"csv")
    os.mkdir(path +"mid") 

except OSError:
    print ("Creation of the directory %s failed" % path)
else:
    print ("Successfully created the directory %s" % path)
    
for file_name_song in file_list:
    
    name_file_without_ext = file_name_song.rsplit('.', 1)[0]
    
    # Load the MIDI file and parse it into CSV format
    csv_string = pm.midi_to_csv("midi/"+ name_file_without_ext + ".mid")

    with open("csv/" + name_file_without_ext + ".csv", "w") as f:
        f.writelines(csv_string)

    # Parse the CSV output of the previous command back into a MIDI file
    midi_object = pm.csv_to_midi(csv_string)

    # Save the parsed MIDI file to disk
    with open("mid/" + name_file_without_ext + ".mid", "wb") as output_file:
        midi_writer = pm.FileWriter(output_file)
        midi_writer.write(midi_object)
    print("processed file name:",file_name_song)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.