Click here to Skip to main content
Click here to Skip to main content

C# MIDI Toolkit

By , 18 Apr 2007
 

Screenshot - SequencerDemo.png

Contents

  1. Introduction
  2. Flow-based programming
    1. Implementing flow-based programming in C#
  3. MIDI messages
    1. Message builders
    2. MessageDispatcher class
  4. Clocks
  5. MidiEvent class
  6. Track class
  7. Sequence class
  8. MIDI devices
    1. InputDevice class
    2. OutputDeviceBase class
    3. OutputDevice class
    4. OutputStream class
  9. Sequencer Class
  10. Dependencies
  11. Conclusion
  12. History

Introduction

This is the fifth version of my .NET MIDI toolkit. I had thought that the previous version was the final one, but I have made many changes that have warranted a new version. This version takes a more traditional C#/.NET approach to flow-based programming, which I'll describe below. I wasn't comfortable with version four's implementation along these lines, so I took a step back and made changes that keep the flow-based approach while remaining within C#/.NET accepted idioms. I'm hoping that this will make the toolkit easier to use and understand.

The toolkit has seen many revisions over the past two to three years. Each revision has been an almost total rewrite of the previous one. When writing software, it is usually a bad idea to make updates that break software using previous versions. However, my goal in creating this toolkit has been to provide the best design possible. As I have grown as a programmer, I have improved my skills and understanding of software design. This has led me to revise the earlier designs of the toolkit without regard to how these revisions will break code. Not exactly the attitude one wants to adopt in a professional setting, but since the toolkit is free and since I have used it as a learning experience to improve my craft, my priorities are different.

top

Flow-based programming

Before I get into the specifics of the toolkit, I would like to talk about its architecture. With each version of the toolkit, I have struggled with how to structure the flow of messages through the system. I wanted an approach that would be versatile and allow customization. It would be nice, I thought, if users could plug their own classes into the flow of MIDI messages to do whatever they want. For example, say you wanted to write a harmonizer, a class capable of transposing notes in a specified key to create harmony parts automatically. It should be easy to simply plug the harmonizer into the toolkit without affecting other classes. In other words, the toolkit should be customizable and configurable.

Investigating this problem led me to J. Paul Morrison's excellent website on flow-based programming. He has written a book on the subject, which can be found on his website as well as at Amazon.

The idea is simple and will probably seem familiar to most: Data flows through a network of components. Each component can do something interesting with the data before passing it along to the next component. In design pattern terms, this approach is most like the Pipe and Filter pattern and is also similar to the Chain of Responsibility pattern. Please check out J. Paul Morrison's excellent book for more information.

(Just to be clear: when I say "component," I'm not necessarily talking about classes that implement the IComponent interface. I'm speaking in more general terms. A component is simply an object in a chain of objects designed to process the flow of messages.)

Below is a very basic network of components designed to handle the flow of MIDI channel messages:

Screenshot - MessageFlow.PNG

The flow of messages begins with the input device. An input device receives MIDI messages from an external source. Next, the messages flow through a user component. This component might want to do something like change the MIDI channel, transpose note messages, or change the messages in some way. Then the messages pass through the channel stopper. This component simply keeps track of all currently sounding notes. When the message flow stops, the channel stopper can turn off all sounding notes so that none of them hang. Finally, the messages reach the output device. Here they are sent to an external MIDI device.

top

Implementing flow-based programming in C#

Well, this is something I really struggled with. You can read a bit about the different ways I tried to achieve this by reading my blog. I found myself going round in circles on this. In version four of the toolkit, I settled on the idea of using a source/sink abstraction. I created an interface representing "Sources." A source represents a source of MIDI messages. "Sinks" were represented by delegates that could be connected to sources; a sink is simply a method capable of receiving a MIDI message. This worked well but it was a little confusing because the implementation looked a little "funny." That is to say, a C# programmer looking at the code for the first time might be confused as to what is going on.

I decided to do away with the sink/source infrastructure and use something more idiomatic. Sources of MIDI messages raise events when they have messages to send. Instead of implementing an interface and having Connect and Disconnect methods for hooking to sinks, they would simply have events. There are two advantages here: First, sources no longer have to implement an ISource interface, and second, .NET events are something very familiar to us. So sources of MIDI messages now look like your everyday class that just happens to have one or more events.

How about sinks, those objects that can receive MIDI messages? A sink can be anything. It's just an object that has a method that can receive a MIDI message. In version four, I had a Sink delegate for representing methods of objects capable of receiving MIDI messages. These delegates were used to connect with sources. This approach of using delegates to "connect" sources and sinks is still used in the toolkit but not as before. Instead, delegates are used as adaptors that connect to the events raised in sources and adapts the events so that objects that need to receive the messages can do so without any knowledge of the source.

Let's look at an example. Say that we're using an InputDevice to receive MIDI messages from a MIDI device, such as your soundcard. The InputDevice raises a ChannelMessageReceived event each time it receives a channel message. Suppose that we want to keep track of any note-on channel messages so that when we decide to stop receiving messages, we can turn off any currently sounding notes to keep them from "hanging." The ChannelStopper class is just for this purpose. However, the ChannelStopper has no knowledge of the InputDevice class. We need a way to hook them up so that messages generated by the InputDevice can be passed along to the ChannelStopper. Here is how we can do this with an anonymous method:

InputDevice inDevice = new InputDevice(0);
ChannelStopper stopper = new ChannelStopper();

inDevice.ChannelMessageReceived += delegate(object sender, ChannelMessageEventArgs e)
{
    stopper.Process(e.Message);
};

inDevice.StartRecording();

// ...

In this example, an anonymous method adapts events raised by the InputDevice so that they can be processed by a ChannelStopper. The InputDevice is the source of channel messages and the ChannelStopper is a sink capable of receiving and processing channel messages. The nice thing about this approach is that no explicit source/sink infrastructure is needed. Neither class knows anything about being a source or sink. The flow of messages is orchestrated by an external agent, in this case, an anonymous method.

top

MIDI messages

There are several categories of MIDI messages: Channel, System Exclusive, Meta, etc. In designing a MIDI toolkit, the challenge is to decide how to represent these messages. One approach is to create two or three general MIDI classes and have specific types of MIDI messages represented through the properties of those classes. The Java MIDI API takes this route. Another approach is to create a large collection of finely grained classes to represent all of the different types of MIDI messages. For example, there are many types of Channel messages such as the Note-on, Note-off, Program change, and Pitch Bend messages. The fine grained approach would create a class for each of those message types. My approach was to take a middle ground. I created classes for the general categories of MIDI messages but left the specific types of messages as properties within those classes. This kept the class hierarchy lightweight and manageable while providing enough specialization to make working with MIDI messages easy.

Here is the hierarchy of MIDI message classes in the MIDI toolkit:

  • IMidiMessage
    • ShortMessage
      • ChannelMessage
      • SysCommonMessage
      • SysRealtimeMessage
    • SysExMessage
    • MetaMessage

