From 2 PM Friday, Jan 20 - 10:00 PM CST Monday, Jan 23, ni.com will be undergoing system upgrades that may result in temporary service interruption. We appreciate your patience as we improve our online experience.

The MIDI Throughput.vi and the mididll.dll

Publish Date: May 22, 2008 | 3 Ratings | 5.00 out of 5 | Print

Table of Contents

  1. Requirements
  2. History
  3. Program Analysis
  4. Acknowledgements
  5. References
  6. Download Code

Author: Larry Goga, LAG Consulting and ALVIN User Group Director

The MIDI Throughput.vi is a solution to the problem of inputting MIDI data from the Windows OS into a National Instruments LabVIEW program. The MIDI Throughput.vi uses a custom DLL to interface to Windows and solves the problem of dealing with the Windows “callback” function by means of the LabVIEW Event Structure. The MIDI Throughput.vi displays the incoming MIDI data (midishortmsg) in the form of a 32-bit integer (I32). The MIDI data is then passed to subVIs taken from the midi-example.llb you can find in NI Developer Zone. This allows the MIDI data to be passed to the sound card for audio output. In this manner, the MIDI Throughput.vi both receives MIDI data and transmits it back to the Windows OS for playback, all inside a LabVIEW VI.

1. Requirements

This VI and its companion DLL were both written to run on a PC under the Windows XP operating system. The VI was written using LabVIEW 8.0.1. The source code for the DLL was written and compiled using LabWindows™/CVI Version 8.0. For the DLL to function properly, you must properly install the LabWindows/CVI Run-Time Engine Version 8.0.1 in the Windows OS. Earlier versions of the LabWindows/CVI Run-Time Engine are not compatible with this DLL. LabWindows/CVI Run-Time Engine Version 8.0.1 is available at no charge to registered users on the National Instruments Web site.

Back to Top

2. History

The MIDI Throughput.vi was created as the result of a call for help from the Explora Children’s Museum in Albuquerque, New Mexico. A designer there was trying to design an exhibit that would explain the concept of “musical timbre” to children. To this end, an exhibit was created that used a MIDI/USB keyboard to play musical notes and a Creative Technology’s Sound Blaster sound card to turn the MIDI data into analog audio signals. The exhibit needed to capture the analog audio and display the resulting waveforms on a computer screen. The exhibit also included a series of pushbutton switches to select one of six different musical instrument “voices” and two sets of pushbuttons to record and play back two seconds of audio data. All of this was controlled by one LabVIEW program.

The NI Web site provided the perfect example program for how to output MIDI data from a LabVIEW program to the Windows OS. (See midi-example.llb in the NI Developer Zone.) However, there was no corresponding example that showed how to get incoming MIDI data from the Windows OS into a LabVIEW program. An analysis of this problem showed that the solution was anything but trivial. For inputting MIDI data, Windows relies on using a mechanism called “callbacks” to hand off MIDI data to an external application that requests it. Unfortunately, LabVIEW has no internal mechanism to directly request a “callback.” This is how the search for a solution to this problem started.

At the beginning, it was decided that if a solution could be found, it should follow the preexisting paradigm of the “midi-example” program. This paradigm is very similar to many other coding models in LabVIEW. Normally, a communications path is opened to an external device (OPEN.vi). Data is read from or written to that device (READ.vi or WRITE.vi). When finished, the communications path is closed and the device resource is returned to the OS for later use (CLOSE.vi). This type of coding model is found in data acquisition, image acquisition, Virtual Instrument Software Architecture (VISA), the Sound VIs, and in many other LabVIEW programs.

A search of the Internet turned up an excellent source of MIDI programming information in the work done by J. Glatt (see References at the end of this document). Glatt’s Web site provided several C++ source code files for creating executables to both read and write MIDI data. The first attempt to compile his code using LabWindows/CVI failed because of references in the code to a header file called conio.h. Subsequently, it was learned that conio.h is a header file that is not supported by an ANSI C compiler such as CVI. Thanks to the work of Jeff Tipps at NI Tech Support, the MIDI input code was modified to use stdio.h function calls instead of conio.h, and the new source code did compile and would execute. A method to read and display incoming MIDI data was then available, but this data was not yet accessible by a LabVIEW program.

