Whole document tree Chapter 15Providing MIDI Services
Chapter 13, "Introduction to the Service Provider Interfaces," explained that the Applications programmers who only use existing MIDI services in their programs can safely skip this chapter. For an overview of MIDI and the use of the installed MIDI services in an application program, see Part II, "MIDI," of this Programmer's Guide. This chapter assumes that the reader is familiar with the JavaTM Sound API methods that application programs invoke to access installed MIDI services. Introduction
There are four abstract classes in the
An application program won't directly create an instance of a service object-whether a provider object, such as a Providing MIDI File-Writing ServicesThere are three standard MIDI file formats, all of which an implementation of the Java Sound API can support: Type 0, Type 1, and Type 2. These file formats differ in their internal representation of the MIDI sequence data in the file, and are appropriate for different kinds of sequences. If an implementation doesn't itself support all three types, a service provider can supply the support for the unimplemented ones. There are also variants of the standard MIDI file formats, some of them proprietary, which similarly could be supported by a third-party vendor.
The ability to write MIDI files is provided by concrete subclasses of The first of these provides general information about whether the file writer can ever write the specified type of MIDI file type. The second method is more specific: it asks whether a particular Sequence can be written to the specified type of MIDI file. Generally, you don't need to override either of these two concrete methods. In the default implementation, each invokes one of two other corresponding query methods and iterates over the results returned. Being abstract, these other two query methods need to be implemented in the subclass:boolean isFileTypeSupported(int fileType) boolean isFileTypeSupported(int fileType, Sequence sequence) The first of these returns an array of all the file types that are supported in general. A typical implementation might initialize the array in the file writer's constructor and return the array from this method. From that set of file types, the second method finds the subset to which the file writer can write the given Sequence. In accordance with the MIDI specification, not all types of sequences can be written to all types of MIDI files.abstract int[] getMidiFileTypes() abstract int[] getMidiFileTypes(Sequence sequence)
The To do this, theabstract int write(Sequence in, int fileType, java.io.File out) abstract int write(Sequence in, int fileType, java.io.OutputStream out) write method must parse the Sequence by iterating over its tracks, construct an appropriate file header, and write the header and tracks to the output. The MIDI file's header format is, of course, defined by the MIDI specification. It includes such information as a "magic number" identifying this as a MIDI file, the header's length, the number of tracks, and the sequence's timing information (division type and resolution). The rest of the MIDI file consists of the track data, in the format defined by the MIDI specification.
Let's briefly look at how the application program, MIDI system, and service provider cooperate in writing a MIDI file. In a typical situation, an application program has a particular MIDI Providing MIDI File-Reading Services
The Concrete subclasses must implement these methods to return a filled-outabstract MidiFileFormat getMidiFileFormat(java.io.File file) abstract MidiFileFormat getMidiFileFormat( java.io.InputStream stream) abstract MidiFileFormat getMidiFileFormat(java.net.URL url) MidiFileFormat object describing the format of the specified MIDI file (or stream or URL), assuming that the file is of a type supported by the file reader and that it contains valid header information. Otherwise, an InvalidMidiDataException should be thrown.
The other overloaded method returns a MIDI Theabstract Sequence getSequence(java.io.File file) abstract Sequence getSequence(java.io.InputStream stream) abstract Sequence getSequence(java.net.URL url) getSequence method performs the actual work of parsing the bytes in the MIDI input file and constructing a corresponding Sequence object. This is essentially the inverse of the process used by MidiFileWriter.write . Because there is a one-to-one correspondence between the contents of a MIDI file as defined by the MIDI specification and a Sequence object as defined by the Java Sound API, the details of the parsing are straightforward. If the file passed to getSequence contains data that the file reader can't parse (for example, because the file has been corrupted or doesn't conform to the MIDI specification), an InvalidMidiDataException should be thrown.
Providing Particular MIDI Devices
A
As with the other
Because a single subclass of The returned array can contain a single element, of course. A typical implementation of the provider might initialize an array in its constructor and return it here. In turn, an implementation of theabstract MidiDevice.Info[] getDeviceInfo() MidiSystem can iterate over all the installed MidiDeviceProviders to construct lists of installed devices that it returns to the application program.
This method permits the system to query the provider about a specific kind of device. Generally, you don't need to override this convenience method. The default implementation iterates over the array returned by getDeviceInfo and compares the argument to each element.boolean isDeviceSupported(MidiDevice.Info info)
The third and final This method should first test the argument to make sure it describes a device that this provider can supply. If it doesn't, it should throw anabstract MidiDevice getDevice(MidiDevice.Info info) IllegalArgumentException . Otherwise, it returns the device.
Providing Soundbank File-Reading Services
A
Concrete subclasses ofabstract Soundbank getSoundbank(java.io.File file) abstract Soundbank getSoundbank(java.io.InputStream stream) abstract Soundbank getSoundbank(java.net.URL url) SoundbankReader will work in tandem with particular provider-defined implementations of SoundBank , Instrument , and Synthesizer to allow the system to load a SoundBank from a file into an instance of a particular Synthesizer class. Synthesizers may differ wildly in their synthesis techniques, and, as a consequence, the data stored in an Instrument or SoundBank that provides the control or specification data for a Synthesizer's synthesis process can take a variety of forms. One synthesis technique may only require only a few bytes of parameter data; another may be based on extensive sound samples. The particular set of resources present in a SoundBank will depend upon the nature of the Synthesizer into which they get loaded, and therefore a SoundbankReader subclass's implementation of the getSoundbank method has access to knowledge about a particular kind of SoundBank . In addition, a particular subclass of SoundbankReader also understands a particular file format for storing the SoundBank data. That file format may be vendor-specific and proprietary.
Soundbank files are created outside the Java Sound API, typically by the vendor of the synthesizer that can load that kind of soundbank. Some vendors might supply end-user tools for creating such files. [Top] [Prev] [Next] [Bottom] Copyright © 2000, Sun Microsystems Inc. All rights reserved. |