Specific types of messages are represented through properties. For example, the ChannelMessage class has a Command property that can be set to represent the various types of Channel messages.

top

Message builders

All message classes are immutable. This makes sharing messages throughout an application safe. To create messages, you pass the desired property values to their constructor. Additionally, the toolkit provides a set of builder classes for making message creation more convenient.

The toolkit provides the following message builders:

  • ChannelMessageBuilder
  • SysCommonMessageBuilder
  • KeySignatureBuilder
  • MetaTextBuilder
  • SongPositionPointerBuilder
  • TempoChangeBuilder
  • TimeSignatureBuilder

The ChannelMessageBuilder and the SysCommonBuilder also use the Flyweight design pattern. When a new message is built, it is stored in a cache. When another message is needed that has the exact same properties as a message that has already been built, the previous message is retrieved rather than creating a new one. When you consider that a typical MIDI sequence is made up of thousands of messages, many of them identical, it is easy to see how the Flyweight pattern is applicable.

Here is an example of creating a ChannelMessage object representing a note-on message:

ChannelMessageBuilder builder = new ChannelMessageBuilder();

builder.Command = ChannelCommand.NoteOn;
builder.MidiChannel = 0;
builder.Data1 = 60;
builder.Data2 = 127;
builder.Build();
Console.WriteLine(builder.Result);

After the builder has been initialized with the desired properties, the MIDI message is built with a call to the Build method. The MIDI message can then be retrieved via the Result property.

There are several builder classes for creating specific types of meta messages. For example, to create a key signature meta message, you use the KeySignatureBuilder class:

KeySignatureBuilder builder = new KeySignatureBuilder();
builder.Key = Key.CMajor;
builder.Build();
Console.WriteLine(builder.Result);

top

MessageDispatcher class

Often there is a need to process a collection of IMidiMessages. How each message is processed depends on its type. The problem is that you cannot tell an IMidiMessage's type without an explicit check. The IMidiMessage provides a MessageType property just for this purpose. However, having to repeatedly check message types throughout your code can be cumbersome.

The MessageDispatch class is designed to automate these checks. This class acts as a source for every type of MIDI message. It raises an event each time it dispatches a message. The type of event is determined by the type of message it is dispatching.

top

Clocks

MIDI playback is driven by ticks that occur periodically. The source of these ticks are MIDI clocks. MIDI clocks come in all shapes and sizes. For example, playback can be driven by an internal or external clock. Also, the way in which the ticks are generated depends on whether the MIDI sequence has pulses per quarter note resolution or SMPTE resolution. For the vast majority of situations, an internal clock generating ticks with pulses per quarter note resolution is all you need.

The IClock interface represents the basic functionality for all MIDI clocks:

public interface IClock
{
    event EventHandler Tick;
    event EventHandler Started;
    event EventHandler Continued;
    event EventHandler Stopped;
    bool IsRunning
    {
        get;
    }
}

The Tick event occurs when a MIDI tick has elapsed. The Started, Continued, and Stopped events are self-explanatory. However, it should be pointed out that when the Started event occurs, sequence playback starts from the beginning of the sequence. When the Continued event occurs, playback starts from the current position. The IsRunning property indicates whether the clock is running.

You may notice that there are no methods in the interface for starting and stopping a clock. That is because with clocks that are driven by an external source, the source is responsible for starting and stopping the clock. The clocks receive messages via MIDI and based on those messages starts or stops generating ticks. Since all MIDI clocks implement IClock, it only represents the functionality common to all the clocks.

At this time, the toolkit provides only one clock class, the MidiInternalClock. This clock generates MIDI ticks internally using pulses per quarter note resolution. For the majority of situations, this clock will work fine.

The MidiInternalClock has a Tempo property for setting the tempo in microseconds per beat. To set the tempo to 120 bpm, for example, you would set the Tempo property to 500000. It can receive meta tempo change messages. When a meta tempo change message is passed to it, it changes its tempo to match the tempo represented by the message.

top

MidiEvent class

A MIDI file is made up of several tracks. Each track contains one or more timestamped MIDI messages. The timestamp represents the number of ticks since the last message was played. This timestamp is called delta ticks. The MidiEvent class represents a timestamped MIDI message. It has three public properties:

  • DeltaTicks
  • AbsoluteTicks
  • MidiMessage

The DeltaTicks property represents the number of ticks since the last MidiEvent. In other words, this value represents how long to wait after playing the previous MidiEvent before playing the current MidiEvent. For example, if the DeltaTicks value is 10, we would allow 10 ticks to elapse before playing the MIDI message represented by the current MidiEvent.

The AbsoluteTicks represents the overall position of the MidiEvent. This is the total number of ticks that have elapsed until the current MidiEvent.

The MidiMessage property is the IMidiMessage represented by the MidiEvent.

In addition there are two internal properties, one which points to the previous MidiEvent in the track, and one which points to the next MidiEvent in the track. In other words, the MidiEvent class acts as a node in a doubly linked list of MidiEvents.

top

Track class

The Track class represents a collection of MidiEvents. It is responsible for maintaining a collection of MidiEvents in proper order. MidiEvents are not directly added to a Track. Instead, you add an IMidiMessage, specifying its absolute position in the Track. The Track then creates a MidiEvent to represent the message and inserts it into its collection of MidiEvents.

In addition to providing functionality for adding and removing MIDI events, the Track class also provides several iterators. There is a standard iterator that simply iterates over the MidiEvents one at a time. Another iterator takes a MessageDispatcher object and passes each IMidiMessage to the dispatcher which in turn raises an event specific to the type of message it is dispatching. The value the iterator returns is the absolute ticks for the current MidiEvent.

Perhaps the most useful iterator is the one that when advanced moves forward only one tick at a time. The iterator keeps track of its tick position in the Track. When the tick count has reached a value in which it is time to play the next MidiEvent, it passes the IMidiMessage represented by the MidiEvent to the MessageDispatcher and returns the absolute tick count. This iterator also takes a ChannelChaser object as well as a start position value and "chases" up to the start position before switching to the playback mode. In essence, this iterator allows us to stream the Track in real-time.

top

Sequence class

The Sequence class represents a collection of Tracks. It also provides functionality for loading and saving MIDI files, so Sequences can load and save themselves.

Every Sequence has a division value. This value represents the resolution of the Sequence and is represented by a property. There are two types of division values: Pulses per quarter note and SMPTE. The Sequence has a SequenceType property indicating the sequence type. Unfortunately, SMPTE sequences aren't supported at this time.

top

MIDI devices

There are several MIDI device classes in the toolkit. Each device class is derived directly or indirectly from the abstract Device class in the Sanford.Multimedia namespace. The InputDevice class represents a MIDI device capable of receiving MIDI messages from an external source, such as a MIDI keyboard controller or synthesizer. The OutputDeviceBase class is an abstract class that serves as the base class for the output device classes. The OutputDevice class represents a MIDI device capable of sending MIDI messages to an external source or your soundcard. And the OutputStream class encapsulates the Windows Multimedia MIDI output stream API. It is capable of playing back timestamped MIDI messages.

