Jump to content

MMAPG - Sequencer Device

From EDM2
Multimedia Application Programming Guide
  1. Introduction
  2. What's New...
  3. Multimedia Application Programming Environment
  4. Media Control Interface
  5. Multimedia Logical Devices
  6. Amplifier-Mixer Device
  7. Waveform Audio Device
  8. Sequencer Device
  9. CD Audio Device
  10. CD-XA Device
  11. Videodisc Device
  12. Digital Video Device
  13. Direct Interface Video Extensions (DIVE)
  14. Captioning
  15. OS/2 Multimedia Controls
  16. Multimedia I/O File Services
  17. Resource Interchange File Format (RIFF) Services
  18. Sample Application Programs
  19. Installing a Program Using MINSTALL
  20. Caption DLL
  21. High-Level Service API
  22. Notices
  23. Glossary

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:
  • Cues a sequencer input device
  • Cues a sequencer output device
MCI_GETDEVCAPS Gets device capabilities.
MCI_INFO Gets the following information:
  • Sequencer product name
  • Name of the currently loaded file
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:
  • Specify start and stop positions in the device element
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:
  • Identify the channels to be used
  • Set the volume
  • Enable or disable the audio output

Sets sequencer information:

  • Set the sequencer as master and specify type of MIDI data
  • Change the SMPTE offset
  • Set the output MIDI port
  • Set the MIDI mapper as the port
  • Set the sequencer as slave
  • Set the tempo

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.