At this point, it was determined that the solution to the MIDI input problem lay in creating a custom DLL and calling that DLL from inside a LabVIEW program. With the assistance of Chris Burak, a LabVIEW and C++ programmer from RIO Scientific, a DLL was created that could be called from inside a LabVIEW program. Burak’s solution allowed for the opening and closing of the default MIDI devices, but it did not allow for selecting any other MIDI devices. Burak’s solution also didn’t make the MIDI data available inside the LabVIEW program. Instead, it simply handed the data immediately back to Windows for output. Because Burak’s DLL was written using C++, it presented several new problems when LabWindows/CVI was used to try to recompile the code. Still, it was a working solution and it did solve the original problem for the Explora Museum exhibit.

Because it was apparent that there were others who were also interested in a solution to this problem, it was decided that this solution should be further developed and then submitted to NI as a user solution for inputting MIDI data into a LabVIEW program. This was accomplished by enlisting the services of David Bonal, one of the NI field sales engineers in Albuquerque. Bonal agreed that the proper solution should follow the existing paradigm and that it should make the MIDI data available to the LabVIEW program should the end user wish to manipulate the data before outputting it to the sound card. To accomplish this, Bonal took the work done by Glatt and Burak and created a new DLL that was written in ANSI C and, thus, could be compiled by LabWindows/CVI. It is Bonal’s DLL that is used in this solution.

Back to Top

3. Program Analysis

The MIDI Throughput.vi uses both Bonal’s DLL and his VI solution along with subVIs taken from the midi-example.llb library file. The main VI contains a while loop, inside of which is placed a LabVIEW Event Structure. The subVIs from midi-example are used to (1) open a channel to the MIDI output device, (2) select the appropriate musical “voice” using the Select Patch.vi, (3) accept the incoming MIDI data and send it back to Windows using the midioutshortmsg.vi and (4) close the MIDI output channel upon completion of the program. All of the subVIs taken from midi-example.llb have been rewritten to follow the example from NI for error handling in subroutines.

To input the MIDI data, it is first necessary to open a channel to the MIDI input device. This is accomplished by the midiinopen.vi. This subVI calls the custom mididll.dll and passes to it the MIDI Input Device number and a User Event Reference. By creating a user event and registering that event, the Event Structure is notified when incoming MIDI data becomes available. A user event must be created before calling the midiinopen.vi. LabVIEW does not have the ability to respond to DLL callbacks. With user events, a callback mechanism that passes messages from the DLL is possible. The DLL uses the LabVIEW CINTOOL function PostLVUserEvent. This function fires a user event for the event for which data is to be posted. Also, this function passes data to the Event Structure with which it is registered. This data is passed into the Event Structure through the “value” parameter in the form a 32-bit integer (I32). The four bytes of MIDI data contained in the I32 are already in the correct position for output so they are simply displayed and then passed to the midioutshortmsg.vi. Upon program termination, the midiinclose.vi closes the channel to the MIDI input device and releases the resource back to the OS. At the same time, the Registration for User Events is cancelled, and any unprocessed events that might remain in the event cue are destroyed.

This program has been tested on several computers running Windows XP with LabVIEW 8 and the LabWindows/CVI Run-Time Engine 8.0.1 previously installed. The MIDI input device for these tests was an M-Audio O2 keyboard controller with a USB interface. The Windows XP OS immediately recognizes the keyboard as a MIDI I/O device and makes it available to the API. The program was developed on a Dell XPS Gen3 with a Creative Technology Sound Blaster Audigy sound card installed. The installation of the drivers for the Sound Blaster also adds three additional MIDI tone generator files to the Windows OS. These tone generators are:

  1. SB Audigy Synth A
  2. SB Audigy Synth B
  3. SB Audigy SW Synth

These files are in addition to the Microsoft GS Wavetable SW Synth file that is installed as part of the Windows OS. Unfortunately, the “Microsoft GS Wave … ” tone generator suffers from severe latency. This latency issue causes an excessive delay between the time a key pressed on the MIDI keyboard and the time the sound is played. This latency does not exist when any of the SB Audigy files are used. The latency issue with the Microsoft file is known to exist, and a search of the Internet reveals several fixes for the problem although none of them are considered easy. If at all possible, it is suggested that any of the Sound Blaster files should be used in preference to the Microsoft file.