There can be more than one of these devices present on your computer. To determine the number of input devices present, for example, you would query the InputDevice's static DeviceCount property. The output device classes also have this property.

Each MIDI device has its own unique ID. This is simply an integer value representing the device's order in the list of devices available. For example, the first output device on your system would have an ID of 0. The second output device would have an ID of 1, and so on. The same is true for the input devices. When you create a MIDI device, you pass it the ID of the device you wish to use to its constructor. If there was an error in opening the device, an exception is thrown.

To find out the capabilities of a device, you query the class' static GetDeviceCapabilities method, passing it the device ID of the device you are interested in. This method will return a structure filled with values representing the capabilities of the specified MIDI device.

Let's describe each device class in detail:

top

InputDevice class

The InputDevice class represents a MIDI device capable of receiving MIDI messages. It has an event for each of the major MIDI message it can receive. To receive MIDI messages, you connect to one or more of these events. Then you call the StartRecording method. Recording will continue until either StopRecording or Reset is called. The InputDevice lets you set the size of the sysex buffer it uses to receive sysex messages. When the InputDevice has received a complete sysex message, it raises the SysExReceived event.

top

OutputDeviceBase class

The OutputDeviceBase class is an abstract class that provides basic functionality for sending MIDI messages. It has several overloaded Send methods for sending various types of MIDI messages.

top

OutputDevice class

The OutputDevice class represents a MIDI device capable of sending MIDI messages. It inherits most of its functionality from the OutputDeviceBase class. It also provides running status functionality.

The following code creates an OutputDevice, builds and sends a note-on message, sleeps for one second, and then builds and sends a note-off message:

using(OutputDevice outDevice = new OutputDevice(0))
{
    ChannelMessageBuilder builder = new ChannelMessageBuilder();

    builder.Command = ChannelCommand.NoteOn;
    builder.MidiChannel = 0;
    builder.Data1 = 60;
    builder.Data2 = 127;
    builder.Build();

    outDevice.Send(builder.Result);

    Thread.Sleep(1000);

    builder.Command = ChannelCommand.NoteOff;
    builder.Data2 = 0;
    builder.Build();

    outDevice.Send(builder.Result);
}

top

OutputStream class

The OutputStream class is also derived from the OutputDeviceBase class. It encapsulates the Windows multimedia MIDI output stream API. It provides functionality for playing back MIDI messages.

To play MIDI messages, you call StartPlaying. The OutputStream will then begin playing back any MIDI messages in its queue. To place MIDI messages in the queue, you first write one or more MidiEvents using the Write method. After writing the desired number of MidiEvents, you call Flush. This flushes the events to the stream causing it to play them back.

top

Sequencer Class

The Sequencer class is back. It's a lightweight class for playing back Sequences. I felt the previous MidiFilePlayer class was not the best means for playing back MIDI sequences. I wanted to give the toolkit the ability to play Sequences your create programmatically. One issue that caused me to shy away from a Sequencer class (after having created one in earlier versions) is the problem of a Sequence changing as it's being played by a Sequencer. I still haven't solved that problem, but I didn't want that issue to prevent easy Sequence playback. So I'm putting in a new version of the Sequencer class with the understanding that it's meant to be used for simple playback. For something more sophisticated, you can use it as the basis for creating something more.

top

Dependencies

The MIDI toolkit depends on the DelegateQueue class from my Sanford.Threading namespace; the InputDevice and OutputDevice classes use it for queueing MIDI events. In turn, the Sanford.Threading namespace depends on my Sanford.Collection namespace, so that assembly is also necessary for the toolkit to compile. Finally, the toolkit uses the Sanford.Multimedia namespace. I've provided all of the assemblies with the download. I've linked the projects that use them to the assemblies in hopes that the toolkit will compile out of the box. Hopefully, the days of having trouble compiling my projects because of not having the right assemblies are over.

top

Conclusion

This article has provided an overview of my .NET MIDI toolkit. My hope is that it will be a useful and powerful tool for writing MIDI applications. It has been a lot of fun to write. Each version has represented the very best of my skill and knowledge as a programmer. I welcome feedback and any bug reports you may have. Take care and thanks for your time.

top

History

  • 20th Feb, 2004
    • Article submitted.
  • 07th May, 2004
    • Second major version.
  • 27th Oct, 2004
    • Third major version.
  • 08th March, 2006
    • Fourth major version.
  • 14th March, 2006
    • Cleaned up the article a bit.
    • Consolidated the sources into one generic interface in the Multimedia namespace.
    • Consolidated all of the sinks into one generic delegate also in the Multimedia namespace.
    • Fixed a bug in the MIDI File Player demo as well as a bug in the Sequence class.
  • 14th April, 2007
    • Fifth major version.

top

License

This article, along with any associated source code and files, is licensed under The MIT License

About the Author

Leslie Sanford
United States United States
Member
Aside from dabbling in BASIC on his old Atari 1040ST years ago, Leslie's programming experience didn't really begin until he discovered the Internet in the late 90s. There he found a treasure trove of information about two of his favorite interests: MIDI and sound synthesis.
 
After spending a good deal of time calculating formulas he found on the Internet for creating new sounds by hand, he decided that an easier way would be to program the computer to do the work for him. This led him to learn C. He discovered that beyond using programming as a tool for synthesizing sound, he loved programming in and of itself.
 
Eventually he taught himself C++ and C#, and along the way he immersed himself in the ideas of object oriented programming. Like many of us, he gotten bitten by the design patterns bug and a copy of GOF is never far from his hands.
 
Now his primary interest is in creating a complete MIDI toolkit using the C# language. He hopes to create something that will become an indispensable tool for those wanting to write MIDI applications for the .NET framework.
 
Besides programming, his other interests are photography and playing his Les Paul guitars.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerRe: What about changing to another instrument, like fx. organ?memberMember 774238922 Mar '11 - 5:35 
All I know is, that it's done with a MetaMessage where you can set InstrumentName. This MetaMessage can't be sent via MIDI but must be read from a MIDI file.
But how can I do this with this toolkit?
Hope someone can help Smile | :)
GeneralRe: What about changing to another instrument, like fx. organ?member10chiken28 Mar '11 - 17:35 
Use Command = ChannelCommand.ProgramChange, and as data1 — index of instrument. Works for me, at least.
GeneralCallbackOnCollectedDelegate was detectedmemberSebKister18 Nov '10 - 17:01 
Hi,
 
I get a "CallbackOnCollectedDelegate was detected" from the MDA in my app. The error occurs just after calling outDevice.Dispose() and I can't figure out why. I compiled the SequencerDemo and it s working without any problem in my environnement ( VS2010, Windows 7 x64).
In both cases, my app and the demo app, VS code analysis gives me :
 
