Search Results for

    Show / Hide Table of Contents

    Playback - Overview

    Playback class allows to play MIDI events via an IOutputDevice (see Output device article) or without a device at all (see Playback without device). To get an instance of the Playback you can use its constructors or GetPlayback extension methods in PlaybackUtilities.

    Following example shows simple console app where specified MIDI file is played until end of the file reached or B note is about to be played. So in our example B note means to stop playback.

    using System;
    using System.Linq;
    using System.Threading;
    using Melanchall.DryWetMidi.Core;
    using Melanchall.DryWetMidi.Multimedia;
    
    namespace SimplePlaybackApp
    {
        class Program
        {
            private static Playback _playback;
    
            static void Main(string[] args)
            {
                var midiFile = MidiFile.Read("The Greatest Song Ever.mid");
    
                var outputDevice = OutputDevice.GetByName("Microsoft GS Wavetable Synth");
    
                _playback = midiFile.GetPlayback(outputDevice);
                _playback.NotesPlaybackStarted += OnNotesPlaybackStarted;
                _playback.Start();
    
                SpinWait.SpinUntil(() => !_playback.IsRunning);
    
                Console.WriteLine("Playback stopped or finished.");
    
                outputDevice.Dispose();
                _playback.Dispose();
            }
    
            private static void OnNotesPlaybackStarted(object sender, NotesEventArgs e)
            {
                if (e.Notes.Any(n => n.NoteName == Melanchall.DryWetMidi.MusicTheory.NoteName.B))
                    _playback.Stop();
            }
        }
    }
    

    Please read Tick generator article and PlaybackSettings class documentation to learn how you can adjust playback's internals.

    Playback without device

    There are constructors of Playback that don't accept IOutputDevice as an argument. It can be useful, for example, for notes visualization without sound. Playback provides events that will be fired with or without output device (see Events section of the Playback API page). Also all GetPlayback extensions methods have overloads without the outputDevice parameter.

    Also if you don't specify output device and use tick generator other than HighPrecisionTickGenerator, you can use Playback in cross-platform app like Unity game that is supposed to be built for different platforms.

    Blocking playback

    If you call Play method of the Playback, the calling thread will be blocked until entire collection of MIDI events will be played. Note that execution of this method will be infinite if the Loop property set to true.

    There are also extension methods Play in PlaybackUtilities:

    using (var outputDevice = OutputDevice.GetByName("Output MIDI device"))
    {
        MidiFile.Read("Some MIDI file.mid").Play(outputDevice);
    
        // ...
    }
    

    Non-blocking playback

    Is you call Start method of the Playback, execution of the calling thread will continue immediately after the method is called. To stop playback use Stop method. Note that there is no any pausing method since it's useless. Stop leaves playback at the point where the method was called. To move to the start of the playback use MoveToStart method.

    Important

    You should be very careful with this approach and using block. Example below shows the case where part of MIDI data will not be played because of playback is disposed before the last MIDI event will be played:

    using (var outputDevice = OutputDevice.GetByName("Output MIDI device"))
    using (var playback = MidiFile.Read("Some MIDI file.mid").GetPlayback(outputDevice))
    {
        playback.Start();
    
        // ...
    }
    

    With non-blocking approach you must call Dispose manually after you've finished work with playback object.

    In This Article
    Back to top 2022 / Generated by DocFX