Although the Loader is a decidedly unglamorous feature of DirectX Audio, it is a good idea to become familiar with it. Not only does the Loader manage the files you load, it also manages how they are cached in memory. So, even if you skip past this chapter for now, be sure to come back and give it a read later.
The Loader serves three purposes: managing linkages between DirectMusic files, providing convenience functions for easy file loading and manipulation, and being replaceable so an application can write its own customized Loader that can deliver resources from a packaged file format of its own devising (more on why this is useful later).
The Loader manages the relatively complex linkages that exist between DirectMusic files. For example, a Style playback Segment file might reference both a Style file and a DLS instrument file. Because multiple Segments might use the same Style and DLS files, it is extremely inefficient to bundle up all the Style and DLS data into the Segment. You end up with multiple files bundling redundant Style and DLS data. Worse, all this data would redundantly load into memory with the Segment. The solution is to place the shared Styles and DLS instruments in their own files that the Style playback Segment references. At the time the Segment is loaded, the appropriate Style and DLS files must also be loaded and correctly linked. The Loader provides a centralized mechanism to manage this for you.
In Figure 9-1, three Segment files reference different combinations of DLS, Style, and wave files. The Loader manages internal pointers to the DLS, Style, and wave objects, so only one instance of each is necessary.
Figure 9-1: File referencing in DirectMusic.
In some circumstances it is reasonable to bundle all of the files required by a Segment into the Segment itself. This can include waves, DLS, Styles, and more. You can create Segments with embedded files with the Segment Designer in DirectMusic Producer. This has the advantage of packaging the Segment as just one file with no dependencies. It is great for music file players, since there is no need to ship a set of interconnected files.
The Loader serves as a convenience function for easy file loading. All DirectMusic objects that can be loaded from files support the standard COM file I/O interface IPersistStream. By supporting this, any DirectMusic object can be loaded in a few steps by:
Calling CoCreateInstance() to create an instance of the object.
Calling the object's QueryInterface() method to retrieve its IPersistStream interface.
Creating a file stream object represented by the standard IStream interface.
Presenting the IStream to the IPersistStream Load() method, which reads the data from the stream and creates the instance of a loaded object.
Clearly, this is a lot of work, and yet it is something that every application must do. Therefore, it makes sense to provide a standard helper so the application does not have to do this redundant work.
Applications like games often keep resources bundled up in one large file. Although DirectMusic's container format provides an easy way to accomplish that, it still does not provide encryption or compression features that a game might require. Because the Loader uses a publicly defined interface, you can create your own Loader and have it retrieve the data in any way that it pleases.