Warning 3 CA2213 : Microsoft.Usage : 'Form1' contains field 'Form1.outDevice' that is of IDisposable type: 'OutputDevice'. Change the Dispose method on 'Form1' to call Dispose or Close on this field. C:\Users\Sebastien\Documents\Visual Studio 2010\Projects\Scala\Scala\Form1.Designer.cs 18 Scala
 
But doing that does not solve the problem ...
 
Anyone has an idea or had the same problem ?
 
Thanks for help.
 
Sebastien
GeneralRe: CallbackOnCollectedDelegate was detectedmemberRogueTrooper18 Feb '11 - 14:52 
Yes. I have a similar problem, although I didn't call the Dispose() method, nor do I want to as I need to keep the OutputDevice available. I know is it's got something to do with unmanaged code which I don't have a clue about. I've found a solution on MSDN which is to use a static variable for the callback method which will keep it alive. Unfortunately, the problem lies within Leslie's code which I don't have access to. I'm hoping he'll update it so this problem won't occur.
GeneralRe: CallbackOnCollectedDelegate was detectedmemberMarek Ledvina4 Apr '11 - 18:49 
Hi guys,
 
Have you found a solution for these?
 
Thanks, Marek.
GeneralSending Midi timecode to output device [modified]memberinternetwjm17 Oct '10 - 8:53 
Hi,
 
I'm trying to send MIDI timecode to an external device. I'm trying to set a constructor for a systemrealtimemessage but VS says: Sysrealtimemessage does not contain a constructor with 1 argument:
 Midiclock.Start();
                                SysRealtimeMessage tickMsg = new SysRealtimeMessage(SysRealtimeType.Tick);
                                
                                Midiout.Send(tickMsg);
 
The Midiclock is an instance of MidiInternalClock.
 
Any help? I want to keep sending the current time (ticks or clock?) to a device, either in MIDI Timecode or SMPTE format. I found other posts on this subject but they remained unanswered.

modified on Sunday, October 17, 2010 7:29 PM

GeneralRe: Sending Midi timecode to output device [modified]memberdoctorwho60113 Oct '11 - 6:21 
I will first state that I didn't research this closely. But the problem is most likely that the argument provided declaration is of the wrong type. SysRealType.Tick is not the expected element for the contructor. It looks like:
private SysRealtimeMessageEventArgs(SysRealtimeMessage message)
wants a SysRealTimeMessage object and not a SysRealtimeType.
GeneralSaving sequence to MIDI file [modified]memberarusslabs16 Oct '10 - 6:52 
hi,
 
is it possible to store instrument data in a midi file? i am trying to create a midi file with from a sequnce with random tones, using 5 different channels with different instruments but whet i save it to midi file i get allways piano sound (instrument id: 0)
 
has somebody a clue for me to solve this problem?
 
here is the code its playing the propper thing and saving a wrong one
public void MakeFoo()
{
int position;
Sequence sequence = new Sequence();
ChannelMessageBuilder builder = new ChannelMessageBuilder() { Command = ChannelCommand.ProgramChange };
Track track = new Track(); // this.CreateTrack();
sequence.Add(track);
 
for (int i = 0; i < 5; i++)
{
builder.MidiChannel = i;
builder.Data1 = (int)Random.Next(0, 127);
builder.Build();
this._outDevice.Send(builder.Result);
 
position = 0;
 
for (int j = 0; j < 20; j++)
{
int noteId = Random.Next(0, 127);
track.Insert(position, new ChannelMessage(ChannelCommand.NoteOn, i, noteId, Random.Next(80, 120)));
position += Random.Next(15, 24);
track.Insert(position, new ChannelMessage(ChannelCommand.NoteOff, i, noteId, 0));
position += Random.Next(0, 10);
}
}
 
Sequencer sequencer = new Sequencer() { Sequence = sequence };
sequencer.ChannelMessagePlayed += new EventHandler<ChannelMessageEventArgs>(Sequencer_ChannelMessagePlayed);
 
sequence.Save("foo.mid");
sequencer.Start();
 
}


modified on Saturday, October 16, 2010 2:17 PM

GeneralRe: Saving sequence to MIDI filememberarusslabs16 Oct '10 - 22:52 
Hey Smile | :) I solved this problem
 
I forgot to add a ProgrammChange message to the track, instead of sending it directly to device I add it now and it works
 
track.Insert(0, builder.Result);
QuestionUsing USB-to-MIDI as output device?memberkroepoeksklok5 Oct '10 - 0:09 
Hi!
I have an electronic drum kit which has a MIDI IN. Using some proprietary software I can program a drum track and in that software I can use my USB-to-MIDI cable to send MIDI notes to the device. It plays exactly what I specify so all works as it should, but programming the drum tracks is very tedious, especially when you already have all the data stored in some other (custom) format. I can use that format to deduce the required MIDI notes, so that's no biggee.
 
However, is it possible to use the .NET MIDI toolkit's output functionality to send MIDI signals to the USB-to-MIDI device or would I have to write some of my own code to set this up?
 
Thanks for you help! Feel free to ask for any clarification you may need.
AnswerRe: Using USB-to-MIDI as output device?memberinternetwjm17 Oct '10 - 13:36 
Hi,
 
You can just sum up all the output devices on your computer to which you send midi:
 
 if(OutputDevice.DeviceCount != 0)
            {
                deviceOut = OutputDevice.DeviceCount;
                Midiout = new OutputDevice(0);
                int i = 0;
                do
                {
                    Moutbox.Items.Add(Sanford.Multimedia.Midi.OutputDevice.GetDeviceCapabilities(i).name.ToString());
                    i++;
                }
                while (i != Sanford.Multimedia.Midi.OutputDevice.DeviceCount);
            }
 
