Melanchall.DryWetMidi 7.0.2

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Melanchall.DryWetMidi --version 7.0.2                
NuGet\Install-Package Melanchall.DryWetMidi -Version 7.0.2                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Melanchall.DryWetMidi" Version="7.0.2" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Melanchall.DryWetMidi --version 7.0.2                
#r "nuget: Melanchall.DryWetMidi, 7.0.2"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Melanchall.DryWetMidi as a Cake Addin
#addin nuget:?package=Melanchall.DryWetMidi&version=7.0.2

// Install Melanchall.DryWetMidi as a Cake Tool
#tool nuget:?package=Melanchall.DryWetMidi&version=7.0.2                

DryWetMIDI Logo

NuGet (full) NuGet (nativeless) Unity asset (full) Unity asset (nativeless)

DryWetMIDI is the .NET library to work with MIDI data and MIDI devices. It allows:

  • Read, write and create Standard MIDI Files (SMF). It is also possible to read RMID files where SMF wrapped to RIFF chunk. You can easily catch specific error when reading or writing MIDI file since all possible errors in a MIDI file are presented as separate exception classes.
  • Send MIDI events to/receive them from MIDI devices, play MIDI data and record it. This APIs support Windows and macOS.
  • Finely adjust process of reading and writing. It allows, for example, to read corrupted files and repair them, or build MIDI file validators.
  • Implement custom meta events and custom chunks that can be written to and read from MIDI files.
  • Manage content of a MIDI file either with low-level objects, like event, or high-level ones, like note (read the High-level data managing section of the library docs).
  • Build musical compositions (see Pattern page of the library docs) and use music theory API (see Music Theory - Overview article).
  • Perform complex tasks like quantizing, notes splitting or converting MIDI file to CSV representation (see Tools page of the library docs).

Please see Getting started section below for quick jump into the library.

Warning
If you want to create an issue or a discussion, read this article first – Support.

Projects using DryWetMIDI

Here the list of noticeable projects that use DryWetMIDI:

If you find that DryWetMIDI has been useful for your project, please put a link to the library in your project's About section or something like that.

Getting Started

Let's see some examples of what you can do with DryWetMIDI.

To read a MIDI file you have to use Read static method of the MidiFile:

var midiFile = MidiFile.Read("Some Great Song.mid");

or, in more advanced form (visit Reading settings page on the library docs to learn more about how to adjust process of reading)

var midiFile = MidiFile.Read(
    "Some Great Song.mid",
    new ReadingSettings
    {
        NoHeaderChunkPolicy = NoHeaderChunkPolicy.Abort,
        CustomChunkTypes = new ChunkTypesCollection
        {
            { typeof(MyCustomChunk), "Cstm" }
        }
    });

To write MIDI data to a file you have to use Write method of the MidiFile:

midiFile.Write("My Great Song.mid");

or, in more advanced form (visit Writing settings page on the library docs to learn more about how to adjust process of writing)

midiFile.Write(
    "My Great Song.mid",
    true,
    MidiFileFormat.SingleTrack,
    new WritingSettings
    {
        UseRunningStatus = true,
        NoteOffAsSilentNoteOn = true
    });

Of course you can create a MIDI file from scratch by creating an instance of the MidiFile and writing it:

var midiFile = new MidiFile(
    new TrackChunk(
        new SetTempoEvent(500000)),
    new TrackChunk(
        new TextEvent("It's just single note track..."),
        new NoteOnEvent((SevenBitNumber)60, (SevenBitNumber)45),
        new NoteOffEvent((SevenBitNumber)60, (SevenBitNumber)0)
        {
            DeltaTime = 400
        }));

midiFile.Write("My Future Great Song.mid");

or

var midiFile = new MidiFile();
TempoMap tempoMap = midiFile.GetTempoMap();

var trackChunk = new TrackChunk();
using (var notesManager = trackChunk.ManageNotes())
{
    NotesCollection notes = notesManager.Objects;
    notes.Add(new Note(
        NoteName.A,
        4,
        LengthConverter.ConvertFrom(
            new MetricTimeSpan(hours: 0, minutes: 0, seconds: 10),
            0,
            tempoMap)));
}

midiFile.Chunks.Add(trackChunk);
midiFile.Write("My Future Great Song.mid");

If you want to speed up playing back a MIDI file by two times you can do it with this code:

foreach (var trackChunk in midiFile.Chunks.OfType<TrackChunk>())
{
    foreach (var setTempoEvent in trackChunk.Events.OfType<SetTempoEvent>())
    {
        setTempoEvent.MicrosecondsPerQuarterNote /= 2;
    }
}

Of course this code is simplified. In practice a MIDI file may not contain SetTempo event which means it has the default one (500,000 microseconds per beat).

Instead of modifying a MIDI file you can use Playback class:

using (var outputDevice = OutputDevice.GetByName("Microsoft GS Wavetable Synth"))
using (var playback = midiFile.GetPlayback(outputDevice))
{
    playback.Speed = 2.0;
    playback.Play();
}

To get duration of a MIDI file as TimeSpan use this code:

TempoMap tempoMap = midiFile.GetTempoMap();
TimeSpan midiFileDuration = midiFile
    .GetTimedEvents()
    .LastOrDefault(e => e.Event is NoteOffEvent)
    ?.TimeAs<MetricTimeSpan>(tempoMap) ?? new MetricTimeSpan();

or simply:

TimeSpan midiFileDuration = midiFile.GetDuration<MetricTimeSpan>();

Suppose you want to remove all C# notes from a MIDI file. It can be done with this code:

foreach (var trackChunk in midiFile.GetTrackChunks())
{
    using (var notesManager = trackChunk.ManageNotes())
    {
        notesManager.Objects.RemoveAll(n => n.NoteName == NoteName.CSharp);
    }
}

