MMAPG - Sequencer Device
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
Sequencer Device
The OS/2 sequencer device plays a MIDI song by sending commands from a MIDI file to a synthesizer, where the commands are converted to the sounds of a specific instrument. Typically, a digital signal processor (DSP) is used to generate the sounds of the instrument, which results in an authentic reproduction of the original performance.
General MIDI (Musical Instrument Digital Interface) is a standard specification for playing back music from a series of commands, rather than actual audio data. The commands represent musical events, such as turning a note on and off ("Note On" and "Note Off"), as well as timing mechanisms for specifying the duration of the note sound. The sequencer uses the timing commands to sequence the playing of the music.
Following is a text example of the commands generated when someone depresses the "middle C" key of a synthesizer keyboard: a note-on command X'90' and two bytes of data:
- X'90' - "Note-on" command to MIDI channel 0
- X'3C' - Keyboard note (middle-C)
- X'40' - Velocity (X'00'-X'7F').
MIDI augments waveform audio as a means of producing sounds in the multimedia environment. MIDI data offers the advantage of requiring far less storage than waveform data. For example, suppose a three-note chord—middle-C, E and G—is held for one second. Following are the MIDI commands required to reproduce the chord on a synthesizer:
- TIME = 0 sec
- 90 3C 40 (C-on)
- 90 40 40 (E-on)
- 90 43 40 (G-on)
- TIME = 1 sec
- 90 3C 00 (C-off)
- 90 40 00 (E-off)
- 90 43 00 (G-off)
The storage required for the MIDI commands is 18 bytes. To store the same information as 16-bit, PCM, 44 kHz, stereo waveform audio data requires 176KB.
Another advantage of storing musical performances as a series of instructions is that the information can be edited, the same way words in a document can be edited by a word processor. The musical editing process can be used, for example, to correct mistakes in an artist's original interpretation, or to change certain points of style before playback or final recording. Playback of MIDI data using the sequencer media device can be used to reproduce the original performance or to print out musical scores.
Sequencer Device Specifics
The sequencer device sends MIDI messages and data to the audio adapter. Some audio adapters, such as the M-Audio adapter, perform FM synthesis to produce music. Other audio adapters, such as the Sound Blaster adapter, have the capability to send the MIDI data through a MIDI port to an external synthesizer device.
The OS/2 sequencer device does not currently support recording new MIDI information.
MIDI Stream Connector
The MIDI stream connector represents the flow of MIDI information from the sequencer device to its associated amplifier-mixer (ampmix) device. During playback, the sequencer device sends MIDI information from either application memory or files to the ampmix device for subsequent conversion into audio that can be heard through conventional speakers or headphones.
Control of the characteristics of the MIDI information is provided by the sequencer device. Volume control is provided as an additional service, although this feature is actually provided by the ampmix device in a way that is transparent to the calling application. If other advanced audio-shaping features are required, the application can retrieve the device ID of the ampmix device using the MCI_CONNECTION message. Once the device ID has been obtained, the application can send set commands directly to the ampmix device to manipulate audio attributes, such as treble, bass, balance, and so on.
MIDI Data Formats
The MIDI support for the OS/2 multimedia system handles the RIFF RMID data type, as well as standard MIDI file formats 0 and 1. MIDI file format 0 merges tracks of MIDI data into one track; MIDI file format 1 preserves the separate tracks of data. MIDI file format 2 is not supported.
MIDI files are made up of chunks, similar to RIFF chunks. In MIDI files, there are two types of chunks: header chunks and track chunks. A header chunk provides a minimal amount of information pertaining to the entire file. A track chunk contains a sequential stream of MIDI data, which can contain information for up to 16 MIDI channels.
General MIDI Specification
The standard MIDI channel, patch, and percussion key assignments shown in the following tables are defined in the General MIDI Specification issued by the MIDI Manufacturers Association (MMA).
Channel Assignments
Channels are divided into two general categories, low-end synthesizer support and high-end synthesizer support. The following table shows the channel assignments for this standard.
| Channel Range | Use Description | Polyphony |
|---|---|---|
| 1 through 9 | Extended Melodic Tracks | 16 Notes |
| 10 Only | Extended Percussion Track | 16 Notes |
| 11 through 12 | Unused Tracks | |
| 13 through 15 | Base-Level Melodic Tracks | 6 Notes |
| 16 Only | Base-Level Percussion Track | 3 Notes |
Patch Assignments
The following table shows the standard patch definitions for MIDI instruments. Each family of instruments (for example, strings or brass) has eight different voice numbers reserved for patch definitions.
| Piano | Chromatic Percussion | Organ | Guitar |
|---|---|---|---|
| 0 Acoustic Grand Piano | 8 Celesta | 16 Hammond Organ | 24 Acoustic Guitar (nylon) |
| 1 Bright Acoustic Piano | 9 Glockenspiel | 17 Percussive Organ | 25 Acoustic Guitar (steel) |
| 2 Electric Grand Piano | 10 Music box | 18 Rock Organ | 26 Electric Guitar (jazz) |
| 3 Honky-Tonk Piano | 11 Vibraphone | 19 Church Organ | 27 Electric Guitar (clean) |
| 4 Rhodes Piano | 12 Marimba | 20 Reed Organ | 28 Electric Guitar (muted) |
| 5 Chorused Piano | 13 Xylophone | 21 Accordion | 29 Overdriven Guitar |
| 6 Harpsichord | 14 Tubular Bells | 22 Harmonica | 30 Distortion Guitar |
| 7 Clavinet | 15 Dulcimer | 23 Tango Accordion | 31 Guitar Harmonics |
| Bass | Strings | Ensemble | Brass |
| 32 Acoustic Bass | 40 Violin | 48 String Ensemble 1 | 56 Trumpet |
| 33 Electric Bass (finger) | 41 Viola | 49 String Ensemble 2 | 57 Trombone |
| 34 Electric Bass (pick) | 42 Cello | 50 Synth Strings 1 | 58 Tuba |
| 35 Fretless Bass | 43 Contrabass | 51 Synth Strings 2 | 59 Muted Trumpet |
| 36 Slap Bass 1 | 44 Tremolo Strings | 52 Choir Aahs | 60 French Horn |
| 37 Slap Bass 2 | 45 Pizzicato Strings | 53 Voice Oohs | 61 Brass Section |
| 38 Synth Bass 1 | 46 Orchestral Harp | 54 Synth Voice | 62 Synth Brass 1 |
| 39 Synth Bass 2 | 47 Timpani | 55 Orchestra Hit | 63 Synth Brass 2 |
| Reed | Pipe | Synth Lead | Synth Pad |
| 64 Soprano Sax | 72 Piccolo | 80 Lead 1 (square) | 88 Pad 1 (New Age) |
| 65 Alto Sax | 73 Flute | 81 Lead 2 (sawtooth) | 89 Pad (warm) |
| 66 Tenor Sax | 74 Recorder | 82 Lead 3 (calliope lead) | 90 Pad 3 (polysynth) |
| 67 Baritone Sax | 75 Pan Flute | 83 Lead 4 (chiff lead) | 91 Pad 4 (choir) |
| 68 Oboe | 76 Bottle Blow | 84 Lead 5 (charang) | 92 Pad 5 (bowed) |
| 69 English Horn | 77 Shakuhachi | 85 Lead 6 (voice) | 93 Pad 6 (metallic) |
| 70 Bassoon | 78 Whistle | 86 Lead 7 (fifths) | 94 Pad 7 (halo) |
| 71 Clarinet | 79 Ocarina | 87 Lead 8 (bass + lead) | 95 Pad 8 (sweep) |
| Synth Effects | Ethnic | Percussive | Sound Effects |
| 96 FX 1 (rain) | 104 Sitar | 112 Tinkle Bell | 120 Guitar Fret Noise |
| 97 FX 2 (soundtrack) | 105 Banjo | 113 Agogo | 121 Breath Noise |
| 98 FX 3 (crystal) | 106 Shamisen | 114 Steel Drums | 122 Seashore |
| 99 FX 4 (atmosphere) | 107 Koto | 115 Woodblock | 123 Bird Tweet |
| 100 FX 5 (brightness) | 108 Kalimba | 116 Taiko Drum | 124 Telephone Ring |
| 101 FX 6 (goblins) | 109 Bagpipe | 117 Melodic Drum | 125 Helicopter |
| 102 FX 7 (echoes) | 110 Fiddle | 118 Synth Drum | 126 Applause |
| 103 FX 8 (sci-fi) | 111 Shanai | 119 Reverse Cymbal | 127 Gunshot |
Percussion Key Assignments
In MIDI, timbre (the sound of a specific instrument; for example, a violin or a trumpet) for most instruments is assigned a specific number. For example, voice 56 represents a trumpet sound. Thus, all note values for voice 56 produce notes having the distinctive sound of a trumpet.
Typically, number assignments for percussion instruments are handled differently. Although each percussion instrument has a distinctive sound, all percussion instruments for a particular synthesizer are assigned one voice or timbre number. For example, if a synthesizer specifies that timbre 45 is a PCM percussion set, then note 60 (Middle C) might be for a kettle drum, 61 for a bass drum, 62 for a triangle and so on.
Many manufacturers use percussion and note number assignments that are unique to their hardware. For example, note 60 might be assigned to a kettle drum on one synthesizer model and to castanets on another.
MIDI Mapping Function
The MIDI mapping function provided with the sequencer device offers a level of device independence to application developers. Because MIDI patch assignments and percussion key assignments of different MIDI manufacturers vary, the MIDI mapper can be enabled to dynamically translate MIDI data in real-time, as a MIDI song is played. An application enables the mapper by setting the port with the MCI_SET command:
set sequencer port mapper
The user can configure the sequencer device by selecting from a list of available device types. The list is provided on the mapper page of the Multimedia Setup application. OS/2 multimedia provides a General MIDI map, as well as a map for each sequencer device supported by OS/2 multimedia. A mapper page also allows the user to enable or disable specific channels.
Once the MIDI mapper is enabled, the Sequencer expects the MIDI files it plays to conform to the General MIDI Specification. The MIDI mapper translates the General MIDI format to the appropriate device format as specified in the Mapper page of a MIDI device in Multimedia Setup.
Guidelines for MIDI Song Authors
MIDI authors should be aware of several design concerns when producing a MIDI song:
- The General MIDI specification defines a base-level configuration and an extended-level configuration for synthesizers. Because you cannot control which synthesizer is used to play your song, you should provide percussion and melody tracks for both configurations.
- Put your important melody sounds in the lower-numbered channels. By prioritizing channel use, you ensure that your song sounds reasonable when it is played on hardware that supports only a few channels.
- When selecting instruments for your MIDI song, use the instruments that are defined for the most popular MIDI devices. Your song can then be easily and accurately mapped to other hardware formats.
- When using nonpercussive channels, limit the polyphony (number of simultaneous notes) to 6 notes for the base level and 16 notes for the extended level.
- When using percussion channels, limit the polyphony to 3 notes for the base level and 16 notes for the extended level.
- Use the standard General MIDI patch assignments and percussion key assignments.
- Always send a program change command to a channel before sending other commands to the channel. For channels 10 and 16, which are used for percussion, select patch 0.
- Always send a MIDI main volume controller command (controller number 7) to a channel after selecting a patch by sending a program change command. Use the value of 80 (X'50') for normal listening levels.
Using the Sequencer Device
After you open the sequencer device, query the division type of the device element with a status command. Division type refers to the method used to represent the time between MIDI events in the sequence.
open mysong.mid alias midi1 shareable status midi1 division type wait
A MIDI file's division type can be either PPQN or any of the following SMPTE formats:
- PPQN (parts-per-quarter-note)
- SMPTE 24 frame
- SMPTE 25 frame
- SMPTE 30 frame
- SMPTE 30 drop frame
After you determine the file division type, you can make other status queries such as:
- length: Length of sequence
- length track n: Length of track n
- position: Current position of sequence
- position track n: Current position of track n
- tempo: Current tempo.
Responses are all in the current time format. PPQN files return length and position information in song pointer units. However, SMPTE files return the information in colon format HOURS:MINUTES:SECONDS:FRAMES. PPQN files return the tempo in beats per minute; SMPTE files return the tempo in frames per second.
Playing A MIDI Song
Before you start playing MIDI music, you may want to set the port to the MIDI mapper so that channel and patch reassignments can be made.
set midi1 port mapper seek midi1 to start wait play midi1 notify ** playing ** close midi1
Creating MIDI Memory Files
Applications that access memory buffers to store and access MIDI data can use the memory I/O features of the multimedia input/output (MMIO) file services. This technique consists of opening a memory file using mmioOpen. mmioOpen has a pointer to the buffer of MIDI data as a parameter. This buffer can then be operated on by MCI and MMIO as if it were a file.
Care must be taken when calling MMIO functions and sending MCI messages to the same memory file. MMIO and MCI are independent subsystems linked only through the MMIO memory handle passed to MCI_OPEN. Each subsystem keeps its own set of relevant files and stream pointers. If one subsystem changes the data in memory, but the memory had previously been cued with MCI_CUE, the change of data will not be recognized by MCI until a call to reload the streams has been issued.
The following code fragment shows the opening of a memory file with a user-supplied MIDI buffer of untranslated (format 0 or 1) data and the playing of that data through MCI.
{
/* variable for IOProc */
PMMIOPROC pIOProc;
HMODULE hModMidiio;
/* variables for memory file */
MMIOINFO mmioInfo;
CHAR UserBuffer[SIZE_OF_BUFFER];
HMMIO hmmio;
/* variables for MCI commands */
MCI_OPEN_PARMS mop;
MCI_PLAY_PARMS mpp;
/* Open memory file. Provide MIDI-filled data buffer to MMIO, so
* data buffer becomes file image in memory. Also specify that
* the data will need to be translated.
*/
mmioInfo.pchBuffer = UserBuffer; /* Filled with untranslated
MIDI data */
mmioInfo.cchBuffer = SIZE_OF_BUFFER; /* User-defined */
mmioInfo.ulTranslate = MMIO_TRANSLATEDATA | MMIO_TRANSLATEHEADER;
/* Need to translate data */
mmioInfo.fccIOProc = mmioFOURCC( 'M', 'I', 'D', 'I');/* Data
format */
mmioMemInfo.fccChildIOProc = FOURCC_MEM; /* Storage type */
hmmio = mmioOpen ( NULL, mmioInfo, MMIO_READWRITE );
/* open MIDI device */
mop.pszElementName = (PSZ) hmmiomem;
mciSendCommand(
0, /* We don't know the device yet. */
MCI_OPEN, /* MCI message */
MCI_WAIT | MCI_OPEN_MMIO |
MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE
(ULONG) &mop, /* Parameters for the message */
0 ); /* Parameter for notify message */
/* play MIDI memory file for 1 second */
mpp.ulFrom=0;
mpp.ulTo=3000; /* default is MMTIME units (1/3000 second) */
mciSendCommand(
mop.usDeviceID, /* Device to play the data */
MCI_PLAY, /* MCI message */
MCI_WAIT |
MCI_FROM | MCI_TO, /* Flags for the MCI message */
(ULONG) &mpp, /* Parameters for the message */
0 ); /* No parm necessary */
/* close device */
mciSendCommand(
mop.usDeviceID, /* Device to play this */
MCI_CLOSE, /* MCI message */
MCI_WAIT, /* Flags for the MCI message */
(ULONG) NULL, /* Parameters for the message */
(ULONG) NULL ); /* Parameter for notify message */
}
Sequencer Command Messages
| Message | Description |
|---|---|
| MCI_CLOSE | Closes the sequencer device. |
| MCI_CONNECTOR | Enables or disables a connector, queries its state or identifies its type. |
| MCI_CUE | Cues the device for minimum delay in playback or recording:
|
| MCI_GETDEVCAPS | Gets device capabilities. |
| MCI_INFO | Gets the following information:
|
| MCI_LOAD | Loads a sequencer data file. |
| MCI_OPEN | Initializes the sequencer device. |
| MCI_PLAY | Plays back MIDI data by means of the audio adapter. Optional actions:
|
| MCI_PAUSE | Suspends the current playback action. |
| MCI_RESUME | Resumes playing from a paused state, keeping previously specified parameters in effect. |
| MCI_SAVE | Saves the device element in its current format. |
| MCI_SEEK | Moves to the specified position in the device element. |
| MCI_SET | Sets audio attributes:
Sets sequencer information:
Sets time format: Song pointer, SMPTE 24, 25, 30, 30 drop. |
| MCI_SET_CUEPOINT | Sets a cue point. |
| MCI_SET_POSITION_ADVISE | Sets a position change notification request. |
| MCI_SET_SYNC_OFFSET | Sets a synchronization offset. |
| MCI_STATUS | Receives status on items such as: File division type, length, sync master/slave status, assigned MIDI port, SMPTE offset, current tempo and time format. |
| MCI_STOP | Stops the sequencer device before loading a file. |
Sequencer Connectors
The sequencer device directly supports one MIDI stream connector that is always enabled. As it is likely that an application will need to select the output destination on the amplifier-mixer device, the sequencer device will attempt to provide the following connector services to an application. If the requested connector is not available, the command will fail.
- headphones
- speakers
- line out
Additional connectors may be available on the ampmix device. To control these connectors, obtain the device ID of the ampmix device using the MCI_CONNECTION message and issue the connector command directly to the associated amplifier-mixer.
To determine which connectors are supported by an amplifier-mixer device, use the MCI_CONNECTORINFO message.