Here I add all the devices to a combobox called Moutbox. Then write some code to set the selected item as your midi out device. If your usb-midi device is connected properly you can select it from that list:
 private void moutchange(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (Moutbox.SelectedIndex != -1 && Minbox.SelectedIndex <= Sanford.Multimedia.Midi.OutputDevice.DeviceCount - 1)
            {
                Midiout.Dispose();
                Midiout = new OutputDevice(Moutbox.SelectedIndex);
            }
 
Be sure to write some code in case the connection is lost (by pulling out the cable for example). I constantly check if the devicecount I had has not become smaller and when that happens I reset all the midi devices and let the user reconfigure:
  if (deviceIn > Sanford.Multimedia.Midi.InputDevice.DeviceCount || deviceOut > Sanford.Multimedia.Midi.OutputDevice.DeviceCount) {
                    Refreshdevices(null, null);
                }
The code above I use in a dispatchertimer so it constantly runs this. Then it actives Refreshdevices:
        private void Refreshdevices(object sender, System.Windows.RoutedEventArgs e)
        {
            Midiout.Dispose();
            Midiin.Dispose();
            Moutbox.Items.Clear();
            Minbox.Items.Clear();
            if (OutputDevice.DeviceCount != 0)
            {
                Midiout = new OutputDevice(0);
                int i = 0;
                do
                {
                    Moutbox.Items.Add(Sanford.Multimedia.Midi.OutputDevice.GetDeviceCapabilities(i).name.ToString());
                    i++;
                }
                while (i != Sanford.Multimedia.Midi.OutputDevice.DeviceCount);
                deviceOut = Sanford.Multimedia.Midi.OutputDevice.DeviceCount;
            }
 
            if (Sanford.Multimedia.Midi.InputDevice.DeviceCount != 0)
            {
                Midiin = new Sanford.Multimedia.Midi.InputDevice(0);
                Midiin.ChannelMessageReceived += input_ChannelMessageReceived;
                Midiin.StartRecording();
                int i = 0;
                do
                {
                    Minbox.Items.Add(Sanford.Multimedia.Midi.InputDevice.GetDeviceCapabilities(i).name.ToString());
                    i++;
                }
                while (i != Sanford.Multimedia.Midi.InputDevice.DeviceCount);
                deviceIn = Sanford.Multimedia.Midi.InputDevice.DeviceCount;
            }
        }
 
This disposes both in and out devices, refills the comboboxes and it only happens if a device is disconnected.
 
Good luck
GeneralRe: Using USB-to-MIDI as output device?memberkroepoeksklok31 Jan '11 - 2:17 
Hi!
 
My apologies for my late reply. I have email notification turned on, but it never arrived for some obscure reason and I forgot all about this since it's only a hobby project. Only recently did I start to pick this up again.
 
Your answer is very thorough, thank you very much for taking the time to write it out. It should easily get me started. Funny that it simply sees it as a MIDI device and that it doesn't care if it's USB. I was afraid I was going to have to mess around with USB libraries or some kernel writing, but it seems that this isn't the case.
QuestionRe: Using USB-to-MIDI as output device?memberkroepoeksklok31 Jan '11 - 9:02 
Hi!
 
So far, no luck. The Midi library recognizes the device, though. Here's what I'm trying:
 
                List<String> devices = new List<string>();
                int i = 0;
                do {
                    devices.Add(Sanford.Multimedia.Midi.OutputDevice.GetDeviceCapabilities(i).name.ToString());
                    i++;
                }
                while( i != Sanford.Multimedia.Midi.OutputDevice.DeviceCount );
 
                Console.WriteLine("Detected MIDI devices");
                int k = 0;
                foreach( String s in devices ) {
                    Console.WriteLine(k + ": " + s);
                    k++;
                }
 
Works like a charm and produces the following list:
Detected MIDI devices
0: Microsoft GS Wavetable Synth
1: USB2.0-MIDI
2: MIDIOUT2 (USB2.0-MIDI)
 
I'm not sure if I need #1 or #2 for this to work, but regardless of which one I pick, nothing is happening when I play a Midi note, using the following snippet:
 
                using( OutputDevice input = new OutputDevice(1) ) {
                    using(OutputDevice outDevice = new OutputDevice(2)) {
                        ChannelMessageBuilder builder = new ChannelMessageBuilder();
                        builder.Command = ChannelCommand.NoteOn;
                        builder.MidiChannel = 10;
                        builder.Data1 = 45; //Triggers a confirmation event
                        builder.Data2 = 127;
                        builder.Build();
 
                        outDevice.Send(builder.Result);
                        input.Send(builder.Result);
                        Thread.Sleep(500);
 
                        builder.Command = ChannelCommand.NoteOff;
                        builder.Data2 = 0;
                        builder.Build();
 
                        outDevice.Send(builder.Result);
                        input.Send(builder.Result);
                    }
                }
 
I know from Sonar that the device works, so I'm a bit baffled as to why it won't work from this library. I've also tried swapping the MIDI connectors around: the USB-to-MIDI has two plugs, IN and OUT and so has the device I'm trying to send to, so I tried all four combinations: IN in IN, IN in OUT, OUT in IN, OUT in OUT and every single time I was playing MIDI note number 21 to 108 set to Data1 and Data2 set to 127, but didn't see anything happen. I'm going on the assumption that Data1 resembles the Midi number and that Data2 resembles something like velocity and that in order to send a simple MIDI note, I must use the ChannelMessageBuilder. Maybe I'm wrong, though, or maybe I'm missing something simple.
 
For info, here are the capabilities of the three devices:
 
Channel mask:-1
Driver version: 256
Mid: 1
Name: Microsoft GS Wavetable Synth
Pid: 27
Support: 1
Technology: 7
Voices: 32
 
Channel mask:-1
Driver version: 596
Mid: -1
Name: USB2.0-MIDI
Pid: -1
Support: 0
Technology: 1
Voices: 0
 
Channel mask:-1
Driver version: 596
Mid: -1
Name: MIDIOUT2 (USB2.0-MIDI)
Pid: -1
Support: 0
Technology: 1
Voices: 0
 
I don't have the foggiest as to what I'm doing wrong or if my device simply is faulty or incapable of playing through this library. Either way, I'm pretty sure that I can get the rest going if I know how to send at least one note.
Any help is much appreciated!
AnswerRe: Using USB-to-MIDI as output device?memberkroepoeksklok1 Feb '11 - 8:39 
Nevermind! I didn't know that the channels were 0-based. Setting 10 to 9 fixed it.
Generalyour inputDevice ID is out of range of local Systemmember小piao122 Aug '10 - 16:46 
Dear Leslie:
thanks for your toolkit,it's really great!
But now i have met a problem.i want to use the InputDevice Class to record my sound and hope make my sound become a midi file.but when i use this inputDevice Class,it is said they can't find a true device.the "true device" i meant is a device like when i use the OutputDevice,there is a "Microsoft GS wavetable synth" device which can be used for playback midi sound.is my thought wrong?but how can i solve this problem that record my sound to make a midi file?Please forgive for my poor English~~thanks~
GeneralRe: your inputDevice ID is out of range of local Systemmemberinternetwjm17 Oct '10 - 13:41 
Hi,
 
I think you need to check whether you have a recording device (meaning a device capable of interpreting MIDI, by default most pc's don't have one...). Perhaps you can consider looking at USB-MIDI cables, these cables have an in and out connection.
 
If you do have a MIDI In capable device you need to select it:
 
 if(Sanford.Multimedia.Midi.InputDevice.DeviceCount != 0)
            {
                deviceIn = Sanford.Multimedia.Midi.InputDevice.DeviceCount;
                Midiin = new Sanford.Multimedia.Midi.InputDevice(0);
                Midiin.ChannelMessageReceived += input_ChannelMessageReceived;
                Midiin.StartRecording();
                int i = 0;
                do
                {
                    Minbox.Items.Add(Sanford.Multimedia.Midi.InputDevice.GetDeviceCapabilities(i).name.ToString());
                    i++;
                }
                while (i != Sanford.Multimedia.Midi.InputDevice.DeviceCount);
            }
 
This code fills a combobox called Minbox with all your MIDI In capable devices and automatically sets your first one as active. If this code is not run (set a breakpoint and try) then you don't have a device.
 
Good luck
GeneralRe: your inputDevice ID is out of range of local Systemmember小piao118 Oct '10 - 22:27 
thank you for your detail answer~~
Questioncan I program a game like "vos" in XNA with your toolkit?memberdzrjojo22 Aug '10 - 1:56 
Have you ever heard of "vos" game?
I like it.
AnswerRe: can I program a game like "vos" in XNA with your toolkit?memberasmartin30 Aug '10 - 10:47 
There is nearly infinite potential for integrating this toolkit into other C# applications, such as games. It is possible to link the Sanford.Multimedia.Midi libraries to XNA Game Studio 3.0 . Creating the methods you need to make a DJ type of game might be a little more complicated.
GeneralNeed help creating a new clock...memberMember 44691153 Aug '10 - 4:53 
In my project, I'm using MIDI as control track and wav or mp3 for audio. Long story short, I want to use MIDI to sync lights and stage effects to the audio track.
 
If I understand this awesome toolkit correctly, I need to create a clock that plays the audio and uses the time code from the audio file as the clock for the midi.
 
So question one is : Am I thinking about this correctly? With my goal in mind, is there a better implementation?
 
Question two: Provided I've got the right idea, Can anyone give any advice on how I could go about writing a new clock. I can play wav audio just fine. But I get kinda cross-eyed when trying to take its position and convert it into a meaningful number for the toolkit.
 
Thanks in advance for any pointers or advice!
GeneralRe: Need help creating a new clock...memberinternetwjm17 Oct '10 - 13:51 
Hi,
 
I think I understand what you want to do, here are some pointers:
 
1. You need to write some code of your own to play your audio track
2. You can then either: convert the current position (milliseconds) to ticks and set those to your external device (lighting console)
3. or Start a clock which runs along with your audio and syncs the clock on your lighting desk (more likely)
 
The documentation in the toolkit on syncing clocks is very vague (asking how to sync clocks here myself).
 
However, sending timecode to a lighting console is not enough. The timecode only tells the console what time it is. The console has to do something with this information. For example on a RoadHog console you can place light cues on a track, for example at 00:00:35 you place Cue 1. Then when you start a clock, the clock reaches 00:00:35, the console will start Cue 1. What this means is that you need to have a console with these kinds of capabilities.
 
The other way you could do this is make a list of MSC (Midi show control) cues in a program like Q-Lab. This works across many more lighting consoles. This is simply a matter of sending a GO command to the lighting console. The MIDI Toolkit allows you to send these commands using the sysexmessagebuilder. Here is an example to send a GO cue for cue list 1 cue 1:
 
 byte commandobyte = 0x01;
                                    if (qcommand == "STOP") { commandbyte = 0x02; }
                                    else if (qcommand == "RESUME") { commandbyte = 0x03; }
                                    else if (qcommand == "LOAD") { commandbyte = 0x05; }
                                    else if (qcommand == "FIRE") { commandbyte = 0x07; }
                                  
                                    byte[] data =         
                                        {(byte)0xF0, //  SysEx
                                         (byte)0x7F, //  Realtime
                                         (byte)0x7F, //  Device id
                                         (byte)0x02, //  Constant
                                         (byte)0x01, //  Lighting format 
                                         (commandbyte), //  GO         
                                         (byte)0x31, //  qnumber     
                                         (byte)0x00, //  space
                                         (byte)0x31, //  qlist 
                                         (byte)0x00, //  space
                                         (byte)0xF7, //  End of SysEx        
                                        };
                                   
                                    SysExMessage message = new SysExMessage(data);
                                    Midiout.Send(message);
 
Hope this helps,
General.NET Micro Framework 4memberCharlie_vZ13 Jul '10 - 9:54 
Hello,
 
Has anyone had any success adapting the toolkit to run on the .NET Micro Framework 4? As I understand it (correct me if I'm wrong) the C# Midi Toolkit requires the winmm.dll library which is not present on the Micro Framework (I don't think). How hard would it be to adapt it to send and receive midi bytes across serial ports? What does the winmm.dll actually do?
 
Thanks for your feedback.
 
Charlie
GeneralNeed PitchWheel sample [modified]memberPaul Shaffer1 Apr '10 - 9:28 
I am converting c++ project that uses another midi library. It has a working pitch wheel feature.
 
I am unable to get the ChannelCommand.PitchWheel command to work. Does anyone have an example of a working pitch wheel with this toolkit? What I need is: which ChannelMessage ctor do I use? The one with 2 data args or 1 data arg? What do the args represent, and what is the valid numerical range for the pitch wheel args? Etc.
 
Most of the commands and features of this toolkit have to be reverse engineered to be used. Would be nice if there was a little more documentation on how the calls work, command arguments and ranges. Are there any docs I have overlooked?
modified on Thursday, April 1, 2010 3:35 PM

GeneralRe: Need PitchWheel samplememberPaul Shaffer1 Apr '10 - 10:15 
The borg.com docs are gone. What is your favorite replacement site for docs?
I found an earlier thread on this here. The default pitch bend range appears to be +/- 8192 with a center at 8192.
I was getting argument exception on data2 so I put this in.
if(pitchBend > 16383)
pitchBend = 16383;
 

int pitchBend = 8192; // Pitch wheel center.
int mask = 127;

ChannelMessageBuilder builder = new ChannelMessageBuilder();

// Build pitch bend message;
builder.Command = ChannelCommand.PitchWheel;

// Unpack pitch bend value into two data bytes.
builder.Data1 = pitchBend & mask;
builder.Data2 = pitchBend >> 7;

// Build message.
builder.Build();

ChannelMessage pitchBendMessage = builder.Result;

// Send message (assumes we've created an output device).
outDevice.Send(pitchBendMessage);

GeneralProblems on win7-64memberPaul Shaffer17 Mar '10 - 7:27 
Are you able to run this in Win7-64? The app comes up with no midi input devices found. Why does it need an input device? I just want to click on the piano keys and use midi output. The app makes no sound, and will not close. I have to run process explorer to kill it.
 
Where exactly is the midi setup for wavetable synth, etc. in Windows 7? It doesn't have a UI as in XP, and appears to be hidden. I would like to be able to enumerate the general midi patches from the sound system, not from the patch list in this project. This is going to take a while.
GeneralRe: Problems on win7-64membersimonjohnroberts197423 Mar '10 - 12:46 
Um yeah.
 
Degug the Sequencer demo not the Midi Watcher.
 
Set the SequencerDemo as your starup project.
GeneralRe: Problems on win7-64memberPaul Shaffer25 Mar '10 - 10:13 
Funny, I downloaded it again, rebuilt and it runs okay.
QuestionAn efficient way to solo & mute track from midi filememberchick7403026 Mar '10 - 23:59 
hello Leslie !~ thanks for the cool toolkit!
 
i have two questions that i cannot figure out.
 
(1)
 
now i can use sequence.remove(sequence[index]) to remove track from midi file
 
it seems an inefficient idea to doing solo & mute, is there any efficient way to do that?
 
(2)
 
how can i get midi's instrument names from the midi file that i'm playing?
 
now i can just get how many tracks in my midi file but dont know what they name.
 
i have search for the Q&A but cannot found a solution~
 
thanks for reply^^
AnswerRe: An efficient way to solo & mute track from midi filemember10chiken28 Mar '11 - 17:41 
For panic switch you may use standard 0x78 (120) command, sending it in pack ChannelCommand.Controller message.
public void Panic(){
            for (int i = 0; i < 16; i++)
            {
                //Sending all-notes-off command to channel.
                m_outDevice.Send(new ChannelMessage(ChannelCommand.Controller, i, 120, 0));
            }
        }
Technically it tells every channel to turn notes off. So you may modify it to silence all but one channel or silence specified channel, if you deem necessary.
GeneralI need example to find note secondsmemberMember 246139012 Feb '10 - 22:55 
I need example to find note seconds for karaoke lyric
 
How can I find, I see some equation but don't understand - -" please help...
 
My english is too bad, sorry, Thanks Smile | :)
GeneralProblems with Asynch midi messages into SystemExclusive midi messagesmemberbellaz5 Feb '10 - 4:21 
Hello!
 
