A Python port and library-fication of the midicsv tool by John Walker.

Overview

py_midicsv

CircleCI 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.

Options:
  -u, --usage
  -v, --verbose
  --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.

Options:
  -u, --usage
  -v, --verbose
  -z, --strict-csv
  -x, --no-compress
  --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 = pm.midi_to_csv("example.mid")

with open("example_converted.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("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.

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

    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

    opened by Blizzsuxx 6
  • name conflict

    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.

    opened by steveschow 4
  • Not enough values on to_TimeSignatureEvent

    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?

    opened by SaschaVanEssen 3
  • Don't work

    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
    
    opened by npeeth 3
  • IndexError while Parsing MIDI

    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).

    opened by josepdecid 3
  • several small fixes, to prevent crashes or unintended changes

    several small fixes, to prevent crashes or unintended changes

    The commits in this pull request together enable the package to read in any(?) valid midi file, convert it to CSV, and convert the CSV back to midi, without losing any data (or introducing any other changes). This was "almost" true already; most of the changes are small adjustments for particular event types.

    My test set of almost 5000 midi files inadvertently contained an invalid file, which (at first) the package happily translated to CSV and (almost) back to the original, without indicating a problem. The "Validate byte types in midi input" commit makes the package catch the bad file and report the place in the input where the problem was found. (Big points to Python's design for enabling that to be implemented cleanly!)

    See the commit comments for more details on the individual changes.

    opened by snively 2
  • Removing track from midi file

    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!

    opened by aesthese 2
  • Processing folder? Why not? :)

    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)
    
    opened by Midnight93 1
  • Fix example of writing CSV string to file

    Fix example of writing CSV string to file

    As you mention here, the midi_to_csv function returns a list of strings. write is expecting a string rather than a list of strings, so running the example results in an error. Your provided fix was to use the writelines function instead, but you forgot to update the README.

    opened by joshnatis 1
  • TypeError: ('Bad header in MIDI file.', b'')

    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 `

    opened by ExodusSolis 1
  • Add path option in csv2midi

    Add path option in csv2midi

    When converting CSV to MIDI, csv.reader requires a file object. I added the option to pass a file path that can be activated with an extra boolean parameter in order to not break current version behaviour.

    opened by josepdecid 1
Releases(v1.14.1)
Owner
Tim Wedde
I largely build solutions for odd problems you didn't know you had.
Tim Wedde
An audio guide for destroying oracles in Destiny's Vault of Glass raid

prophet An audio guide for destroying oracles in Destiny's Vault of Glass raid. This project allows you to make any encounter with oracles without hav

24 Sep 15, 2022
Python audio and music signal processing library

madmom Madmom is an audio signal processing library written in Python with a strong focus on music information retrieval (MIR) tasks. The library is i

Institute of Computational Perception 1k Dec 26, 2022
Port Hitsuboku Kumi Chinese CVVC voicebank to deepvocal. / 筆墨クミDeepvocal中文音源

Hitsuboku Kumi (筆墨クミ) is a UTAU virtual singer developed by Cubialpha. This project ports Hitsuboku Kumi Chinese CVVC voicebank to deepvocal. This is the first open-source deepvocal voicebank on Gith

8 Apr 26, 2022
A useful tool to generate chord progressions according to melody MIDIs

Auto chord generator, pure python package that generate chord progressions according to given melodies

Billy Yi 53 Dec 30, 2022
Royal Music You can play music and video at a time in vc

Royals-Music Royal Music You can play music and video at a time in vc Commands SOON String STRING_SESSION Deployment 🎖 Credits • 🇸ᴏᴍʏᴀ⃝🇯ᴇᴇᴛ • 🇴ғғɪ

2 Nov 23, 2021
Powerful, simple, audio tag editor for GNU/Linux

puddletag puddletag is an audio tag editor (primarily created) for GNU/Linux similar to the Windows program, Mp3tag. Unlike most taggers for GNU/Linux

341 Dec 26, 2022
Simple, hackable offline speech to text - using the VOSK-API.

Nerd Dictation Offline Speech to Text for Desktop Linux. This is a utility that provides simple access speech to text for using in Linux without being

Campbell Barton 844 Jan 07, 2023
A Python 3 script for capturing and recording a SDR stream to a WAV file (or serving it to a HTTP audio stream).

rfsoapyfile A Python 3 script for capturing and recording a SDR stream to a WAV file (or serving it to a HTTP audio stream). The script is threaded fo

4 Dec 19, 2022
Use python MIDI to write some simple music

Use Python MIDI to write songs

小宝 1 Nov 19, 2021
Speech Algorithms Collections

Speech Algorithms Collections

Ryuk 498 Jan 06, 2023
a library for audio and music analysis

aubio aubio is a library to label music and sounds. It listens to audio signals and attempts to detect events. For instance, when a drum is hit, at wh

aubio 2.9k Dec 30, 2022
Bot Music Pintar. Created by Rio

🎶 Rio Music 🎶 Kalo Fork Star Ya Bang Hehehe Requirements 📝 FFmpeg NodeJS nodesource.com Python 3.8+ or 3.7 PyTgCalls Generate String Using Replit ⤵

RioProjectX 7 Jun 15, 2022
Python implementation of the Short Term Objective Intelligibility measure

Python implementation of STOI Implementation of the classical and extended Short Term Objective Intelligibility measures Intelligibility measure which

Pariente Manuel 250 Dec 21, 2022
Suyash More 111 Jan 07, 2023
無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXのコア

無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXのコア

Hiroshiba 0 Aug 29, 2022
Mousai is a simple application that can identify song like Shazam

Mousai is a simple application that can identify song like Shazam. It saves the artist, album, and title of the identified song in a JSON file.

Dave Patrick 662 Jan 07, 2023
Implementation of "Slow-Fast Auditory Streams for Audio Recognition, ICASSP, 2021" in PyTorch

Auditory Slow-Fast This repository implements the model proposed in the paper: Evangelos Kazakos, Arsha Nagrani, Andrew Zisserman, Dima Damen, Slow-Fa

Evangelos Kazakos 57 Dec 07, 2022
Terminal-based music player written in Python for the best music in the world 🎵 🎧 💻

audius-terminal-player Terminal-based music player written in Python for the best music in the world 🎵 🎧 💻 Browse and listen to Audius from the com

Audius 21 Jul 23, 2022
A tool for retrieving audio in the past

Rewinder A tool for retrieving audio in the past. Ever felt like, I need to remember that discussion which happened 10 min back. Now you can! Rewind a

Bharat 1 Jan 24, 2022
music library manager and MusicBrainz tagger

beets Beets is the media library management system for obsessive music geeks. The purpose of beets is to get your music collection right once and for

beetbox 11.3k Dec 31, 2022