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
Okaeri-Music is a telegram music bot project, allow you to play music on voice chat group telegram.

🗄️ PROJECT MUSIC,THIS IS MAINTAINED Okaeri-Music is a telegram bot project that's allow you to play music on telegram voice chat group Features 🔥 Th

Okaeri-Project 2 Dec 23, 2021
A python program for visualizing MIDI files, and displaying them in a spiral layout

SpiralMusic_python A python program for visualizing MIDI files, and displaying them in a spiral layout For a hardware version using Teensy & LED displ

Gavin 6 Nov 23, 2022
PatrikZero's CS:GO Hearing protection

Program that lowers volume when you die and get flashed in CS:GO. It aims to lower the chance of hearing damage by reducing overall sound exposure. Uses game state integration. Anti-cheat safe.

Patrik Žúdel 224 Dec 04, 2022
Python tools for the corpus analysis of popular music.

CATCHY Corpus Analysis Tools for Computational Hook discovery Python tools for the corpus analysis of popular music recordings. The tools can be used

Jan VB 20 Aug 20, 2022
Music Streaming Platform based on full implementation of DBSM

Symphony Music Streaming Platform based on full implementation of DBSM List of Commands Insert User (INSERT) Function to implement input in USER Get a

Parth Maradia 1 Nov 12, 2021
𝙰 𝙼𝚞𝚜𝚒𝚌 𝙱𝚘𝚝 𝙲𝚛𝚎𝚊𝚝𝚎𝚍 𝙱𝚢 𝚃𝚎𝚊𝚖𝙳𝚕𝚝 💖

TeamDltmusic 𝙰 𝙼𝚞𝚜𝚒𝚌 𝙱𝚘𝚝 𝙲𝚛𝚎𝚊𝚝𝚎𝚍 𝙱𝚢 𝚃𝚎𝚊𝚖𝙳𝚕𝚝 💖 Deploy String Session String Click hear you can find string session OR join He

TeamDlt 5 Jan 18, 2022
Python Audio Analysis Library: Feature Extraction, Classification, Segmentation and Applications

A Python library for audio feature extraction, classification, segmentation and applications This doc contains general info. Click here for the comple

Theodoros Giannakopoulos 5.1k Jan 02, 2023
Telegram Voice-Chat Bot Written In Python Using Pyrogram.

Telegram Voice-Chat Bot Telegram Voice-Chat Bot To Play Music From Various Sources In Your Group Support All linux based os. Windows Mac Diagram Requi

TheHamkerCat 314 Dec 29, 2022
A Python library for audio data augmentation. Inspired by albumentations. Useful for machine learning.

Audiomentations A Python library for audio data augmentation. Inspired by albumentations. Useful for deep learning. Runs on CPU. Supports mono audio a

Iver Jordal 1.2k Jan 07, 2023
Music bot of # Owner

Pokimane-Music Music bot of # Owner How To Host The easiest way to deploy this Bot Support Channel :- TeamDlt Support Group :- TeamDlt Please fork thi

5 Dec 23, 2022
PianoPlayer - Automatic fingering generator for piano scores

PianoPlayer - Automatic fingering generator for piano scores

Marco Musy 571 Jan 02, 2023
A telegram bot for which is help to play songs in vc 🥰 give 🌟 and fork this repo before use 😏

TamilVcMusic 🌟 TamilVCMusicBot 🌟 Give your 💙 Before clicking on deploy to heroku just click on fork and star just below How to deploy Click the bel

TamilBots 150 Dec 13, 2022
Open-Source bot to play songs in your Telegram's Group Voice Chat. Powered by @Akki_ThePro

VcPlayer Telegram Voice-Chat Bot [PyTGCalls] ⇝ Requirements ⇜ Account requirements A Telegram account to use as the music bot, You cannot use regular

Akki ThePro 2 Dec 25, 2021
Audio Retrieval with Natural Language Queries: A Benchmark Study

Audio Retrieval with Natural Language Queries: A Benchmark Study Paper | Project page | Text-to-audio search demo This repository is the implementatio

21 Oct 31, 2022
BART aids transcribe tasks by taking a source audio file and creating automatic repeated loops, allowing transcribers to listen to fragments multiple times

BART (Beyond Audio Replay Technology) aids transcribe tasks by taking a source audio file and creating automatic repeated loops, allowing transcribers to listen to fragments multiple times (with poss

2 Feb 04, 2022
Using python to generate a bat script of repetitive lines of code that differ in some way but can sort out a group of audio files according to their common names

Batch Sorting Using python to generate a bat script of repetitive lines of code that differ in some way but can sort out a group of audio files accord

David Mainoo 1 Oct 29, 2021
:sound: Play and Record Sound with Python :snake:

Play and Record Sound with Python This Python module provides bindings for the PortAudio library and a few convenience functions to play and record Nu

spatialaudio.net 750 Dec 31, 2022
Some utils for auto speech recognition

About Some utils for auto speech recognition. Utils Util Description Script Reset audio Reset sample rate, sample width, etc of audios.

1 Jan 24, 2022
A Music Player Bot for Discord Servers

A Music Player Bot for Discord Servers

Halil Acar 2 Oct 25, 2021
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