I have problems to parse and dispatch Asynch midi messages (midiClock and ActiveSensing) that arrives into SystemExclusive midi messages management realized by dispatcher class.
 
When my external sequencer (Viscount RD70) puts into channel 0xF8 (midiclock) and 0xFE (ActiveSenting) continually seems to lost the first bytes of SystemExclusive message managed at
that moment.
 
From the original SystemExclusive midi message it seems to keep just the byte 0xF7 (The SystemExclusive byte closure or a little more).
 
It's a buffer dimension problem or it's a SystemExclusive message management problem's with Asynch midi messages storm ? or something else?
 
thanks in advance!
 
Best Regards
GeneralWhere do I beginmembergideonrv30 Jan '10 - 11:26 
I'm a WPF/C# programmer, not a musician. My last attempt to play music was about 45 years ago, when my fingers refused to form the F chord on the guitar.
 
Now things have changed a little, so I bought a MIDI keyboard, and the best way for a programmer to learn music is to write something like an automatic harmonizer (the arranger will come next, if I live long enough…).
 
The Sanford's C# MIDI Toolkit seems to be a good start. However, I need a beginners guide, a means to understand how I capture messages from the keyboard (or from a MIDI file), how I send them to the soundcard (or to a MIDI file), and how I add chords of my own, in the right timing.
 