To see which MIDI output devices are available and to set the default device, follow this path: Start Menu > Control Panel > Sound and Audio Devices. When the Sound and Audio Devices Properties window opens, click on the Audio tab. The Audio window is divided into three parts: Sound Playback, Sound Recording, and MIDI Music Playback. In the MIDI Music Playback section, there is a pull-down menu of available MIDI tone generators. As previously stated, it is better to select anything other than the “Microsoft … ” tone generator.

When a MIDI/USB keyboard is recognized by Windows, it is added to the menu in the Audio tab described above. Unfortunately, Windows does not know if the USB audio device is available for input only, output only, or both. Consequently, it adds the MIDI device to the list of MIDI Music Playback devices. Because the O2 keyboard is capable of MIDI input only, you should not select it as a MIDI Music Playback device. If the O2 keyboard is the only MIDI input device connected to the computer, then it should assume the position of the default MIDI input device (Device 0). All previous testing of the LabVIEW MIDI Throughput.vi shows that this should be the case, but there are no guarantees. If the program does not display any incoming MIDI data, and there are multiple MIDI input devices available, then stop the program, change the MIDI input device number, and try the program again. Also, additional testing has shown that if there is only one MIDI input device connected to the computer, then it doesn’t seem to matter what the MIDI input device number is set to because this program seems to respond to any number as the default device. Although this may be an error in the mididll.dll, only one MIDI input device was available at the time this program was tested.

In closing, it should be noted that this program does not support MIDI System Exclusive Messages. If the MIDI input device sends SYSEX messages, which are much longer than the three-byte MIDI Short Message, then the operation of this program is unknown. Unfortunately, a MIDI output device that was capable of generating SYSEX messages was not available at the time this program was developed or tested.

The C source code file that was used to create the mididll.dll file is included with this program and is compatible with LabWindows/CVI. The origin of this source code was the file MidiIn.c that was downloaded from the J. Glatt Web site (see References below). It is left to other programmers who are more fluent in C, knowledgeable about the Windows OS, and skilled in LabVIEW to take this program to the next level.

Back to Top

4. Acknowledgements

The following people played a part in the development of this program. Their help, support, and guidance were instrumental in reaching the solution presented here. Without their assistance, none of this would have been possible. Thanks to:

Jamie Olive, senior field sales engineer for New Mexico at National Instruments, for bringing this problem to the forefront and introducing me to the people at the Explora Children’s Museum.

Sherlock Terry, exhibit developer at Explora Children’s Museum in Albuquerque, for his patience in explaining to me the details of the exhibit that he was trying to create.

J. Glatt, publisher of MIDI is the language of gods (found on the Internet), for taking the time to publish a wealth of accurate and usable information about MIDI.

Robert Lowe, director of IT at Explora Children’s Museum in Albuquerque, for showing me that the Midiin.c program written by J. Glatt did indeed work.

Chris Burak, CEO and chief scientist at RIO Scientific in Stanley, New Mexico, for writing the DLL that provided the solution to the MIDI input problem for the Explora exhibit.

David Bonal, field sales engineer for New Mexico at National Instruments, for his work in improving the DLL and his help in providing the solution that is presented here.\

Back to Top

5. References

1. Communicating with a Windows MIDI Device in LabVIEW

This document shows how to use the Windows Multimedia DLL to communicate with a MIDI device and includes the downloadable example VI, midi-example.llb.

2. MIDI is the language of gods

This is the home page of a series of comprehensive articles on MIDI and MIDI programming published by J. Glatt.

3. A Low Level MIDI API

This document is a very thorough discussion of how to input and output MIDI data. It is a part of the series of MIDI articles published by J. Glatt and referenced above. At the end of this article is a clickable link to downloadable C++ source code file for a program that can input MIDI data and deal with Windows “callbacks.” Midi In Callback

4. FAQ: Using Dynamic Link Libraries with LabWindows/CVI

This NI Developer Zone document is an excellent reference on how to use DLLs in a LabVIEW VI and how to convert DLLs written in C++ to LabWindows/CVI.

5. Musical Instrument Digital Interface (MIDI)

This is the home page for information about MIDI at the Microsoft Developers Network. From this starting point, you can find specific information about each of the MIDI function calls in the Windows Multi Media DLL (winmm.dll).

Back to Top

6. Download Code

Back to Top

Bookmark & Share


Downloads


Ratings

Rate this document

Answered Your Question?
Yes No

Submit