7. GSound: The GWindows Sound System
Technically, the GWindows Sound System is not part of GWindows itself. Rather, it is a separate module which is designed to work in tandem with GWindows. You can use GWindows without the GSound Module, and you can use the GSound module without the rest of GWindows.
To install the GWindows Sound System, insert the line:
If you are using GSound without GWindows, you must also include the GWindows Core's definitions file:
before including the Inform parser.
7.1 GSound Features
The GWindows Sound System is capable of using all the features available for Glk audio. It automatically manages the allocation of Glk sound resources as needed to maximize the availablility of audio features where possible.
Please note: All current Glk implementations provide some restriction on sound availability, whether this be the total absence of sound, unavailability of certain sound formats (The SONG format is supported on almost no platforms, and MOD is not universally available), lack of sound notification events, or simply a limitation on the number of simultaneous sounds. GSound attempts to cope with this as best it can, but you should always check the status of any sound-related request to make sure it worked.
Whenever the player does a restart, restore, or undo, the sound system is completely reset; all playing sounds will stop. GSound will attempt to restart any sounds which were playing in a loop. This may produce a "stuttering" effect if the player, say, types undo several times in rapid succession, but this is necessary to maintain a consistant sound state.
7.2 Sound Channels
The fundamental object for dealing with sound resources under GSound is a sound channel. A sound channel is roughly analagous to a screen window. A sound channel can play a single sound at any time, and may have certain rules attached to it, called audio effects.
The GWindows Sound System defines three major classes of sound channel:
GSvChannel: This is the common ancestor of all GSound Sound channels. You should not create GSvChannels directly, but if you want to loop over all sound channels, you can use
objectloop (o ofclass GSvChannel)to do this.
GSChannel: A normal user sound channel. Most sound channels you declare will be of this type.
GSMusicChannel: Glk does not really make any distinction between "music" and "sound effects", however, the underlying formats for sound resources supported by blorb are suited to different tasks; the MOD format is well suited for music, while the AIFF format is better suited for sound effects (certainly, either format could contain either, but placing a short sound effect in a MOD would result in excessive load-time, and placing a long piece of music in an AIFF would result in a huge filesize). Because many Glk implementations do not support the musical formats, there is a mechanism for deducing whether or not tracked music is available. A GSMusicChannel will not play any sound at all if the gestalt selector soundMusic is zero. This is the only difference between a GSMusicChannel and a GSChannel. Both classes are capable of playing any form of Blorb audio. However, in general, if a channel is to be used only for music, one should use a GSMusicChannel, to reduce the possibility of error messages on interpreters not providing music.
The principle of an audio channel is simple; one can play a sound in it. If you attempt to play another sound in a channel before the previous sound stops, the previous sound is interrupted.
You can have as many sound channels as you like. Sounds played in different channels will overlap. The total number of sounds which can be played at the same time will, of course, depend on the player's interpreter, and possibly his sound card.
Sound channels all provide the following properties:
7.3 Audio Effects
A channel may have one or more audio effects attached to it. Audio effects are roughly analagous to GWindows Widgets.
An audio effect has two phases: a before phase and an after phase. It need not make use of both. The before phase is executed before a sound starts playing. The after phase, when it completes. Of course, if sound notifications are unavailable, GSound will not know when to trigger the after-phase, so it will never occur. This is unfortunate, because while before-phase effects are more portable, after-phase are more useful. You install an audio effect on a channel by placing it inside the channel. Effects are run in the order of their lineage.
Here is an example audio effect: Linear Repeat and Fade
with after [ x;
if (parent(self).vol > 0)
The passed parameter is the Blorb sound resource. The before and after routines are additive. Make of this what you will when using classes to define complex effects.
One small note: An audio effect like this assumes that it is called as soon as the sound ends. Unfortunately, this is not always the case. The sound event will only be registered within the game's main event loop (that is, when the game is waiting for the user to type something). Therefore, if the game performs some slow computation, and the sound finishes during this computation, the effect will only be executed after the prompt is displayed an new input solicited from the user.
7.4 The Multichannel
For must purposes, using GSound Channels is really overkill. Often, you will simply want to say "play this sound". The multichannel exits for this purpose. Sounds played on the multichannel will not interrupt each other (unless too many of them are playing at once). You can use the multichannel in tandem with GSound channels, or on its own.
The Multichannel, called GSMultiChannel appears like any other GSound channel, with a few exceptions:
Though the Multichannel is clearly less flexible than normal GSound channels, it is easy to use for the most common purposes. Unlike a GSound channel, if you play a new sound in the MultiChannel while another sound is playing, the older sound will not be stopped (unless the interpreter is unable to play both at the same time).
The Multichannel can play up to the lower of GS_MULTICHAN_MAX and the overall limit of the interpreter sounds at the same time. The default value is 64, which almost certainly more than any Glk interpreter will actually be able to manage.
Whenever you try to play a new sound, GSound will do everything in its power to make sure that sound gets played. This may include cancelling an already-playing sound in the multichannel. If you do not wish to risk cancelling a sound, play it in a GSound channel instead. The Multichannel is designed to play a small number of short audio clips, some of which may overlap. It is not well-suited to, say, background music (Though it is perfectly suitable for, say, a "stinger" -- a short piece of music which plays once in response to some key event, but which may be simultaneous with other sound effects).
7.5 Other GSound Features
GSound defines the global variable GS_ABILITIES, which is a bitmask of the following information (this variable is read-only):
GS_SOUNDOK- Sound is available at all. GSound will do almost nothing if this is not set.
GS_VOLOK- It is possible to adjust the volume.
GS_NTFYOK- Sound notification events are available. GSound will be able to correctly determine when sounds stop playing, and execute after-effects.
GS_MUSOK- Music is available. GSMusicChannels will work.
7.6 Known Issues
At the time of writing, I've totally lost track of what the sound issues are.