I read the article a few times, but didn't understand it. I even tried to learn the code with the help of the debugger, but the real time clock failed me.
 
I ask for help. A link, or even a clue, would be fine.
 
Thank you all.
GeneralRe: Where do I beginmemberLeslie Sanford30 Jan '10 - 11:48 
This website has a ton of information about MIDI:
 
MIDI Technical Fanatic's Brainwashing Center[^]
 
Take a look at the Technical Docs and Programming section, in particular.
GeneralOutputDevice sporadically throwws exception because midiOutLongMsg returned MMSYSERR_INVALPARAMmemberGoogleMaster20 Jan '10 - 0:53 
Hi,
 
I'm having a slight stability problem with OutputDevice.Send(SysExMessage). Most of the time it works fine in my actual application but very sporadically it will throw an exception because midiOutLongMsg returned MMSYSERR_INVALPARAM for no apparent reason. The next call to it with the same SysEx message (although a new object) will be fine.
 
Because it occurs so infrequently I decided to do a little stress testing with some code like this:
 
for(int bugtest = 0; bugtest < 5000; bugtest++)
   {
   scanoutputDevice.Send(new SysExMessage(new byte[] { 0xF0, 0x7E, 6, 66, 6, 0xF7 }));
   }
 
As it turns out this will consistenly reproduce the problem on my system. Depending on the size of the SysEx message the call to midiOutLongMsg in Send(SysExMessage) will return MMSYSERR_INVALPARAM every x iterations. It appears to happen more often with shorter SysEx messages. If you call System.Threading.Thread.Sleep(10); after every loop iteration it also seems to fix the problem but obviously I don't want to insert Sleep statements after every call to Send.
 
I'm guessing that the problem is that perhaps some internal buffer of the MIDI output device driver is getting full somehow. Too bad it doesn't return a more clear error code to indicate this.
 
My question is: How can I prevent this or how can I best recover from this, keeping in mind that I must send the SysEx message that failed asap. I'd also like to know exactly what is causing this problem in the first place.
 
BTW The MIDI interface is a Roland UM2-EX with the latest drivers on Windows XP SP2. It happens both in Debug and Release builds.
 
Thanks,
Arjan
GeneralSequencer Demo : midi notes sometimes stuck loading new midi filesmembermrpulsar12 Jan '10 - 7:25 
Hi,
 
Trying the SequencerDemo example in the Midi Toolkit ...
 
It's not stable when load repeatedly new midifiles. Infact, closing the dialogbox for choosing new midifile , often the sequencer freeze notes. Seems not receiving the noteoff command.
 
In this way the Toolkit it's not so much usable in professional live apps.
Someone can try this ? Any ideas or fix ?
 
I'm building the project with visual c# express 2008.
 
Thanks in advance.
 
Luca
GeneralRe: Sequencer Demo : midi notes sometimes stuck loading new midi filesmemberandynormancx19 Jan '10 - 7:12 
Well the toolkit certainly is capable of very professional results.
 
One obvious question springs to mind. Is this happening in a compiled app or in an app running under debug in Visual Studio ? MIDI is effectively a realtime situation and you definitely can see poor performance of the toolkit when it is being slowed down by the debug processes involved in having Visual Studio attached.
 
I haven't looked at the sample code for some time, it is entirely possible that it isn't doing sensible things like stopping the sequencer properly before loading new MIDI files.
GeneralRe: Sequencer Demo : midi notes sometimes stuck loading new midi filesmembermrpulsar21 Jan '10 - 22:43 
Thanks for your reply...
 
I use the sample in a compiled app (not in debug environment), following the Leslie tip to disable the debug instructions too. In this way the midi files loading is quite faster than debug mode.
 
Even if you try to load new midifiles and play many times with them on the sequencer demo you'll understand my question. Often midi notes stuck and hangs putting the sequencer in a unusable state.
 
I tried to review the code adding stop and midi note off instructions but with no results.
 
Can you a point of view ?
 
Thanks,
 
Luca
GeneralRe: Sequencer Demo : midi notes sometimes stuck loading new midi filesmembermrpulsar24 Jan '10 - 22:49 
I've fixed it (i hope Smile | :) ) with some adjustments to the sequencerdemo code.
 
Many troubles occours whith the pianocontrol component (keyboard at bottom). Cutting away it i have no more problems with hanged midi notes; plus eliminating pianocontrol component solve the sequncer's sob while play with the s.o. windows (i do often this test to check the hardiness of the sequencer).
 