or

midiFile.RemoveNotes(n => n.NoteName == NoteName.CSharp);

To get all chords of a MIDI file at 20 seconds from the start of the file write this:

TempoMap tempoMap = midiFile.GetTempoMap();
IEnumerable<Chord> chordsAt20seconds = midiFile
    .GetChords()
    .AtTime(
        new MetricTimeSpan(0, 0, 20),
        tempoMap,
        LengthedObjectPart.Entire);

To create a MIDI file with single note which length will be equal to length of two triplet eighth notes you can use this code:

var midiFile = new MidiFile();
var tempoMap = midiFile.GetTempoMap();

var trackChunk = new TrackChunk();
using (var notesManager = trackChunk.ManageNotes())
{
    var length = LengthConverter.ConvertFrom(
        2 * MusicalTimeSpan.Eighth.Triplet(),
        0,
        tempoMap);
    var note = new Note(NoteName.A, 4, length);
    notesManager.Objects.Add(note);
}

midiFile.Chunks.Add(trackChunk);
midiFile.Write("Single note great song.mid");

You can even build a musical composition:

Pattern pattern = new PatternBuilder()
     
    // Insert a pause of 5 seconds
    .StepForward(new MetricTimeSpan(0, 0, 5))

    // Insert an eighth C# note of the 4th octave
    .Note(Octave.Get(4).CSharp, MusicalTimeSpan.Eighth)

    // Set default note length to triplet eighth and default octave to 5
    .SetNoteLength(MusicalTimeSpan.Eighth.Triplet())
    .SetOctave(Octave.Get(5))

    // Now we can add triplet eighth notes of the 5th octave in a simple way
    .Note(NoteName.A)
    .Note(NoteName.B)
    .Note(NoteName.GSharp)

    // Get pattern
    .Build();

MidiFile midiFile = pattern.ToFile(TempoMap.Default);

DryWetMIDI provides devices API allowing to send MIDI events to and receive them from MIDI devices. Following example shows how to send events to MIDI device and handle them as they are received by the device:

using System;
using Melanchall.DryWetMidi.Multimedia;
using Melanchall.DryWetMidi.Core;

// ...

using (var outputDevice = OutputDevice.GetByName("MIDI Device"))
{
    outputDevice.EventSent += OnEventSent;

    using (var inputDevice = InputDevice.GetByName("MIDI Device"))
    {
        inputDevice.EventReceived += OnEventReceived;
        inputDevice.StartEventsListening();

        outputDevice.SendEvent(new NoteOnEvent());
        outputDevice.SendEvent(new NoteOffEvent());
    }
}

// ...

private void OnEventReceived(object sender, MidiEventReceivedEventArgs e)
{
    var midiDevice = (MidiDevice)sender;
    Console.WriteLine($"Event received from '{midiDevice.Name}' at {DateTime.Now}: {e.Event}");
}

private void OnEventSent(object sender, MidiEventSentEventArgs e)
{
    var midiDevice = (MidiDevice)sender;
    Console.WriteLine($"Event sent to '{midiDevice.Name}' at {DateTime.Now}: {e.Event}");
}

SAST Tools

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net45 is compatible.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.5

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Melanchall.DryWetMidi:

Package Downloads
Carbon.Feature.Media

Provides various document and media processing functions.

launchpad-dot-net

An extension of iUltimateLP's Launchpad DotNet library that adds support for the Launchpad Mini Mk3 and enables SysEx support. Ported to dotnet standard by pstaszko.

BehringerXTouchExtender

Send and receive events with a Behringer X-Touch Extender DAW MIDI control surface over USB.

EZSynth.Implementations

C# synthesizer designed to be extensible and generic in terms of formats of audio and sequence data.

GitHub repositories (10)

Showing the top 5 popular GitHub repositories that depend on Melanchall.DryWetMidi:

Repository Stars
stakira/OpenUtau
Open singing synthesis platform / Open source UTAU successor
SciSharp/Keras.NET
Keras.NET is a high-level neural networks API for C# and F#, with Python Binding and capable of running on top of TensorFlow, CNTK, or Theano.
melanchall/drywetmidi
.NET library to read, write, process MIDI files and to work with MIDI devices
xunkong/KeqingNiuza
刻记牛杂店
sabihoshi/GenshinLyreMidiPlayer
Genshin Impact Windsong Lyre, Floral Zither, & Vintage Lyre MIDI auto player in Modern Mica UI. Supports MIDI instruments & Playlist controls.
Version Downloads Last updated
7.2.1-prerelease1 243 9/15/2024
7.2.0 1,635 9/5/2024
7.1.0 3,422 5/2/2024
7.0.2 6,960 12/22/2023
7.0.1 1,640 8/30/2023
7.0.0 1,247 6/26/2023
6.1.4 15,503 1/14/2023
6.1.3 3,479 10/23/2022
6.1.2 2,770 8/1/2022
6.1.1 1,051 6/8/2022
6.1.0 807 5/16/2022
6.0.1 3,062 12/21/2021
6.0.0 3,733 10/22/2021
5.2.1 26,695 6/20/2021
5.2.0 1,719 3/26/2021
5.1.2 12,879 11/21/2020
5.1.1 4,366 6/29/2020
5.1.0 2,172 3/13/2020
5.0.0 1,281 11/21/2019
4.1.1 1,214 7/31/2019
4.1.0 1,534 4/22/2019
4.0.0 1,313 1/30/2019
3.1.0 1,717 7/8/2018
3.0.0 1,581 6/15/2018
2.0.1 1,385 12/3/2017
2.0.0 1,309 11/6/2017
1.3.0 1,168 8/24/2017
1.2.0 1,105 8/1/2017
1.1.0 1,189 7/7/2017
1.0.0 1,574 5/25/2017