So... someone capable of this must be fix the part of pianocontrol to make stronger MidiToolkit. (anyway i no need the pianocontrol for now Smile | :) )
QuestionSending MIDI messages to a VST instrumentmemberXORDotNet25 Dec '09 - 9:43 
Hello to everyone, I'm an amateur programmer and musician... anyone can tell me how to send MIDI messages to a VST instrument?
 
For more details, I want to build an application that receives MIDI messages from an external instrument (KORG M3 keyboard for example), and if I press the C4 key on the keyboard, the application must create two MIDI messages additionally to form a C major (C4, E4 and G4), and then the application must send (or forward) these three notes to a VST instrument running on Kontakt Player for example. In this way the sounds are generated by the VST instrument, so... anyone can tell me how to send MIDI messages to a VST instrument?
 

Thank you all in advance and thank you Leslie for this toolkit.
 
nothing

AnswerRe: Sending MIDI messages to a VST instrumentmemberLeslie Sanford25 Dec '09 - 11:04 
You're best bet would be to write a VSTi/MIDI plugin. You could then run the MIDI plugin as well as the target plugin inside the same host and use its routing capabilities to route the output of the MIDI plugin into the target plugin.
 
It could prove challenging to attempt using my MIDI toolkit for the same purpose. I'm not sure offhand how it could be done, though others may have an idea or two.
GeneralRe: Sending MIDI messages to a VST instrumentmemberXORDotNet25 Dec '09 - 12:21 
Thanks for your prompt response. I would like to use your MIDI Toolkit for my purpose but for writing a VST / MIDI plugin without your toolkit, what resources do you recommend to investigate?
 
I greatly appreciate your response.
 
nothing

GeneralRe: Sending MIDI messages to a VST instrumentmemberLeslie Sanford25 Dec '09 - 12:39 
XORDotNet wrote:
for writing a VST / MIDI plugin without your toolkit, what resources do you recommend to investigate?

 
I'd begin with becoming familiar with Steinberg's VST SDK v2.4. It's in C++, though. If that's not a stumbling block, I'd get the SDK. Once you get it and the examples that come with it to compile, you can start digging into them to learn how to create your own plugins. There's a forum[^] over at KVR where a lot of VST developers hang out. We'd be happy to answer your questions there. I've written a few VST/MIDI plugins, so I'm familiar with the steps needed to write one.
GeneralRe: Sending MIDI messages to a VST instrumentmemberXORDotNet25 Dec '09 - 12:50 
Thanks man, the way you respond is really wonderful, thanks for the replies, I'll investigate what you said.
 
nothing

GeneralRe: Sending MIDI messages to a VST instrumentmemberondra003 Mar '10 - 10:39 
OK, so this would work when youre recieving some midi signal, but can you play an sound via vst plugin when you want to create the tones of the melody in computer and than play it in the vst ? thanks Smile | :)
GeneralRe: Sending MIDI messages to a VST instrumentmemberRonald Schlenker17 Aug '10 - 23:10 
There is also another, maybe a simpler way to do it: Look here, this is a virtual midi loop-through driver called LoopBe1, which will create another Midi-In and Midi-Out device in your computer. Now, you can write your software using the Midi toolkit. The midi messages shall be written to the LoopBe1 device. In your DAW (Cubase), use the LoopBe1 as midi device for your VST instruments - that's it!
GeneralUser ListmemberJames Ingram18 Dec '09 - 0:10 
Hi all,
I am also a very grateful user of this wonderful Toolkit, and am thinking (after Alain Vizzini's post) that we ought to have a list of users. This would be a way of thanking Leslie for his work, and be an interesting resource for the rest of us. I, for one, would like to know what other people are doing...
 
If you want to be on the list, just reply to this post with a link to a website or a one sentence description of your project.
 
Putting oneself on this list is, of course, not a commitment to give help to beginners. (My project uses an older version of the toolkit and has moved on from MIDI, so what I once knew has disappeared into the recesses of my subconcious...)
 
The MIDI stuff on my website is here: http://james-ingram-act-two.de/moritz/moritzMidiNodes.html[^]
 
All the best,
 
James
GeneralRe: User Listmemberandynormancx18 Dec '09 - 22:32 
I'm extremely thankful for Leslie's excellent toolkit. I used it when I created the software for the Gigajam music tuition software, that is used by thousands of school kids to learn to play an instrument.
 
The toolkit is used to playback lesson files, record the pupils performance and then playback their performance with the lesson backing track. And it works brilliantly.
GeneralRe: User List [modified]memberRogueTrooper19 Jan '10 - 17:28 
I've made a program which was intended to be an patch editor/librarian for the Access Virus C series. I haven't worked on it for ages, but the patch librarian functions work well. I might finish it one day.
 
I'm just starting a new project which is an app to make the Korg PadKontrol do whatever I tell it to in Native Mode.
 
There are many, many things I could make it do including-
-assigning any scale to the pads
-assigning any chord to the pads
-doing cool light shows by making the pads flash
-controlling any DAW
-using the X-Y pad to move the mouse pointer
-using the pads to launch Windows apps
-play Noughts and Crosses(or any other simple game playable on a 4x4 board).
-make words scroll across the 7-segment LED.
 
modified on Tuesday, January 19, 2010 11:37 PM

GeneralRe: User ListmemberGoogleMaster19 Jan '10 - 22:20 
Hi everybody,
 
What a nice idea. I have used Leslie's toolkit for one small and one slightly larger project now and I have to say this toolkit is very well done.
 
The first project was a simple 'pitch bend rounder' application that I created to sort of emulate a Haaken Continuum using the R2M ribbon controller from Doepfer. Basically what it does is more or less intelligently round the pitchbend values for the target device whose pitchbend range is set to, for example one octave.
 
http://forums.rolandclan.com/index.php?action=show_thread&thread=29017&fid=1&page=1[^]
 
The second project is a bit more ambitious and I haven't really finished with it but it's completely usable at this point. It's a live performance control program allowing the Roland Fantom X to seamlessly switch between sounds by turning on/off internal parts and also external modules. I have also added numerous other nice features. More info can be found here:
 
http://www.livecommander.com/[^]
 
Here's a screenshot of an early version:
 
http://www.prognosis.nl/arjan/Fantom%20X%20Live%20Commander%20version%200.0006.png[^]
 
Anyway, a big thank you to Leslie for making this toolkit available.
 
Have fun,
Arjan
GeneralAn application of this programmemberAlain VIZZINI11 Dec '09 - 17:01 
Hi,
 
Thanks a LOT for this piece of code, it's exactly what I need and very nicely written.
 
I use this program to extract out of MIDI file the basic MIDI key information and feed it to a micro-controller and Yamaha chip to play the tunes (chiptune they call it).
Works fine, just listen to one even on main frame. If you're interrested : http://kalshagar.wikispaces.com/MIDI%2C+CSharp+and+Yamaha+chips[^]
 
Hope this helps.
Alan.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 18 Apr 2007
Article Copyright 2004 by Leslie Sanford
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid